59

Suppose I specify some node as occurring at some point on a path. Say for example the node (P) defined on the following path.

\path[draw] (0,9) to[out=-90,in=180] (9,0) node[pos=0.7,circle] (P) {};

I would now like to draw the tangent line at (P) to indicate the slope of the curve at that point.

g.kov
  • 21,864
  • 1
  • 58
  • 95
  • 5
    Is it wise to use the standard definition of the derivative for you? I mean put another invisible node very close to it, say pos=0.695, and draw a line over them and extend the line. – percusse Aug 17 '11 at 11:59
  • No problem, that happens to me a lot. :) – percusse Aug 17 '11 at 12:53

9 Answers9

75

Here's an approach that uses the decorations.markings library to place support coordinates at a specified distance along a path, which can be used to set a local coordinate system at a later time to draw tangents or orthogonal lines.

You specify a tangent point by using tangent=<pos> in your first path. In a later path, you can then set use tangent to set a local coordinate system for that path: (0,0) is the tangent point itself, (1,0) is 1 unit along the tangent line, (0,1) is one unit along the orthogonal line.

You can specify tangent=<pos> multiple times in your original path. You can then specify which tangent point to use for a new path by calling use tangent=<count>, where the tangent points are numbered in the order they were specified in the original path.

Using these styles, the following code

\draw [
    tangent=0.4,
    tangent=0.56
] (0,0)
    to [out=20,in=120] (5,2)
    to [out=-60, in=110] (9,1);
\draw [blue, thick, use tangent] (-3,0) -- (3,0);
\draw [orange, thick, use tangent=2] (-2,0) -- (2,0) (0,0) -- (0,1);

would yield this


Here's the complete code:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\begin{document}

\begin{tikzpicture}[ tangent/.style={ decoration={ markings,% switch on markings mark= at position #1 with { \coordinate (tangent point-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,0pt); \coordinate (tangent unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (1,0pt); \coordinate (tangent orthogonal unit vector-\pgfkeysvalueof{/pgf/decoration/mark info/sequence number}) at (0pt,1); } }, postaction=decorate }, use tangent/.style={ shift=(tangent point-#1), x=(tangent unit vector-#1), y=(tangent orthogonal unit vector-#1) }, use tangent/.default=1 ] \draw [ tangent=0.4, tangent=0.56 ] (0,0) to [out=20,in=120] (5,2) to [out=-60, in=110] (9,1); \draw [blue, thick, use tangent] (-3,0) -- (3,0); \draw [orange, thick, use tangent=2] (-2,0) -- (2,0) (0,0) -- (0,1); \end{tikzpicture} \end{document}

Black Mild
  • 17,569
Jake
  • 232,450
  • 1
    Sweet! I was doing this manually before. – percusse Aug 17 '11 at 13:27
  • The advantage of using the markings library (instead of just putting two points close to each other using pos) is that you actually have a tangential coordinate system at the time the marking is drawn, so it should be somewhat more accurate. – Jake Aug 17 '11 at 13:30
  • Indeed it is a more structured solution than the hack. But do you know by any chance how they(you?) implement the orientation of the coordinate system at the tangent point? – percusse Aug 17 '11 at 13:39
  • 2
    Good question, and it turns out that it's actually not a different approach from the one you mentioned. The decorations.markings library just uses a very short distance (1 sp, which is 1/65536 of a pt) for orienting the coordinate system. – Jake Aug 17 '11 at 13:48
  • How to use this with \coordinate? – AkiRoss Jun 05 '13 at 20:40
  • Oh, I found out: \coordinate [use tangent=2] (B) at (0,0.5) does not seems to work, while \path[use tangent=2, shape=coordinate] (0,0.5) coordinate (A) seems to work. Not sure why... – AkiRoss Jun 05 '13 at 20:54
  • @AkiRoss: \coordinate [use tangent=2] (B) at (0,0.5); works fine for me. Are you maybe using an older version of TikZ (the current one is 2.1)? – Jake Jun 05 '13 at 22:38
  • @Jake, I am using 2.1, too – AkiRoss Jun 06 '13 at 10:38
  • 1
    Very nice. But the code can be realy simpler like this : \tikzset{draw at position/.style 2 args={decoration={markings, mark=at position #1 with {#2} }, postaction=decorate}} and then you can use [draw at position={.5}{\draw[blue] (-1,0)--(1,0);}] – Kpym Dec 03 '14 at 13:36
  • @Kpym: Sure, for some cases that might be all you need. However, for more complicated cases (like http://tex.stackexchange.com/a/107912/2552) I much prefer the syntax that results from using my answer. – Jake Dec 03 '14 at 13:58
  • 3
    I came across one issue using this (very nice!) style: in pgfplots, it doesn't work combined with the smooth style. Explanation of the dimension too large error that occurs is in http://tex.stackexchange.com/questions/170595/tikz-decorations-markings-cause-dimension-too-large; I simply removed the smooth style since I had enough data points anyway. – Geert F Feb 02 '15 at 13:20
  • @GeertF You could simply do the plot twice, once with smooth and once with tangent=...,samples=200,draw=none to get the tangent. If you run the second plot from the x value at which you'd like to draw the tangent, you just put tangent=0 and have the tangent right where you want to have it. –  Jun 23 '18 at 20:08
19

For comparison, this is how one can draw a tangent in Metapost.

Metapost has a notion of time along a path. The first point on a path has time=0, the 2nd point has time=1, and so on. The operator point .. of <path> picks a point at a particular time along a path. The operator direction ... of <path> gives the direction of the curve at that time---which is precisely the tangent of the curve. These two operators can be combined to draw the tangent at any point on a curve.

enter image description here

The code below is in ConTeXt, but it will also work with standalone Metapost or LaTeX + emp or LaTeX + gmp.

\starttext

\startMPpage[offset=3mm]

  % Specify a path
  path p;
  p := (0,0) {dir 20} .. {dir -60} (5,2)  .. {dir 20} (9,1);
  p := p scaled 1cm;

  % Draw the path
  draw p withpen pencircle scaled 1bp withcolor red;

  % Specify a time along the path
  numeric ta; ta := 0.6;

  % Pick the point at that time
  pair a;     a := point ta of p;

  % Draw the point
  fill fullcircle scaled 3bp shifted a;

  % Draw a tangent at a particular point
  path tangent; tangent := (-2cm,0) -- (2cm,0);
  tangent := tangent rotated (angle direction ta of p) shifted a;

  draw tangent withcolor blue;


\stopMPpage


\stoptext
Aditya
  • 62,301
  • Maybe you should add a few words about the whatever operator? I am not a scientist, but metapost ability to deal with equations could be emphasized that way. – sztruks Nov 04 '19 at 17:08
  • @sztruks: But this solution does not use the whatever operator. – Aditya Nov 04 '19 at 18:49
  • Yes, I know, I was thinking about introducing a trick using it, but this is far beyond my skills. – sztruks Nov 04 '19 at 19:34
17

(For further readers). This is my try:

    \begin{tikzpicture}
\draw (-2,7.5) .. controls (5,15.5) and (4,0.5) .. (12.5,7.5)
  node[sloped, inner xsep=20mm, inner ysep=0, fill, pos=0.5, red] (P) {};
\filldraw (P) circle(2pt); 
\end{tikzpicture}

enter image description here

Remark: This trick does not works for predefined curves like ellipse, circle, ... because pos of node doesn't works properly as I know.

  • +1 That's really great, bravo! – AndréC Oct 31 '19 at 19:25
  • @AndréC, Is it really deserve +100 (or any) award? This is just a simple answer. –  Nov 05 '19 at 06:07
  • The question of building tangents is a recurrent one. For example, the same question can be found here: https://tex.stackexchange.com/q/461573/138900 Your answer is remarkable because it is very simple and easy to understand. This is the most important criterion in an answer: simplicity and efficiency. Do a lot with little. You did what no one else before you thought of doing. Congratulations! – AndréC Nov 05 '19 at 06:13
  • Would you have an idea on why this code: \draw [purple, xshift=4cm, yshift=4cm, very thick] plot [smooth, tension=1] coordinates {(0,0) (1.25,-0.10) (2.9, 3.45) (4.2,4.2)} node[sloped,inner xsep=1.5cm,inner ysep=1.5pt, fill,pos=2.12,red] (P) {}; produces a tangent that's horizontal (and centered at 0 instead of 2.12) despite that the curve doesn't have a horizontal tangent at that point? – untreated_paramediensis_karnik Sep 06 '20 at 21:11
  • 1
    @thermomagneticcondensedboson: First pos argument should be between 0 and 1. Secondly, I think node is not able to recognize a curve constructed by coordinate and points. –  Sep 25 '20 at 13:48
  • @AndréC Is there a way to draw the tangent before drawing the curve? I mean below the curve. – berkus Aug 15 '21 at 20:44
  • @berkus I don't understand your question, what do you mean by drawing a tangent under the curve? – AndréC Aug 17 '21 at 05:56
  • @AndréC I mean is there a way to change the draw order. First the red tangent, then the black curve, so the red curve would not overwrite the black line. – berkus Aug 17 '21 at 15:36
  • @berkus I am not sure if this is possible with this solution, I have a doubt about it. It is possible with others. Ask a new question, greater TikZ specialists than me can look into this problem. – AndréC Aug 18 '21 at 16:34
  • @berkus can't you just draw the curve in white, then the tangent in black, then the curve again ? – xounamoun Nov 24 '22 at 20:23
15

Jake's solution is really nice. But if you want to draw a tangent in a plot, let's say, over x=1 you have to guess what position (pos=?) to use. Here is a solution that use /tikz/turn key.

\begin{tikzpicture}
  \draw[domain=0:1] plot (\x,{sqrt(\x)}) {[turn] (-1,0) coordinate(t1) (2,0) coordinate(t2)};
  \draw[domain=1:3] plot (\x,{sqrt(\x)});
  \draw[red] (t1)--(t2);
\end{tikzpicture}

enter image description here

This method has some issues :

  • You can easily use it only with plots (because you have to stop drawing the curve at the given point).
  • There is a bug in [turn] when used with plot combined with some transform (rotate, shift, scale, ...).

So this is not really complete method, but I put it here for the sake of completeness.

Kpym
  • 23,002
10

enter image description here

The following tikz code is a result of a double translation.

\documentclass{article}
\usepackage[utf8]{inputenc}
\usepackage{tikz}

\begin{document}
\definecolor{cff0000}{RGB}{255,0,0}
\definecolor{c0000ff}{RGB}{0,0,255}


\begin{tikzpicture}[y=0.80pt,x=0.80pt,yscale=-1, inner sep=0pt, outer sep=0pt]
\begin{scope}[cm={{0.996,0.0,0.0,0.996,(0.0,0.0)}}]
  \begin{scope}[cm={{1.0,0.0,0.0,1.0,(57.1229,171.308)}}]
    \path[draw=cff0000,line join=round,line cap=round,miter limit=10.04,line
      width=0.803pt] (0.0000,0.0000) .. controls (63.5042,-23.1136) and
      (123.7280,-141.1820) .. (166.7340,-66.6936) .. controls (192.1080,-22.7441)
      and (250.0570,-15.1248) .. (300.1210,-33.3468);
  \end{scope}
  \begin{scope}[cm={{1.0,0.0,0.0,1.0,(57.1229,171.308)}}]
    \path[fill=black] (111.2830,-82.0534) .. controls (111.2830,-84.0025) and
      (109.7030,-85.5826) .. (107.7540,-85.5826) .. controls (105.8050,-85.5826) and
      (104.2250,-84.0025) .. (104.2250,-82.0534) .. controls (104.2250,-80.1043) and
      (105.8050,-78.5242) .. (107.7540,-78.5242) .. controls (109.7030,-78.5242) and
      (111.2830,-80.1043) .. (111.2830,-82.0534) -- cycle;
  \end{scope}
  \begin{scope}[cm={{1.0,0.0,0.0,1.0,(57.1229,171.308)}}]
    \path[draw=c0000ff,line join=round,line cap=round,miter limit=10.04,line
      width=0.401pt] (50.9475,-47.1101) -- (164.5610,-116.9970);
  \end{scope}
\end{scope}

\end{tikzpicture}
\end{document}

It was obtained by means of svg2tikz from the t.svg file, which was built by asy -f svg t.asy command. The source text is a direct line-by-line translation from the MetaPost version (MP code is commented with //), basically a minor syntactic differences, t.asy:

    size(300);
//
//  % Specify a path
//  path p;
    path p;
//  p := (0,0) {dir 20} .. {dir -60} (5,2)  .. {dir 20} (9,1);
    p  = (0,0) {dir( 20)} .. {dir( -60)} (5,2)  .. {dir( 20)} (9,1);
//  p := p scaled 1cm;
    p  = scale(1cm)*p;
//  % Draw the path
//  draw p withpen pencircle scaled 1bp withcolor red;
    draw(p, red+1bp);

//  % Specify a time along the path
//  numeric ta; ta := 0.6;
    real ta=0.6;
//  % Pick the point at that time
//  pair a;     a := point ta of p;
    pair a = point(p, ta);

//  % Draw the point
//  fill fullcircle scaled 3bp shifted a;
    fill(shift(a)*scale(3bp)*unitcircle);
//
//  % Draw a tangent at a particular point
//  path tangent; tangent := (-2cm,0) -- (2cm,0);
    path tangent=(-2cm,0) -- (2cm,0);
//  tangent := tangent rotated (angle direction ta of p) shifted a;
    tangent = shift(a)*rotate(degrees(dir(p,ta)))*tangent;
//
//  draw tangent withcolor blue;
    draw(tangent,blue);
g.kov
  • 21,864
  • 1
  • 58
  • 95
10

With PSTricks.

enter image description here

\documentclass[pstricks,border=3pt]{standalone}
\usepackage{pst-node,pst-plot}

\edef\N{10}
\edef\X(#1){#1/\N*cos(#1)}
\edef\Y(#1){#1/\N*sin(#1)}

\psset{algebraic,plotpoints=100,arrows=->}
\begin{document}
\begin{pspicture}(-3,-3)(3,3)
    \psparametricplot{0}{5 Pi mul}{\X(t)|\Y(t)}
    \curvepnode{13 Pi mul 3 div}{\X(t)|\Y(t)}{P}
    \normalvec(Ptang){Pnorm}
    \psxline[linecolor=red](P){-(Ptang)}{Ptang} 
    \psxline[linecolor=green](P){}{-(Pnorm)}
    \psxline[linecolor=blue](P){}{(Pnorm)}
\end{pspicture}
\end{document}

Tutorial

  1. \documentclass[pstricks,border=3pt]{standalone} is used to get a tight PDF output with an additional border of 3pt (by default border=0.50001bp).
  2. \usepackage{pst-node,pst-plot} is to load pst-node (containing macros pertaining to node operations) and pst-plot (containing macros for ploting).
  3. Parametric representation of a spiral. Using parametric representation is a good practice as it can handle almost everything.

    \edef\N{10}
    \edef\X(#1){#1/\N*cos(#1)}
    \edef\Y(#1){#1/\N*sin(#1)}
    
  4. \psset{algebraic,plotpoints=100,arrows=->} to switch to algebraic parser (as opposed to default one in RPN), change the default plotpoints from 50 to 100 (making the plot smoother), and change the default arrows from - (none) to -> (arrow head at the final end), respectively.

  5. \begin{pspicture}(-3,-3)(3,3)...\end{pspicture} is the canvas specification. It should be intuitive if you have learnt Cartesian coordinate system in the playgroup.
  6. \psparametricplot{0}{5 Pi mul}{\X(t)|\Y(t)} to plot the given spiral from 0 to 5 Pi mul (5π). Irrelevant information: If you want to know how I show the π, use ALT+227 in Windows.
  7. \curvepnode{13 Pi mul 3 div}{\X(t)|\Y(t)}{P} to specify a single point P on the spiral. It is accidentally chosen at t=13/3 π. One important thing to know is \curvepnode gives us an UNIT TANGENT VECTOR called Ptang (derived from <your point name>tang) free of charge. No unit normal vector is given. Is it strange? Please ask the PSTricks maintainers for the reason!
  8. \normalvec(Ptang){Pnorm} is used to rotate the Ptang about the origin 90 degrees counter clockwise. The vector length is kept the same -- in this case the length is 1 unit. But you can use \normalvect for any vector whether it is unit vector or not.
  9. \psxline[linecolor=red](A){<vector expression>}{<another vector expression>} is used to draw a point from A + <vector expression> to A + <another vector expression>. Is it confusing? Let's take one example:

    \psxline[linecolor=red](P){-(Ptang)}{Ptang} 
    

    that represents a line drawn from P+(-Ptang) to P+Ptang. still get confused? Let's consider the next one:

    \psxline[linecolor=green](P){}{-(Pnorm)}
    

    that represents a line drawn from P+(0,0) to P+(-Ptang).

  10. Compile the code with latex-dvips-ps2pdf (much faster) or xelatex (much slower).

For a curve consisting of a list of arbitrary points

The following is the solution for a curve consisting of a list of arbitrary points. Unfortunately, the point through which the tangent and normal lines pass is not on the curve. This problem has been asked here so you can find there whether or not it has be fixed.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pstricks-add}

\begin{document}
\begin{pspicture}[showgrid](6,3)
    \pscurve[curvature=1 1 1](0,0)(1,2)(2,1)(4,2)(6,1)
    \psTangentLine[Tnormal,linecolor=blue](2,1)(4,2)(6,1){3}{0.25}
    \psTangentLine[linecolor=red](2,1)(4,2)(6,1){3}{1}
    \pscircle*[linecolor=green](OCurve){3pt}
\end{pspicture}
\end{document}

enter image description here

10

Update an Asymptote answer (19 March 2022) simple and direct way, both 2D and 3D curves. TikZ considers tangents/normals as decorations; meanwhile Asymptote treat them as true paths.

For 2D curve:

enter image description here

// http://asymptote.ualberta.ca/
unitsize(1cm);
path mypath=(0,0) ..controls (0,0)+5dir(70) and (8,3)+5dir(-120) .. (8,3);
draw(mypath);
real t=.2;
pair P=point(mypath,t);
pair Pt=dir(mypath,t);        // tangent vector at P
pair Pn=rotate(90)*Pt;        // normal vector at P
draw(mypath);
draw(P-2Pt--P+4Pt,red);
draw(P-2Pn--P+2Pn,blue);

dot(P); shipout(bbox(5mm,invisible));

For 3D curve: Note that triple perp(triple v) return a unit vector perpendicular to a given unit vector v.

In the following figure, the tangent line is in red, the normal plane is in green.

enter image description here

// http://asymptote.ualberta.ca/
import three;
unitsize(2cm);
path3 g=(1,0,0)..(0,1,1)..(-1,0,0)..(0,-1,1)..cycle;

real t=.3; triple P=point(g,t); triple Pt=dir(g,t); // the tangent vector at P

triple Pn1=perp(Pt);
triple Pn2=cross(Pt,Pn1); //dot(P+Pn1^^P+Pn2,red); // 2 points on the normal plane at P path3 Pnormal=plane(1.5Pn1,1.7Pn2,P-.8Pn1-.7Pn2); // the normal plane at P

draw(g); draw(P-2Pt--P+3Pt,red);
draw(Pnormal,blue); draw(surface(Pnormal),lightgreen+opacity(.5));

Old answer C.F.G.'s trick is nice! First I modify a bit his trick: [inner ysep=.5pt] to control thickness of tangent, and adding [rotate=90] to get normal segment. Not that with this trick, there is a restriction: both tangent and normal segments must have the same midpoint at underlying point on the curve.

Then I remove this restriction using pic, also with handy option [sloped]. Now drawing tangents and normals seem to be done, except predefined curves like ellipse, circle, .... However, we can use their parameterization expressions, and plot directly ^^

enter image description here

enter image description here

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
% 1st way with node (based on C.F.G's trick)  
\begin{tikzpicture}
\draw (0,0) ..controls +(70:5) and +(-120:5) .. (8,3)
% for tangent
node[sloped,inner xsep=1.5cm,inner ysep=.5pt, fill,pos=.12,red] (P) {}
% for normal (just add [rotate=90])
node[rotate=90,sloped,inner xsep=1.5cm,inner ysep=.5pt,fill,pos=.12,blue] {}
;
\fill (P) circle(2pt) node[above]{P}; 
\end{tikzpicture}

% 2nd way with pic (more handy) \begin{tikzpicture}[tangent/.pic={ \draw (-1.5,0)--(2.5,0); }] \draw (0,0) ..controls +(70:5) and +(-120:5) .. (8,3) coordinate[pos=.87] (Q) % for tangent pic[pos=.87,sloped,cyan,thick]{tangent} % for normal (just add [rotate=90]) pic[pos=.87,sloped,rotate=90,brown,thick]{tangent} ; \fill (Q) circle(2pt) node[above]{Q}; \end{tikzpicture}

\end{document}

Update As AndreC suggested, I make pic named segment with 3 parameters: angle #1 left #2 right #3, where angle 0 is for tangent, angle 90 is for normal, #2 and #3 are for length of segment to 2 endpoints of segment from underlying point on the curve. Option on thickness can be put later when using pic with line width option.

\documentclass[tikz,border=5mm]{standalone}
\begin{document}
\tikzset{pics/segment/.style args=
{angle #1 left #2 right #3}{
code={\draw[rotate=#1] (180:#2)--(0:#3);}}}

\begin{tikzpicture} \def\mecurve{(0,0) ..controls +(60:6) and +(-120:6) .. (8,2)} \draw \mecurve; \foreach \t in {.1,.5,...,1} \path \mecurve % for tangent {angle 0} pic[pos=\t,sloped,cyan,thick] {segment=angle 0 left 2 right 1.5} % for normal {angle 90} pic[pos=\t,sloped,orange,thick] {segment=angle 90 left 1 right 2} node[pos=\t]{$\bullet$}; \end{tikzpicture} \end{document}

enter image description here

As an applicaton, we can mark along curve (may use when the curve has quite small slope).

\foreach \t in {0,.025,...,1}
\path \mecurve 
pic[pos=\t,sloped,orange,line width=1pt]
{segment=angle 90 left 2mm right 2mm};
\end{tikzpicture}

enter image description here

Black Mild
  • 17,569
  • 1
    +1 In this case, why not make the thickness and length of the tangent/normal two optional parameters? – AndréC Nov 01 '19 at 14:48
  • @AndreC: Sure, we can do that! – Black Mild Nov 01 '19 at 15:14
  • 1
    With rotation as the third optional parameter, it will be complete:-) – AndréC Nov 01 '19 at 15:16
  • Nice, but instead of naming the parameters by left and right, I suggest length and thickness (or even width). – AndréC Nov 01 '19 at 20:40
  • thickness is not necessary parameterized, can be put when using pic. Moreover, in segment, then length of segment is #2 + #3 which is easier to control – Black Mild Nov 01 '19 at 20:45
  • The terms left and right are relative to the page as are the above and below options of TikZ. In the case of a tangent, there is no left and right, since it is relative to the curve itself and not to the page. A tangent, on the other hand, has a length and a thickness. – AndréC Nov 01 '19 at 20:53
  • I know left and right is relative, but it is convention in several places in pgfmanual (see page 637 on library decoration.making for example. Note that marking is a kind of pic). If we use length, then there is 2 lengths: one to the left and one to the right. Anyway, if you give full code for segment, I will check and choose the better. – Black Mild Nov 01 '19 at 21:13
  • 1
    In the manual, left and right are always relative to the page as well as above (or up) and below (or down). And this even in decorations-marking. Giving a meaningful vocabulary makes it easier to use an order. But, it's up to you, since you're the one who does it. Everyone can rename these parameters at will. – AndréC Nov 01 '19 at 21:27
  • Would you have an idea on why this code: \draw [purple, xshift=4cm, yshift=4cm, very thick] plot [smooth, tension=1] coordinates {(0,0) (1.25,-0.10) (2.9, 3.45) (4.2,4.2)} node[sloped,inner xsep=1.5cm,inner ysep=1.5pt, fill,pos=2.12,red] (P) {}; produces a tangent that's horizontal (and centered at 0 instead of 2.12) despite that the curve doesn't have a horizontal tangent at that point? – untreated_paramediensis_karnik Sep 06 '20 at 21:10
  • I have just added a crucial update: General solution for tangents and normals of general (2D and 3D) curves with Asymptote. – Black Mild Mar 19 '22 at 09:32
5

My try of using the tzplot package:

enter image description here

\documentclass[tikz]{standalone}

\usepackage{tzplot}

\begin{document}

\begin{tikzpicture} \tzhelplines*(10,4) \tztos"curve"(0,0)out=20,in=120out=-60,in=110; \tztangentat[blue,thick]{curve}{3.6}[2:6] \tztangentat[orange,thick]{curve}{5}[4:6] \tzslopeat[orange,thick,tzextend={0}{1cm}]{curve}{5}{.1pt}[90] \end{tikzpicture}

\end{document}

I. Cho
  • 2,985
3

The spath3 TikZ library (ctan or github) introduced a transform to coordinate system which sets the coordinates so that the origin is at a specified point on a curve and the x-axis points along the tangent at that point.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/25928/86}
\usepackage{tikz}
\usetikzlibrary{spath3}

\begin{document} \begin{tikzpicture} \path[draw,spath/save=curve] (0,9) to[out=-90,in=180] node[pos=0.7,circle,draw] (P) {} (9,0); \draw[spath/transform to={curve}{0.7}] (-3,0) -- (3,0); \end{tikzpicture} \end{document}

Curve with tangent line at arbitrary point

Andrew Stacey
  • 153,724
  • 43
  • 389
  • 751
  • My curiosity: There is not the keyword "tangent" in your code??? – Black Mild Jun 05 '22 at 13:29
  • 1
    @BlackMild I have code that calculates tangents to curves but it's not exposed at a user level (yet), rather it's used in things like this. I guess my thinking was that it's not much use simply calculating a tangent - pretty much everything one wants to do with that calculation starts with a transformation. If you think it would be useful to make the tangent calculation available at the user level then that would be easy enough to do - open an issue on github for it. – Andrew Stacey Jun 05 '22 at 13:34
  • Very nice! I believe you can remove the (P). :-) – frougon Jun 05 '22 at 13:38
  • @frougon Yes, though I was trying to keep the code as similar to that in the question as I could (though I had to adjust the order of the node and the final coordinate to get the node in the right place). – Andrew Stacey Jun 05 '22 at 13:43