# TikZ: Smooth curve through three points without changing direction

In another question (see here) I was asking about how to put the control points of a curve on the tangent of a specific curve point. While the given answers where helpful for that particular arrangement of points, I would like to have a solution for a more general approach to that problem. It is important to me, that the curve does not change its direction at any given point. Consider the following example:

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

\usepackage{tikz}
\usetikzlibrary{calc,intersections,through}
\tikzset{point/.style={circle,inner sep=0pt,minimum size=3pt,fill=red}}

\begin{document}
\begin{tikzpicture}

\coordinate [label=left:$A$] (A) at (0,0);
\coordinate [label=left:$B$] (B) at (-.2,3);
\coordinate [label=left:$C$] (C) at (-.7,7);

\draw[thin,blue] plot [smooth] coordinates { (A) (B) (C) };

\node[point] at (A) {};
\node[point] at (B) {};
\node[point] at (C) {};

\end{tikzpicture}
\end{document}


This produces a smooth curve through points A, B and C, as you can see here:

However, I want the curve to leave A at an angle of 90 degrees and arrive at C at an angle of -45 degrees, running smoothly through B without changing its direction at any given point. So in this example the curve should always continue to turn to the left. Changing the above \draw statement to this

\draw[thin,green] (A) .. controls +(90:.3)  and +(-85:.2) .. (B) .. controls +(95:.2) and +(-45:.3) .. (C);


produces a curve that is close to what I need.

However, I have to guess about the angle of both control points surrounding B. From the blue plot above I figured that those angles are close to -85 and 95, respectively. But I would rather like to calculate these angles instead of eyeballing them.

So is there a way to determine the input and output angles of a bezier curve through B so that the curve does not change its direction anywhere?

• It is hard to guess what do you mean by "without changing its direction at any given point". Is the tangent direction of the middle point is supposed to be the mean of the starting and the ending directions ?
– Kpym
May 13, 2016 at 19:09
• Consider the following exagerated example: if I'd change the control points around B so that the curve would enter at an angle of -135 and exit at an angle of 45, then the curve would leave A at 90 degrees, make a left turn and then halfway to B change into a right turn. Likewise the curve would leave B at 45 degrees turning right and halfway to C it would turn left. That is not what I want. Basically I want the control points to be on the tangent of point B, so that the curve makes a continuous left-turn through points A, B and C. May 13, 2016 at 21:22
• All in all I guess it boils down to determining the tangent of a given point on a curve and aligning the control points to that tangent. What I need to know is how to calculate the tangent and its angle for any given point on a curve. May 13, 2016 at 21:25
• You want to determine the control points to be on the tangent : but this is by definition of the control points always the case. The question is how do you want to determine the tangent at B based on the tangents and the positions of A and C ? Is the tangent at B depending on the position of B ? If for example the curve leaves A at -45° and arrives at C at -135° and by the way B is very far from A and C, what should be the tangent at B ?
– Kpym
May 14, 2016 at 6:24
• With 3 points you can also fit a circular arc, parabola or inverse parabola (x =ay^2 + by + c). The center of the circle is at the intersection of perpendicular bisectors. For parabolas, do the math. May 14, 2016 at 13:03

Here's an answer to the question using the hobby package from Curve through a sequence of points with Metapost and TikZ.

\documentclass{article}
%\url{https://tex.stackexchange.com/q/309388/86}

\usepackage{tikz}
\usetikzlibrary{calc,intersections,through,hobby}
\tikzset{point/.style={circle,inner sep=0pt,minimum size=3pt,fill=red}}

\begin{document}
\begin{tikzpicture}[use Hobby shortcut]

\coordinate [label=left:$A$] (A) at (0,0);
\coordinate [label=left:$B$] (B) at (-.2,3);
\coordinate [label=left:$C$] (C) at (-.7,7);

\draw[thin,blue] plot [smooth] coordinates { (A) (B) (C) };

\node[point] at (A) {};
\node[point] at (B) {};
\node[point] at (C) {};

\draw[thin,green,out angle=90,in angle=-45] (A) .. (B) .. (C);
\draw[thin,red] (A) .. (B) .. (C);

\end{tikzpicture}
\end{document}


This produces:

I wasn't aware of the issue with coordinates on the curve (as mentioned in the comments). I'll have to have a look into that to see what's going on with that.