5

Let us consider the following code. Why doesn't the part of the path generated by foreach look the same as the unrolled part?

\begin{tikzpicture}[
        edge/.style = {
            draw,
            thick, 
        },
        open/.style = {
            draw, 
            circle, 
            thick, 
            inner sep = 0.09cm, 
        }, 
        closed/.style = {
            open,
            fill,
        }, 
    ]

    \foreach \x in {1, 2, ..., 5} {
        \node[closed] at (\x, 0) (c\x) {};
        \node[open] at (\x + 0.5, 1) (o\x) {};
    }

    \node at (0.25, 0.5) (start) {$\cdots$};
    \node at (6.25, 0.5) (end) {$\cdots$};

    \path[edge] (start.east) foreach \x in {1, 2, 3} {-- (c\x) -- (o\x)}  -- (c4) -- (o4) -- (c5) -- (o5) -- (end.west);
\end{tikzpicture}
  • This has been around a few times in this site. When nodes are connected they are connected on their border. – percusse Dec 17 '16 at 13:29
  • @percusse: But why is there a difference between using foreach or not? – user87690 Dec 17 '16 at 13:30
  • one of them is a contionus path, the other one is from one node to the other separate paths – percusse Dec 17 '16 at 13:31
  • @percusse: Is there a way to build a continuous path with foreach? – user87690 Dec 17 '16 at 13:32
  • Can you add also the result that you want to make it look like ? – percusse Dec 17 '16 at 13:34
7

\foreach adds a group level around the loop body. Therefore, I think, the information that the last point was the open circle node gets lost and TikZ connects the line to the end point of the latest drawn line.

There are many ways to use \foreach here, because the lines are not really connected. Examples:

\path[edge]
  (start.east) -- (c1)
  \foreach \x in {1, 2, ..., 5} {
    (c\x) -- (o\x)
    \ifnum\x<5
      -- (c\the\numexpr\x + 1\relax)
    \fi
  }
  (o5) -- (end.west)
;

or

\path[edge]
  (start.east) -- (c1)
  \foreach \x in {1, 2, ..., 5} {
    (c\x) -- (o\x)
  }
  \foreach \x in {1, 2, ..., 4} {
    (o\x) -- (c\the\numexpr\x + 1\relax)
  }
  (o5) -- (end.west)
;

Result

  • You can also use \draw[thick](start.east) -- (c1) foreach\x [remember=\x as \lastx (initially 1)] in {2,...,5} {(c\lastx) -- (o\lastx)-- (c\x)} (c5) -- (o5) -- (end.west); – percusse Dec 17 '16 at 14:04
  • So we have to explicitly add both the starting node and the ending node to the body of the loop – this is possible with using the \the\numexpr\x + 1\relax syntax I wasn't aware of. Because of the loop body working as a closed interval rather than half-closed, handling the corner cases is more cumbersome. – user87690 Dec 17 '16 at 14:14
  • @user87690 The handling of the corner cases could be simplified by using the names (o0) and (c6) for (start.east) and (end.west). – Heiko Oberdiek Dec 17 '16 at 14:54
0

I have put together the following parametrized variant.

\begin{tikzpicture}[x=1.12cm]
    \def \N {5}

    \foreach \i in {1, ..., \N} {
        \node[closed] (c\i) at (\i + 0.25, -0.5) {};
        \node[open] (o\i) at (\i + 0.75, 0.5) {};
    }
    \path[edge] foreach \i in {1, ..., \N} {
        (\i, 0) -- (c\i) -- (o\i) -- (\i + 1, 0)
    };

    \node[anchor=east] at (1 - 0.1, 0) {${\cdots}$};
    \node[anchor=west] at (\N + 1 + 0.1, 0) {${\cdots}$};
\end{tikzpicture}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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