11

I am trying to convert handwritten text or handdrawn sketches to TikZ. Usually the thickness of a pen stroke varies when the writer applies more or less pressure to the surface.
I am looking for a short way to map that to TikZ, e.g. this syntax would be awesome:

\draw (1,1) --[2pt] (1,3) --[1pt] (2,3);

To draw a 2pt line from (1,1) to (1,3) and a 1pt line from (1,3) to (2,3).

I know that this:

\draw[line width=2pt] (1,1) -- (1,3);
\draw[line width=2pt] (1,1) -- (1,3);

would work, but it's not very practical for lots and lots of coordinates.

Update:
Thanks to Andrew Staceys answer, I was able to finish the tool, which converts handdrawn Xournal sketches to TikZ code.
If you find it useful for your purposes, you can download the tool on https://github.com/flyser/xoj2tikz and read the announcement here.

Have fun :-)

  • Trait with variable thickness is not exactly what I am looking for, because a decoration can not differentiate between the several points of a path (as far as I know). – Fabian Henze Feb 03 '12 at 21:08
  • Is Andrew's answer to Looking for TikZ flourishes and vignettes more useful? – Ignasi Feb 03 '12 at 21:16
  • I don't to want to make a custom path look like its handwritten, I want to convert a handwritten path to tikz, so unfortunately no ... – Fabian Henze Feb 03 '12 at 21:22
  • My initial thought was to explode the path into components (something I did for Jamie Vicary's knot question), but actually, I think it would be eminently and elegantly possible using to paths. Are all your path segments straight lines? (i'm intrigued by the potential usage of this, would you be willing to share more details of the project?). [Typos etc coutesy of iTiePoh, an all-new iPad application] – Andrew Stacey Feb 04 '12 at 09:28
  • The Project aims to convert Xournal (.xoj) files to tikz, to quickly sketch a diagram or include handwritten text in a LaTeX document (and possibly replace the sketch with "proper" TikZ code later).The Xournal files will be created with a pressure sensitive wacom tablet. – Fabian Henze Feb 04 '12 at 15:58
  • As a xournal-user and devoted TikZ-fanatic, I would be very interested in that. I'm tempted not to answer the question unless you promise to let me use it! (But I'll be virtuous and resist temptation ...) – Andrew Stacey Feb 04 '12 at 17:16
  • Of course you can use it :-) I will clean the script up and upload it in github in a bit. – Fabian Henze Feb 06 '12 at 20:44
  • Ouch, I was lazy. anyway ... I finally published it on github: https://github.com/flyser/xoj2tikz – Fabian Henze Mar 11 '12 at 23:12

2 Answers2

5

TikZ supports \foreach loops, maybe this helps when the lines are created according to a specific pattern. See here, page 504 for further information.

Moreover, \tikzset can save you some typing. It lets you define an own style for using in \draw [mystyle].

\tikzset{lw/.style = {line width=2pt}}
\draw [lw] (1,1) -- (2,2);

But if it really comes to "handdrawn" sketches, you might be better off using a vector graphics program such as Inkscape.

Stefan Pinnow
  • 29,535
phimuemue
  • 780
  • thats a good suggestion, I can save some bytes with that, but the real problem is that I need a new \draw for each part of the line. My current implementation creates a document with 2100 lines of code and 162kbyte, while an implementation ignoring line widths gives me 44 lines of code (admittedly very long ones) and 42kbyte for my sample document. –  Feb 03 '12 at 15:55
5

Here's my first attempt using to paths. The idea is to use the to to break up the path into segments and render each one separately, setting the line width on each one. The problem with this (and I can't see a way around this, but it might not be significant if the line widths don't change too much and the line angles don't change much between segments) is that the path is split into segments which means that they don't join up neatly.

\documentclass{standalone}
%\url{http://tex.stackexchange.com/a/43418/86}
\usepackage{tikz}
\tikzset{
  variable line width/.style={
    every variable line width/.append style={#1},
    to path={%
      \pgfextra{%
        \draw[every variable line width/.try,line width=\pgfkeysvalueof{/tikz/thickness}] (\tikztostart) -- (\tikztotarget);
      }%
      (\tikztotarget)
    },
  },
  thickness/.initial=0.6pt,
  every variable line width/.style={line cap=round, line join=round},
}
\begin{document}
\begin{tikzpicture}
\draw[variable line width={blue}] (1,1) to[thickness=1cm] (1,3) to[thickness=.5cm] (2,3);
\end{tikzpicture}
\end{document}

The variable line width key could be specified on the tikzpicture environment as an every draw/.style={variable line width}. To be able to write to[2pt] then one would have to do some funky stuff with the .unknown key handler (where's Ryan Reich when you need him) which would be possible, but I imagine that these are automatically generated and so I would guess that it would be possible to output syntax somewhat like the above - if not, say so and I can adapt the above to suit.

Here's the output of the (the original version of the) above:

TikZ lines with variable width

Update (2012-02-07): Added an every variable line width style which gets added to every inner path. Anything specified as an argument to the variable line width key gets appended to this for the duration of that path.

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • I can't tell you how amazed I am :-) This works like a charm! However, I changed "variable line width" to "vlw" and "thickness" to "t". Additionally I added every path/.style={line cap=round, line join=round} to my tikzpicture environment to work around the path join issue.

    I was able to achieve an almost perfect match between tikz and xournal with that. Just one little problem: when using \draw[vlw], all other parameters are ignored. I can not say \draw[vlw,blue,opacity=0.5] for example. Any idea how to fix that?

    The to[2pt] syntax would be cool, but not neccessary :-)

    – Fabian Henze Feb 06 '12 at 20:49
  • @Flyser That's because options specified on a path command (such as \draw) are local to that command and (which is important) reset to defaults at the start. So the inner draw, which is doing the actual drawing, isn't picking up the options specified on the outer one. There are several ways around this; I'll put one in in a moment, but what suits best will depend on how much flexibility you want and how much control you have (or want to have) over shaping the input. – Andrew Stacey Feb 07 '12 at 09:34
  • There's possibly the simplest way to pass parameters to the subpaths. Would that suffice? I added the line cap and line join as defaults (these could be overridden by suitable options to the variable line width key). – Andrew Stacey Feb 07 '12 at 09:44
  • This example doesn't work for me. There's a dangling comma at line join=round}, and, after resolving it, I get the error: Paragraph ended before \pgfkeys@addpath was complete. – Richard Apr 11 '12 at 16:49
  • @Richard: The problem wasn't the dangling comma, it was the blank line that followed it. Don't know how that snuck in, but I've removed it now so it should compile okay. – Andrew Stacey Apr 11 '12 at 17:50