14

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:

Spiral with position and tangent vectors

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}
\pgfmathparse{rad(\t)}
\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
9

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\radius{rad(\t)}
    \pgfmathsetmacro\st{sin(\t)}
    \pgfmathsetmacro\ct{cos(\t)}
    \path
    ({\radius*\ct},{-\radius*\st}) coordinate (f-\t)
    ({-\radius*\st+\ct},{-\radius*\ct-\st}) coordinate (f'-\t);
  }

  % 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.

enter image description here

\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;
      \radius = rad(\t);
      \st = sin(\t);
      \ct = cos(\t);
      {
        \path
        ({\radius*\ct},{-\radius*\st}) coordinate (f-\c)
        ({-\radius*\st+\ct},{-\radius*\ct-\st}) coordinate (f'-\c);
      };
    };
  }

  % 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
6

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}
        \let\radius=\pgfmathresult
        \coordinate (P\t) at ({\radius*cos(\t)},{-\radius*sin(\t)});
        \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}
4

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}

rendered image

3

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}

enter image description here

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.