4

This question already has an answer here:

I am trying to draw a Bézier curve defined by five control points following the algorithm discussed here.

I generate the points of the curve with a \foreach loop: one point per iteration (also, from the second iteration onwards, I draw a line between the most recently generated point to the previous one.)

I can (implicitly) set the number of points generated by changing the value of the macro \step (see code below.) However, for certain values it works while for others it doesn't., resulting in an incomplete Bézier curve.

The number of iterations performed by \foreach is stored (hopefully correctly) in the counter ni whose value is printed in the image. From this we can see that:

\step expected-ni actual_ni
  0.1          11        10
  0.5          21        20
 0.01         101       101  OK
0.001        1001       993  ???

What is going on? Where did I mess up?

Here is my (not so minimal) example: (It may take a while to compile)

\documentclass{standalone}
\usepackage{tikz}
\usetikzlibrary{calc}
\usepackage{ifthen}
\begin{document}
\begin{tikzpicture}[
  ctrlpoint/.style={%
    draw=#1,
    circle,
    inner sep=0,
    minimum width=1ex,
  },
  ctrlpoint/.default={gray},
  ]
  \def\xmax{10}
  \def\ymax{5}    % Now Copy the same picture for different numbers of Bézier points.
  \newcounter{nc} % Number of Copies: count the Copies of the picture (x-, y-shifted via `scope').
  \newcounter{ni} % Number of Iterations: measure how many times the \foreach loop is evaluated inside each picture.
  \foreach \x/\y/\step in {0/0/1,13/0/0.5,0/6/.2,13/6/.125,0/12/.1111,13/12/.1,0/18/.05,13/18/.02,0/24/0.01,13/24/0.001} 
  {
    \refstepcounter{nc}% Increment number of copies outside `scope'
    \begin{scope}[xshift=\x cm,yshift=-\y cm]
      \node [ctrlpoint] (p0) at (0,0) [label=left:$P_0$] {};
      \node [ctrlpoint] (p1) at (-1,4) [label=120:$P_1$] {};
      \node [ctrlpoint] (p2) at (5,\ymax) [label=above:$P_2$] {};
      \node [ctrlpoint] (p3) at (8,0) [label=right:$P_3$] {};
      \node [ctrlpoint] (p4) at (\xmax,4) [label=right:$P_4$] {};
      \draw [gray] (p0) -- (p1) -- (p2) -- (p3) -- (p4);

      \setcounter{ni}{0}% Reset Number of Iterations at each Copy.

      \foreach \parameter in {0,\step,...,1} { % At each iteration a point belonging to the Bézier curve is generated.
        \refstepcounter{ni}                    % If it is the 2nd time or more, draw a segment from current Bézier-point
        \def\t{\parameter}                     % to the previous one (see end of scope.)
        \path let                              % Each Copy has a different number of generated Bézier points,
        \p0 = (p0),                            % implicitly defined by assignign \step.
        \p1 = (p1),                            % At each iteration the macro \t is redefined overwriting the previous definition.
        \p2 = (p2),
        \p3 = (p3),
        \p4 = (p4),
        \p{01} = ($ (\p0) !\t! (\p1) $),
        \p{12} = ($ (\p1) !\t! (\p2) $),
        \p{23} = ($ (\p2) !\t! (\p3) $),
        \p{34} = ($ (\p3) !\t! (\p4) $)
        in
        coordinate (q0) at (\p{01})
        coordinate (q1) at (\p{12})
        coordinate (q2) at (\p{23})
        coordinate (q3) at (\p{34});

        \path let
        \p0 = (q0),
        \p1 = (q1),
        \p2 = (q2),
        \p3 = (q3),
        \p{01} = ($ (\p0) !\t! (\p1) $),
        \p{12} = ($ (\p1) !\t! (\p2) $),
        \p{23} = ($ (\p2) !\t! (\p3) $)
        in
        coordinate (r0) at (\p{01})
        coordinate (r1) at (\p{12})
        coordinate (r2) at (\p{23});

        \path let
        \p0 = (r0),
        \p1 = (r1),
        \p2 = (r2),
        \p{01} = ($ (\p0) !\t! (\p1) $),
        \p{12} = ($ (\p1) !\t! (\p2) $)
        in
        coordinate (s0) at (\p{01})
        coordinate (s1) at (\p{12});

        \path let
        \p0 = (s0),
        \p1 = (s1),
        \p{01} = ($ (s0) !\t! (s1) $)
        in
        coordinate (t\theni) at (\p{01});
        % \fill [blue] (t\theni) circle (1.5pt);
        \ifthenelse{%
          \theni > 1%
        }{%
          \draw [blue] (t\theni) -- (t\the\numexpr\theni-1);%
        }{}
      }
      \node at (.33*\xmax,.4*\ymax) {Number of Iterations: \textbf{\theni}};
    \end{scope}
  }
\end{tikzpicture}
\end{document}

enter image description here

marked as duplicate by percusse tikz-pgf Feb 7 '15 at 21:39

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • 2
    Imprecise arithmetic tex.stackexchange.com/q/197262/3235 – percusse Jan 8 '15 at 1:07
  • @percusse: Thanks. Could I store the current value of \step in something like pgfmathprintnumber, as suggested in a comment to the linked question? Would it be effective at all? The macro should be redefined at each iteration, too. – Pier Paolo Jan 8 '15 at 1:17
  • 2
    Better multiply the step and the end point with 100 or something and scale it down internally. Or divide the value outside and get the number 1001 outside and use foreach for a known number of times say with \foreach\x{0,...,\pgfmathresult} – percusse Jan 8 '15 at 1:50
  • Grrr.... this yellow dot stuff. Please let me know if you keep this open. – percusse Feb 7 '15 at 21:39

Browse other questions tagged or ask your own question.