To answer Creating gears in TikZ, I would use plot
in a foreach loop used into a single path. But it seems that it is impossible…
Here, an example to show my problem:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw
(0,0)
\foreach \myvar in {1,2,3}{
--
plot[domain=0:1] (\myvar-\x,\myvar)
};
\end{tikzpicture}
\end{document}
This document should produce this result:
In fact, it produces following error:
! Package tikz Error: Giving up on this path. Did you forget a semicolon?.
Edit: I add a more complex example to show the problem.
Here, a code without \foreach
:
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw
(0,0)
--
plot[domain=0:120] ({1-cos(3*\x)},{1-sin(\x)})
--
plot[domain=0:120] ({2-cos(3*\x)},{2-sin(2*\x)})
--
plot[domain=0:120] ({3-cos(3*\x)},{3-sin(3*\x)})
;
\end{tikzpicture}
\end{document}
And the result:
And the factorized code with \foreach
(but this code produces the error):
\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\draw[dahsed]
(0,0)
\foreach \myvar in {1,2,3}{
--
plot[domain=0:120] ({\myvar-cos(3*\x)},{\myvar-sin(\myvar*\x)})
};
\end{tikzpicture}
\end{document}
Best Answer
It's a bug.
The
\foreach
that occurs when you do\draw ... \foreach ...
is not the same as the\foreach
that occurs when you do\foreach ... \draw ...
. It's a wrapper around the real\foreach
that sets up some hooks first before calling the real command. The wrapper command is:The hooks,
\pgffor@beginhook
and so on, get called at specific places in the\foreach
code. The important one is what happens at the end of thebeginhook
:\expandafter\tikz@scan@next@command\pgfutil@firstofone
. The practical upshot of this is that it puts the TikZ parser into the right mode for scanning the body of the foreach loop: it is expecting a path construction command. This is what makes\draw (0,0) \foreach \i in {1} { -- (1,0) };
work: when TikZ finally gets to see the-- (1,0)
it is in the right "mode".The plot function works by calling
\foreach
to generate all of the points it will draw a path through. But when the plot function is working, it doesn't want the TikZ parser to be in effect, it wants to do its own stuff. So the\pgffor@beginhook
is completely in the wrong place here because TikZ will now be expecting a path construction command when it starts generating the points for the path, but the plot code isn't ready to hand control back to the parser at that point. What ends up happening is that the parser goes into an infinite loop, but TikZ has a builtin check for these loops and bails out ... eventually.One fix is to blank the hooks before the plot function calls its loops. I don't know how reliable this is - I've not tested it extensively. Here's some code that does that:
This produces the desired result:
As I said, there are probably better fixes but think of this as a plaster until the real fix is implemented.