3

I am trying to draw a curve by calculating every point's position in a \foreach loop (potentially hundreds of points). Since the calculation is quite complex, I use \pgfmathsetmacro multiple times to store intermediate results.

Here is a MWE of what I currently have. It draws the path I want it to, but it is not a continuous path, so I can't easily fill it.

\documentclass{standalone}

\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}

        \foreach \t in {0.0,0.1,...,1}{
            % complex calculation depending on \t here with lots of \pgfmathsetmacro s
            % The values of the pos variables obviously depend on the previous calculations in my actual use case
            \pgfmathsetmacro \posX {\t}
            \pgfmathsetmacro \posY {\t * \t}
            \pgfmathsetmacro \posXNext {\t + 0.1}
            \pgfmathsetmacro \posYNext {(\t + 0.1) * (\t + 0.1)}
            \draw (\posX, \posY) -- (\posXNext, \posYNext);
        }
    \end{tikzpicture}
\end{document}

I can't use the solution suggested here: Draw a path between many nodes using foreach, because of all the \pgfmathsetmacros before the \draw call (or at least I couldn't get it to work).

Here is an image of the result of the MWE and what I would like to achieve:

MWE output goal

If there is a completely different way of doing this, that's ok too.

Thanks.

Nathanael
  • 245

2 Answers2

4

An arguably simpler way is to use plot along with samples at. TikZ parses the coordinates for you.

\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
    \begin{tikzpicture}
        \draw[fill=red!50!white] (0, 0) --
        plot[samples at={0.0,0.1,...,1},variable=\t] 
        ({\t},{\t * \t});
    \end{tikzpicture}
\end{document}

enter image description here

TikZ automatically parses its coordinates, there is no need to use \pgfmathsetmacro. Let's now assume you have a more complex function. Then you could just store its definition in the declaration of a function.

\documentclass[tikz,border=3.14mm]{standalone}
\begin{document}
    \begin{tikzpicture}[declare function={f(\t)=\t*\t-0.1*pow(\t,3)-0.1*\t*exp(-\t*\t);}]
        \draw[fill=red!50!white] (0, 0) --
        plot[samples at={0.0,0.1,...,1},variable=\t] 
        ({\t},{f(\t)});
    \end{tikzpicture}
\end{document}

You may or may not want to add smooth to your function. Note also that there is the option /tikz/parametric which can be found on p. 339 of the pgfmanual version 3.1.1, which invokes gnuplot to plot a parametric function.

  • Thanks for your answer. It definitely looks a lot simpler, but is it possible to add some \pgfmathsetmacros (or smth. like that) which depend on \t? The computation of the actual curve I am drawing is a lot more complex than t^2, too complex to put it in one line and still understand it in a couple of weeks ^^ – Nathanael May 11 '19 at 18:53
  • @Nathanael TikZ parses the coordinates. You can store any complicated function in a function that you declare, e.g. \documentclass[tikz,border=3.14mm]{standalone} \begin{document} \begin{tikzpicture}[declare function={f(\t)=\t*\t-0.1*pow(\t,3)-0.1*\t*exp(-\t*\t);}] \draw[fill=red!50!white] (0, 0) -- plot[samples at={0.0,0.1,...,1},variable=\t] ({\t},{f(\t)}); \end{tikzpicture} \end{document}. –  May 11 '19 at 18:57
  • Didn't know about these functions, still fairly new to tikz/pgf... I guess I could put it all in a function like that, but it's not really as readable anymore. If you are curious, thats my actual code atm: https://pastebin.com/G79ab1xF I would like to keep these "variables". – Nathanael May 11 '19 at 19:08
  • @Nathanael For some reason your link is empty but you can nest functions, i.e. declare two functions f and g and compute f(g(\x)) and declare functions of several variables and so on. I personally find this much more readable than many \pgfmathsetmacros. –  May 11 '19 at 19:11
  • Strange, maybe this one works: https://pastebin.com/nCb5KtJC I guess with nesting it would work, thanks for the elaboration! – Nathanael May 11 '19 at 19:16
  • @Nathanael You could put all this into a \pgfmathdeclarefunction, see section 95 Customizing the Mathematical Engine of the newest version of the pgfmanual. –  May 11 '19 at 19:20
  • That looks very promising. I will look into it the next time I need something like that. At the moment it works as it is. In case you are wondering: https://en.wikipedia.org/wiki/Centripetal_Catmull%E2%80%93Rom_spline , that's what I am drawing (with variable alpha). Thanks again, greatly appreciated! – Nathanael May 11 '19 at 19:29
3

Thanks to the comment by Paul and the post I mentioned in the original question (Draw a path between many nodes using foreach), I found an answer that suits my needs (The bug mentioned in the linked post is probably fixed by now, as I don't need the definition that's mentioned there):

\documentclass{standalone}

\usepackage{tikz}

\begin{document}

    \begin{tikzpicture}
        \draw[fill=red!50!white] (0, 0)
        \foreach \t in {0.0,0.1,...,1}{
            \pgfextra
                % complex calculation depending on \t here with lots of \pgfmathsetmacro s
                \pgfmathsetmacro \x {\t}
                \pgfmathsetmacro \y {\t * \t}
            \endpgfextra
             -- (\x, \y)
        };
    \end{tikzpicture}

\end{document}

Here is the output:

enter image description here

Thanks Paul!

Nathanael
  • 245