Menu

#357 Drawing paths that start at a node using \foreach

v1.0 (example)
open
nobody
foreach (4)
5
2018-12-23
2015-05-14
Norbert Zeh
No

In the following code example, two curves from (a) to (v2) and from (a) to (v3) are created, but a single curve from (a) to (v3) through (v2) should be drawn.

\begin{tikzpicture}
  \coordinate (v1)  at (0,0);
  \coordinate (c21) at (1,0);
  \coordinate (c22) at (2,0);
  \coordinate (v2)  at (2,1);
  \coordinate (c31) at (2,2);
  \coordinate (c32) at (3,2);
  \coordinate (v3)  at (4,2);
  \node[draw,inner sep=0pt,minimum size=6pt,circle] (a) at (v1) {};
  \draw (a) \foreach \i in {2,3} {.. controls (c\i1) and (c\i2) .. (v\i)};
\end{tikzpicture}

The correct path is drawn if the \foreach loop is manually expanded to

\draw (a) .. controls (c21) and (c22) .. (v2) .. controls (c31) and (c32) .. (v3);

The path is also drawn correctly using

\draw (v1) \foreach \i in {2,3} {.. controls (c\i1) and (c\i2) .. (v\i)};

but it is of course not shortened to start only at the node's boundary. This suggests that \foreach gets confused when the starting point of a path is a node rather than a coordinate.

Discussion

  • percusse

    percusse - 2015-05-23

    Hi Norbert,

    This is not a bug. \foreach is designed this way such that at every spin of loop the last known coordinate is restored because \foreach runs in TeX group and at the end of the group the previous state is restored.

    Hence, the expanded version of your loop is not what you wrote but

    \draw (a) .. controls (c21) and (c22) .. (v2) 
          (a) .. controls (c31) and (c32) .. (v3);
    

    In other words it doesn't concatenate the path syntax. It concatenates the paths.

     

    Last edit: Stefan Pinnow 2018-12-23
    • Norbert Zeh

      Norbert Zeh - 2015-05-24

      Well, this would make some sense if the behaviour were consistent between
      starting the path at a node or coordinate. Alas, it is not. When the
      first element of the path is a node, the behaviour is as you describe.
      When the first element is a coordinate, it does what I expected: each path
      segment starts at the last vertex of the previous path segment.

      Cheers,
      Norbert

       

      Last edit: Stefan Pinnow 2018-12-23
  • Stefan Pinnow

    Stefan Pinnow - 2018-12-23
    • labels: --> foreach
    • Description has changed:

    Diff:

    --- old
    +++ new
    @@ -1,4 +1,4 @@
    -In the following code example, two curves from (a) to (v2) and from (a) to (v3) are created, but a single curve from (a) to (v3) through (v2) should be drawn.
    +In the following code example, two curves from `(a)` to `(v2)` and from `(a)` to `(v3)` are created, but a single curve from `(a)` to `(v3)` through `(v2)` should be drawn.
    
         :::LaTeX
         \begin{tikzpicture}
    @@ -13,7 +13,7 @@
           \draw (a) \foreach \i in {2,3} {.. controls (c\i1) and (c\i2) .. (v\i)};
         \end{tikzpicture}
    
    -The correct path is drawn if the \foreach loop is manually expanded to
    +The correct path is drawn if the `\foreach` loop is manually expanded to
    
         :::LaTeX
         \draw (a) .. controls (c21) and (c22) .. (v2) .. controls (c31) and (c32) .. (v3);