Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

To teach myself TikZ, one of the things I've done is recreate interesting graphs/charts/etc. One of my bigger projects is attempting to recreate the xkcd Movie Narrative Charts comic.

Different elements of the chart probably warrant their own question, but my particular question now is how I would draw the lines in the Primer section of the chart (bottom right). I don't know if there's a good way to draw such messy, looping, interwoven paths. My solution as of now is to just use LaTeXDraw. Is that my only option here?

EDIT: I played around with some of the suggestions from the related thread linked in the comments. I liked the example from the TikZ/pgf manual that Jan Hlavacek suggested. I fiddled with the example some and I'm getting there, but some obstacles are still in my way. First, here's an example of a path I created:

enter image description here

Here's code that created the above. What I was aiming for was not quite a 'random' path because I wanted the path to drift in certain directions at different times. I'm sure what I've written is not the most efficient way of doing it (if you have a better way of doing it, I'd appreciate the advice, but it's not my main concern at the moment):

\documentclass{minimal}
\usepackage{tikz}
\begin{document}

\pgfmathsetseed{1}
   \begin{tikzpicture}[x=10pt,y=10pt,ultra thick,baseline,line cap=round]
     \coordinate (current point) at (0,0);
     \coordinate (old velocity) at (0,0);
     \coordinate (new velocity) at (rand,rand);
     \foreach \i in {0,1,...,15}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(1,rand)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
       \draw[black] (0,0) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(1,rand)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
     }
     \foreach \i in {0,1,...,15}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(rand,1)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
     }
     \foreach \i in {0,1,...,5}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(-1,rand)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
     }
     \foreach \i in {0,1,...,5}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(rand,-1)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
     }
     \foreach \i in {0,1,...,15}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(1,rand-.5)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
     }
   \end{tikzpicture}
\end{document}

Aesthetically it's still not there, but I believe all it takes now is some tweaking.

My problem now: I want to create three such paths that intertwine. I tried creating three paths within the foreach loop, but the coordinates of one path screws with the coordinates of another path in the subsequent loop -- I may just be doing something dumb. So, how would I the create image above with 3 intertwining paths instead of 1?

EDIT 2: I was able to get multiple paths working (I had just forgotten to change something after copy-pasting). Here's an example with two paths:

enter image description here

The code for this is below. But again, this is far from ideal, so I'm wondering if there's a better way to accomplish this (or at least make my method more efficient).

\documentclass{minimal}
\usepackage{tikz}
\begin{document}

\pgfmathsetseed{1}
   \begin{tikzpicture}[x=10pt,y=10pt,ultra thick,baseline,line cap=round]
     \coordinate (current point) at (0,0);
     \coordinate (current point2) at (0,10);
     \coordinate (old velocity) at (0,0);
     \coordinate (old velocity2) at (0,10);
     \coordinate (new velocity) at (rand,rand);
     \coordinate (new velocity2) at (rand,rand);
     \foreach \i in {0,1,...,15}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(1,rand)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
       \draw[red] (current point2) 
       .. controls ++([scale=-1]old velocity2) and
                    ++(new velocity2) .. ++(1,rand-.5)
          coordinate (current point2);
       \coordinate (old velocity2) at (new velocity2);
       \coordinate (new velocity2) at (rand,rand);
     }
     \foreach \i in {0,1,...,15}
     {
       \draw[black] (current point) 
       .. controls ++([scale=-1]old velocity) and
                    ++(new velocity) .. ++(rand,1)
          coordinate (current point);
       \coordinate (old velocity) at (new velocity);
       \coordinate (new velocity) at (rand,rand);
       \draw[red] (current point2) 
       .. controls ++([scale=-1]old velocity2) and
                    ++(new velocity2) .. ++(1,rand+.5)
          coordinate (current point2);
       \coordinate (old velocity2) at (new velocity2);
       \coordinate (new velocity2) at (rand,rand);
     }
   \end{tikzpicture}
\end{document}
share|improve this question
4  
Believe it or not this question may be a duplicate: Drawing random paths in TikZ. –  Alan Munn Oct 29 '11 at 0:14
5  
Well, I could definitive help you with the 12 Angry Man chart! –  Martin Scharrer Oct 29 '11 at 0:22
    
@AlanMunn Thanks for pointing that one out! For some reason, 'random path' wasn't one of my many searches before asking this. One thing that may be a little different is that I don't want the paths to be truly random since I want them to each reach a certain distance to the right. EDIT: Jake's answer in that thread may actually help. –  Mike Wierzbicki Oct 29 '11 at 0:43
    
@MikeWierzbicki: Did that question help? If so, we'll close this as a duplicate for housekeeping reasons. If not, could you elaborate on what doesn't work? At the moment, this question has no official answer, but it's not clear if any further action is needed. –  Loop Space Nov 1 '11 at 7:53
1  
Could you post your code that didn't work? Which foreach loop did you put the three paths in? –  Loop Space Nov 2 '11 at 10:10
show 4 more comments

1 Answer

up vote 7 down vote accepted

I'll add this as an anwer, since it won't fit in a comment. The basic idea is to define some path segments, like loops, bumps, figures eight, etc. With the basic rule that they start and end at the same height. Then we can construct a path between two nodes on the same height, by linking these segments together. If we need to bridge a difference in height, we could add a parameter to the shapes to determine the offset in height. By creating more complicated segments and perhaps randomizing their parameters, we can obtain a relatively random looking path, while still having a guarantee that it will start and end at our nodes. A small example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing, calc}
\begin{document}
  \def\dloop#1#2#3{
    \draw[squig] (curr) -- ++(#1,0) arc(-90:270:#2) -- ++(#3,0);
    \coordinate (curr) at ($(curr) + (#1,0) + (#3,0)$);
  }
  \def\dhump#1{
    \pgfmathsetmacro{\absone}{abs(#1)}
    \draw[squig] (curr) .. controls ($(curr) + (.7*\absone,#1)$) .. ++(1.4*\absone,0);
    \coordinate (curr) at ($(curr) + (1.4*\absone,0)$);
  }
  \def\dnor#1{
    \draw[squig] (curr) -- ++(#1,0);
    \coordinate (curr) at ($(curr) +(#1,0)$);
  }
  \begin{tikzpicture}[squig/.style={decorate, decoration={random steps,segment length=2pt,amplitude=.5pt}}]
    \coordinate (curr) at (0,0);
    \node[anchor=east] at (curr) {start};
    \dnor{1}
    \dloop{.2}{.7}{0} \dloop{0}{.77}{.5}
    \dhump{1}
    \dhump{-.5}
    \dhump{2}
    \dnor{.5}
    \dloop{.1}{.5}{0}\dloop{0.05}{.55}{0.08}\dloop{.02}{.48}{.2}
    \dnor{1}
    \node[anchor=west] at (curr) {end};
  \end{tikzpicture}
\end{document}

And the resulting document:

semi-random path

Update: I saw Jake's post in Easy curves in TikZ and that made me think that this could be apllied here to mimic the lines in the xkcd graphic. Sticking with the idea of using path segments the output can be made to look significantly better. The code is as follows:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}
  \def\twirl{(curr) ($(curr)+(.5,.2)$) ($(curr)+(1,.5)$) ($(curr)+(1,1)$) ($(curr)+(0,1.5)$) ($(curr)+(-1,1)$) ($(curr)+(-1.25,0)$)   ($(curr)+(-1,-.5)$) ($(curr)+(0,-1)$) ($(curr)+(1,0)$) ($(curr)+(1.25,0)$)}
  \def\figeight{(curr) ($(curr)+(1,1)$) ($(curr)+(2,1)$) ($(curr)+(2.5,0)$) ($(curr)+(2,-1)$) ($(curr)+(-1,1)$) ($(curr)+(-2,1)$) ($(curr)+(-2.5,0)$) ($(curr)+(-2,-1)$) ($(curr)+(-1,-1)$) ($(curr)+(1,0)$) ($(curr)+(1.25,0)$)}
  \def\nor{(curr) ($(curr)+(1.25,0)$)}
  \def\start{(curr) ($(curr)+(.5,0)$) ($(curr)+(1,.25)$) ($(curr)+(1.5,0)$) ($(curr)+(2,0)$)}
  \def\nushape{(curr) ($(curr)+(.2,.5)$) ($(curr)+(.5,.75)$) ($(curr)+(.8,.5)$) ($(curr)+(1,0)$) ($(curr)+(1.5,-1)$) ($(curr)+(2.5,0)$) ($(curr)+(2.5,1)$) ($(curr)+(2.25,1.2)$) ($(curr)+(2,.5)$) ($(curr)+(2.5,0)$) ($(curr)+(2.75,0)$)}
  \begin{tikzpicture}
    \coordinate (curr) at (0,0);
    \path [draw, rounded corners] node[anchor=east] {start} plot[smooth,tension=1] coordinates {\start} coordinate (curr)
      \foreach \x in {\nushape,\twirl,\nor,\figeight,\twirl,\nor,\figeight,\start}{
        -- plot [smooth, tension=.5] coordinates {\x}
        coordinate (curr)
      } node[anchor=west] {end};

  \end{tikzpicture}
\end{document}

The result then looks like this:

semi random paths using plot

If you were to parameterize the height and add some randomness, You should be able to get relatively close to the xkcd graphic.

share|improve this answer
    
That is excellent. The 'easy curves' post is indeed a big help. I believe what you've given me will do the job. Thanks for your time! –  Mike Wierzbicki Nov 4 '11 at 18:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.