4

I'm trying to do some tricky things, mostly making use of this thread. However, in the following code, I don't understand anymore what's going on:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\usetikzlibrary{calc}

\pgfmathtruncatemacro\nodecount{0}
\begin{tikzpicture}
  \coordinate (P0) at (-6, -0.5);
  \coordinate (P1) at (-3,-1);
  \coordinate (P2) at ( -0,-0.7);
  \coordinate (P3) at ( 3,-1);
  \coordinate (P4) at ( 6, -0.5);
  \coordinate (P5) at ( 6, 0.5);
  \coordinate (P6) at ( 3, 1.1);
  \coordinate (P7) at ( 0, 1.2);
  \coordinate (P8) at (-3, 1.1);
  \coordinate (P9) at (-6, 0.5);
  \foreach \i in {0,...,9}{
    \pgfmathtruncatemacro{\j}{mod(\i+1,10)}
    \coordinate (X\i) at ($(P\i)!0.5!(P\j)$);
  }
  \foreach \i in {0,...,9}{
    \pgfmathtruncatemacro{\j}{mod(\i+1,10)}
    \draw (X\i) .. controls ($(X\i)!0.7!(P\j)$) and ($(X\j)!0.7!(P\j)$) .. (X\j)
          {\foreach \k in {0,...,100} {
              \pgfextra{\pgfmathtruncatemacro\nodecount{\nodecount+1}}
              coordinate[pos=\k/100] (p\nodecount)
            }
          };
          \draw(p59) -- (p850); % crash
  }
\end{tikzpicture}
\end{document}

The idea of the \pgfextra bit is to have it create a counter for the nodes, such that they can later be used more easily to draw things. However, I don't understand when the evaluation of the contents of \pgfextra happens. I would have expected the coordinates to be numbered nicely p0-p1000 - but if you compile the above code, you sill see that it crashes at the indicated line, because the coordinates p59 and p850 don't exist. In fact, all the coordinates are named p1. Why is that, and how can I fix this?

carsten
  • 2,966
  • \foreach has already a counter option with \foreach\x[count=\xi].... Here you have to declare the variable globally. Within a group its value doesn't survive – percusse Feb 05 '17 at 20:20
  • The problem is that I want the p-coodinates to be numbered continuously. Hence, a single foreach counter doesn't really help. At least I wouldn't know how to do it in one for loop... – carsten Feb 05 '17 at 21:00
  • For example you can use \foreach \k[count=\ki start from \nodecount] in {0,...,100} { coordinate[pos=\k/100] (p\ki) }. You don't define 850 anyhow. – percusse Feb 05 '17 at 22:02
  • Tikz uses its own parser, so from \path until the terminating semicolon one cannot use LaTeX, except inside a node or \pgfextra. Note that \foreach is equivalent to \path foreach, etc. OTOH, almost anything dealing with numbers will be passed through \pgfmathparse. – John Kormylo Feb 05 '17 at 23:18

1 Answers1

5

Firstly, move the line

\draw(p59) -- (p850);

outside of its containing loop, as the p850 coordinate won't have been defined at the end of the first iteration of the outer loop (even if the numbering was working correctly).

Secondly as has been pointed out in the comments, \foreach surrounds each iteration in a TeX group, so any local changes inside an iteration are lost. There are a few ways around this, one is to use:

\foreach \k in {0,...,100} {
  \pgfextra{\pgfmathtruncatemacro\nodecount{\nodecount+1}%
    \global\let\nodecount=\nodecount}
  coordinate[pos=\k/100] (p\nodecount)
}

Although you might consider using a count register (i.e., using \newcount\nodecount in the preamble) as it would be more efficient:

\foreach \k in {0,...,100} {
   \pgfextra{\global\advance\nodecount by1}
   coordinate[pos=\k/100] (p\the\nodecount)
} 

Another way would be to simply calculate the \nodecount variable on-the-fly:

\foreach \k [evaluate={\nodecount=int(\i*100+\k);}] in {0,...,100} {
  coordinate[pos=\k/100] (p\nodecount)
}
Mark Wibrow
  • 70,437