Storing and re-using tikz coordinates for position and tangent vectors

The following code

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.11}
\usetikzlibrary{arrows,backgrounds,patterns,shapes.geometric,calc,positioning}
\tikzset{small dot/.style={fill=black,circle,outer sep=8pt,scale=0.25}}

\begin{document}

\begin{tikzpicture}[scale=0.8]
\draw[ultra thin,color=lightgray] (-4,-2) grid (7,5);   % coordinate grid
\draw[<->] (-4.5,0) -- (7.5,0) node[right] {$x$};   % x-axis
\draw[<->] (0,-2.5) -- (0,5.5) node[above] {$y$};   % y-axis

\foreach \x/\xtext in {-4,...,-1,1,2,..., 7}        % x-axis labels
\draw (\x cm,2pt) -- (\x cm,-2pt) node[anchor=north, font=\footnotesize] {$\xtext$};

\foreach \y/\ytext in {-2, -1,1,2,..., 5}           % y-axis labels
\draw (2pt,\y cm) -- (-2pt,\y cm) node[anchor=east, font=\footnotesize] {$\ytext$};

% parametric function alpha(t)
\draw [thick, samples=1000] plot[parametric, domain=0:2*pi, id=spiral] function{t*cos(t),-t*sin(t)};

% points on graph
\foreach \t in {0, 30, ..., 360}
\filldraw ({(\t*3.14/180)*cos(\t)},{-(\t*3.14/180)*sin(\t)}) circle (2pt);

% position vectors
\foreach \t in {0, 30, ..., 360}
\draw[->, color=blue, thin] (0,0) --
({(\t*3.1/180)*cos(\t)},{-(\t*3.1/180)*sin(\t)});

%tangent vectors
\foreach \t in {0, 30, ..., 360}
\draw[->, color=red, dashed, very thin] ({(\t*3.14/180)*cos(\t)},{-(\t*3.14/180)*sin(\t)}) --
+({-(\t*3.14/180)*sin(\t) + cos(\t)}, {-(\t*3.14/180)*cos(\t) - sin(\t)});

\end{tikzpicture}
\end{document}

produces exactly what I need for the moment: I am generating a parametric curve, then drawing position and tangent vectors at various points. I have read through this, this, this, this, this, and this, and, in particular, this answer to a related question was very helpful. I still have a couple questions about doing this more efficiently.

First, is there a way to store coordinates along the curve at various points, then re-use those to create the position and tangent vectors? For example, I'd like to compute and store something like

\foreach \t in {0, 0.5236, ..., 6.28}
\x = {x(t)}
\y = {y(t)}

in an array, where x(t) and y(t) are the position functions. I would then use those stored values to create the position vectors as

\for each (\x, \y) in [position array]
\draw[->, color=blue, thin] (0,0) -- (\x,\y);

Similar, for the velocity vectors, I would compute

\foreach \t in {0, 0.5236, ..., 6.28}
\deltax = {x'(t)}
\deltay = {y'(t)}

and create velocity vectors

\for each (\x, \y) in [position array]
\draw[->, color=blue, thin] (\x,\y) -- + (\deltax, \deltay);

where (\deltax,\deltay) is indexed to match with the appropriate (\x,\y) position vector.

I have read where pgf / tikz stores gnuplot coordinates in a .table file, but I can't figure out how to access them to do this.

Secondly, I discovered that cos(\t) and sin(\t) are using \t in degrees, so I had to manually convert to radians for the magnitude of the vectors. There has to be a better way to do this? The code

\foreach \t in {0, 30, ..., 360}
\draw[->, color=blue, very thin] (0,0) --
({\pgfmathresult*cos(\t)},{-\pgfmathresult*sin(\t)});

does not work.

• \pgfmathresult is used a lot by TikZ itself. You need to store it using, for example, \let\radius=\pgfmathresult before any other TikZ commands. – John Kormylo Jul 19 '15 at 21:00

Here is a solution where:

• (f-\t) is a point on the curve,

• (f'-\t) is the associate tangent vector.

\documentclass[border=5pt]{standalone}
\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
\draw[ultra thin,color=lightgray] (-4,-2) grid (7,5);   % coordinate grid
\draw[<->] (-4.5,0) -- (7.5,0) node[right] {$x$};   % x-axis
\draw[<->] (0,-2.5) -- (0,5.5) node[above] {$y$};   % y-axis

\foreach \x/\xtext in {-4,...,-1,1,2,...,7}        % x-axis labels
\draw (\x,2pt) -- (\x,-2pt) node[anchor=north, font=\footnotesize] {$\xtext$};

\foreach \y/\ytext in {-2, -1,1,2,..., 5}           % y-axis labels
\draw (2pt,\y) -- (-2pt,\y) node[anchor=east, font=\footnotesize] {$\ytext$};

% parametric function alpha(t)
\draw [thick, samples=50,smooth] plot[variable=\t, domain=0:2*pi] ({\t*cos(\t r)},{-\t*sin(\t r)});

% points and tangent
\foreach \t in {0, 30, ..., 360}{
\pgfmathsetmacro\st{sin(\t)}
\pgfmathsetmacro\ct{cos(\t)}
\path
}

% draw points, radii and vectors
\foreach \t in {0,30,...,360}{
\fill (f-\t) circle (2pt);
\draw[->, color=blue, thin] (0,0) -- (f-\t);
\draw[->, color=red, dashed, very thin] (f-\t) -- ++(f'-\t);
}
\end{tikzpicture}
\end{document}

Edit

Here is a variant using TikZ library math and where each point is named by its order number instead of its angle position. \documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\begin{document}
\begin{tikzpicture}
\draw[ultra thin,color=lightgray] (-4,-2) grid (7,5);   % coordinate grid
\draw[<->] (-4.5,0) -- (7.5,0) node[right] {$x$};   % x-axis
\draw[<->] (0,-2.5) -- (0,5.5) node[above] {$y$};   % y-axis

\foreach \x/\xtext in {-4,...,-1,1,2,...,7}        % x-axis labels
\draw (\x,2pt) -- (\x,-2pt) node[anchor=north, font=\footnotesize] {$\xtext$};

\foreach \y/\ytext in {-2, -1,1,2,..., 5}           % y-axis labels
\draw (2pt,\y) -- (-2pt,\y) node[anchor=east, font=\footnotesize] {$\ytext$};

% parametric function alpha(t)
\draw [thick, samples=50,smooth] plot[variable=\t, domain=0:2*pi] ({\t*cos(\t r)},{-\t*sin(\t r)});

% points and tangent
\tikzmath{
integer \c; \c = 0;
for \t in {30,60,...,360}{
\c = \c + 1;
\st = sin(\t);
\ct = cos(\t);
{
\path
};
};
}

% draw points, radii and vectors
\foreach \c in {1,...,12}{
\draw[->, color=blue, thin] (0,0) -- (f-\c);
\draw[->, color=red, dashed, very thin] (f-\c) -- ++(f'-\c);
\path (f-\c) node[text=white,circle,minimum size=8pt,inner sep=0,fill=black,font=\tiny]{\c};
}
\end{tikzpicture}
\end{document}
• Thank you. It was difficult to choose out of all the solutions, as they were all fantastic. I chose this one because I really like the modification of showing the vectors in sequence (I was planning on doing this). At the same time, I believe @moospit's solution may be more of what I was seeking in terms of compactness. I am going to play around with all of the suggestions. – Abbas Jaffary Jul 22 '15 at 17:35

Except for the missing gnuplot file, this works:

\documentclass[border=5pt]{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}
\usetikzlibrary{arrows,backgrounds,patterns,shapes.geometric,calc,positioning}
\tikzset{small dot/.style={fill=black,circle,outer sep=8pt,scale=0.25}}

\begin{document}

\begin{tikzpicture}[scale=0.8]
\draw[ultra thin,color=lightgray] (-4,-2) grid (7,5);   % coordinate grid
\draw[<->] (-4.5,0) -- (7.5,0) node[right] {$x$};   % x-axis
\draw[<->] (0,-2.5) -- (0,5.5) node[above] {$y$};   % y-axis

\foreach \x/\xtext in {-4,...,-1,1,2,..., 7}        % x-axis labels
\draw (\x cm,2pt) -- (\x cm,-2pt) node[anchor=north, font=\footnotesize] {$\xtext$};

\foreach \y/\ytext in {-2, -1,1,2,..., 5}           % y-axis labels
\draw (2pt,\y cm) -- (-2pt,\y cm) node[anchor=east, font=\footnotesize] {$\ytext$};

% parametric function alpha(t)
\draw [thick, samples=1000] plot[parametric, domain=0:2*pi, id=spiral] function{t*cos(t),-t*sin(t)};

% points on graph
\foreach \t in {0, 30, ..., 360}
{\pgfmathparse{\t*3.141592653589793/180}
\filldraw (P\t) circle (2pt);}

% position vectors
\foreach \t in {0, 30, ..., 360}
\draw[->, color=blue, thin] (0,0) -- (P\t);

%tangent vectors
\foreach \t in {0, 30, ..., 360}
\draw[->, color=red, dashed, very thin] (P\t) -- +($(0,0)!1!-90:(P\t) + ({cos(\t)},{-sin(\t)})$);}
\end{tikzpicture}
\end{document}

Here an approach using the evaluate option of the foreach loop. Using this you can create the whole plot in one loop and pre-calculate all needed values.

The coordinates on the plot are saved via coord-\x and can be reused. All the calculations are done via evaluate.

I think the code is quite self-explanatory. If you still got questions, feel free to ask.

\documentclass[tikz, border=6mm]{standalone}

\begin{document}
\begin{tikzpicture}[>=latex]
% Axis
\draw [black!25, thin] (-4,-2) grid (7,5);
\draw [<->] (-4.5,0) -- (7.5,0) node [right] {$x$};
\draw [<->] (0,-2.5) -- (0,5.5) node [above] {$y$};
\foreach \x in {-4,...,-1,1,2,...,7} {
\draw (\x,2pt) -- (\x,-2pt) node [below] {$\x$};
\ifnum\x>-3\ifnum\x<6
\draw (-2pt,\x) -- (2pt,\x) node [left=.25cm] {$\x$};
\fi\fi
}

% Plot
\draw [thick, smooth, domain=0:2*pi] plot ({\x*cos(\x r)}, {-\x*sin(\x r)});
\foreach \x [
evaluate=\x as \rx using \x*pi/180, %
evaluate=\rx as \rsin using \rx*sin(\x), %
evaluate=\rx as \rcos using \rx*cos(\x), %
evaluate=\x as \sin using sin(\x), %
evaluate=\x as \cos using cos(\x)] in {30, 60,...,360} {
\fill (\rcos, -\rsin) circle (2pt) coordinate (coord-\x);
\draw [blue, ->] (0,0) -- (coord-\x);
\draw [red, dashed, ->] (coord-\x) -- +({-\rsin+\cos}, {-\rcos-\sin});
}
\fill [blue] (0,0) circle (2pt);
\end{tikzpicture}
\end{document} Another example using the math library. This illustrates the use of the r operator which is a post-fix operator which converts the preceding number to degrees. Also, points and derivatives are stored as coordinate macros.

\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{math}
\tikzmath{
coordinate \c, \d;
integer \n;
\n = 0;
for \t in {0, pi/6, ..., 2*pi}{
\n = \n + 1;
\a = \t r;
\c{\n} = (\t * cos \a, -\t * sin \a);
\d{\n} = (cos \a - \t * sin \a, -sin \a - \t * cos \a);
};
}
\begin{document}
\begin{tikzpicture}[>=stealth]
\draw [ultra thin, color=lightgray] (-4,-2) grid (7,5);
\draw [<->] (-4.5,0) -- (7.5,0) node[right] {$x$};
\draw [<->] (0,-2.5) -- (0,5.5) node[above] {$y$};
\foreach \x/\xtext in {-4, -3, ..., 7}
\draw (\x,2pt) -- (\x,-2pt) node [anchor=north, font=\footnotesize] {$\xtext$};
\foreach \y/\ytext in {-2, -1, ..., 5}
\draw (2pt,\y) -- (-2pt,\y) node [anchor=east, font=\footnotesize] {$\ytext$};

\draw [thick, samples=250] plot [smooth, domain=0:2*pi, variable=\t]
({\t*cos(\t r)},{-\t*sin(\t r)});
\foreach \i in {2,...,\n}{
\draw [blue, shorten >=2pt, ->] (0, 0) -- (\c{\i});
\draw [red, dashed, ->]  (\c{\i}) -- (\cx{\i}+\dx{\i}, \cy{\i}+\dy{\i});
\fill (\c{\i}) circle [radius=2pt];
}
\end{tikzpicture}
\end{document} 