1

How to draw a tangent line to a parametrically defined curve in an arbitrary point (plotted with raw gnuplot option)?

The answer given from here well work for monotonically increasing or decreasing function.

The solution for arbitrary point of curve doesn't work.

\documentclass{standalone}
\usepackage{tikz,pgfplots}
% from https://tex.stackexchange.com/a/198046/121799
\usetikzlibrary{intersections}

\makeatletter
\def\parsenode[#1]#2\pgf@nil{%
    \tikzset{label node/.style={#1}}
    \def\nodetext{#2}
}

\tikzset{
    add node at x/.style 2 args={
        name path global=plot line,
        /pgfplots/execute at end plot visualization/.append={
                \begingroup
                \@ifnextchar[{\parsenode}{\parsenode[]}#2\pgf@nil
            \path [name path global = position line #1-1]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [xshift=1pt, name path global = position line #1-2]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) --
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [
                name intersections={
                    of={plot line and position line #1-1},
                    name=left intersection
                },
                name intersections={
                    of={plot line and position line #1-2},
                    name=right intersection
                },
                label node/.append style={pos=1}
            ] (left intersection-1) -- (right intersection-1)
            node [label node]{\nodetext};
            \endgroup
        }
    }
}
\makeatother
\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    axis lines = middle,
    axis line style={-stealth},
   width = 10cm,
   height = 10cm,
   clip=false,
   xmin = -5, xmax = 5,
   ymin = -5, ymax = 5,
   tangent/.style args={at #1 with style #2 and length #3}{
            add node at x={#1}{
                [
                    sloped, 
                    append after command={(\tikzlastnode.west) edge [#2] (\tikzlastnode.east)},
                    minimum width=#3
                ]
            }      
      }
 ]
 \addplot [red,thick,domain=0:5, samples=100, raw gnuplot,
 tangent=at 0 with style {blue,thick} and length 1.5cm,
 tangent=at 2 with style {green,thick} and length 1.5cm,
 tangent=at 4 with style {black,thick} and length 1.5cm
] gnuplot {
    set parametric;
    set samples 1000;   
    set size square;
    plot [0:10] 5*exp(-0.1*t)*cos(2*t), 5*exp(-0.1*t)*sin(2*t);
    };

 \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

2
  • You do get three tangents that seem to be real tangents. Could you perhaps explain what you mean by "The solution for arbitrary point of curve doesn't work."? That is, what is the question?
    – user194703
    Oct 21 '19 at 11:00
  • 1
    Say, I want to do the same as in picture, but for second loop Oct 21 '19 at 11:07
3

I modified the styles to take into account all intersections. This is achieved by adding a "level", which indicates the intersection number (counting from the lowest intersection upwards). For instance, to add the intersections in your example, you need levels 5, 6 and 2, but the level depends on the setup.

\documentclass{standalone}
\usepackage{tikz,pgfplots}
% from https://tex.stackexchange.com/a/198046/121799
\usetikzlibrary{intersections}

\makeatletter
\def\parsenode[#1]#2\pgf@nil{%
    \tikzset{label node/.style={#1}}
    \def\nodetext{#2}
}

\tikzset{
    add node at x/.style n args={3}{
        name path global=plot line,
        /pgfplots/execute at end plot visualization/.append={
                \begingroup
                \@ifnextchar[{\parsenode}{\parsenode[]}#2\pgf@nil
            \path [name path global = position line #1-1]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) to[bend left=0]
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [xshift=1pt, name path global = position line #1-2]
                ({axis cs:#1,0}|-{rel axis cs:0,0}) to[bend left=0]
                ({axis cs:#1,0}|-{rel axis cs:0,1});
            \path [
                name intersections={
                    of={plot line and position line #1-1},
                    name=left intersection,sort by=position line #1-1
                },
                name intersections={
                    of={plot line and position line #1-2},
                    name=right intersection,sort by=position line #1-2
                },
                label node/.append style={pos=1}
            ] (left intersection-#3) -- (right intersection-#3)
            node [label node]{\nodetext};
            \endgroup
        }
    }
}
\makeatother
\begin{document}

\begin{tikzpicture}
  \begin{axis}[
    axis lines = middle,
    axis line style={-stealth},
   width = 10cm,
   height = 10cm,
   clip=false,
   xmin = -5, xmax = 5,
   ymin = -5, ymax = 5,
   tangent/.style args={at #1 with style #2 and length #3 at level #4}{
            add node at x={#1}{
                [
                    sloped, 
                    append after command={(\tikzlastnode.west) edge [#2] (\tikzlastnode.east)},
                    minimum width=#3
                ]
            }{#4}      
      }
 ]
 \addplot [red,thick,domain=0:5, samples=100, raw gnuplot,
 tangent=at 0 with style {blue,thick} and length 1.5cm at level 5,
 tangent=at 1.5 with style {green,thick} and length 1.5cm at level 6,
 tangent=at 3 with style {black,thick} and length 1.5cm at level 2
] gnuplot {
    set parametric;
    set samples 1000;   
    set size square;
    plot [0:10] 5*exp(-0.1*t)*cos(2*t), 5*exp(-0.1*t)*sin(2*t);
    };

 \end{axis}
\end{tikzpicture}
\end{document}

enter image description here

BTW, if you are wondering why I add a straight line with bend left=0: here is why. Otherwise TikZ does not allow one to reliably sort intersections along the straight path.

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.