# Draw a spline with pgfplots

Is it possible to simplify the code, that is to say not to use three times the command \addplot[] ?

\documentclass[tikz]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pgfplots}
\usepgfplotslibrary{patchplots}

\begin{document}

\begin{tikzpicture}

\begin{axis}[
restrict x to domain=-5:9, xmax=9, xmin=-5,
restrict y to domain=-3:4, ymax=4, ymin=-3,
x=1cm,
y=1cm,
axis x line = middle,
axis y line = middle,
axis line style =ultra thick,
major tick style=black,
grid=both,
major grid style=lightgray,
minor grid style=lightgray,
minor tick num=1,
xtick={-5,...,8},
ytick={-3,...,3},
samples=1000,
>=stealth,
]

patch,
red,
thick,
]
coordinates{
(-4,0) (0,1)(-2,-3) (-0.6,0)
};

patch,
blue,
thick,
]
coordinates{
(0,1) (2,1)(1,2)(1.4,1.8)
};

patch,
green,
patch type=cubic spline,
thick,
]
coordinates{
(2,1) (7,0)(3,0.4)(5,0.1)
};

\node[fill=black,circle,scale=0.4] at (-4,0){};
\node[fill=black,circle,scale=0.4] at (7,0){};

\node[below left] at (axis cs:0,0) {$0$};
\node[below] at (axis cs:9.8,-0.1) {$x$};
\node[left] at (axis cs:-0.1,3.8) {$y$};

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

• You combine three curves. Between them spline functions doesn't work as you expected. If the curve can be one (in the same color), than just merge it into one. – Zarko Nov 14 '15 at 11:30
• You can do it without an \addplot by using a \draw with to[in=<angle>, out=<angle>, looseness=<values>] operations. – Tom Bombadil Nov 14 '15 at 12:55
• @Tom Thank you for your answer. Nevertheless, I find to do too many tests to find the right entry and exit angles, but it might be me who does not know very well do it. Also, I found this in documentation \draw [thick,red](-4,0)..controls(-2,-4)..(-0.5,0)..controls(0,1)..(0,1)..controls(1,2.3)..(2,1)..controls(2.8,0.1)..(7,0); – Fabrice Nov 15 '15 at 11:34
• @Fabrice: Oh right, I always forget about ..controls as I rarely ever use it myself. Is the result you obtain with it satisfactory? If so, please don't hesitate to answer your own question, so that future visitors with a similar problem might profit from it! – Tom Bombadil Nov 15 '15 at 13:02
• @ Tom I posted an answer. Is it possible to see what you do ? Thank you – Fabrice Nov 16 '15 at 9:34

From what I understand, you want to to generate a plot which is "close to" your screenshot, without requiring 100% accuracy. That sounds a lot like "make it smooth and ensure that it interpolates at some key points".

While this can be done using manually computed splines, it is cumbersome as you need to fiddle around with the angles at the intersections.

There is also an automatic solution which consists of two steps: first you generate the plot (on the entire domain, meaning you can use tikz's smoother), second you compute intersections segements and draw them in the desired color. The whole approach works as follows:

\documentclass{standalone}
\usepackage{pgfplots}
\usepgfplotslibrary{fillbetween}
\pgfplotsset{compat=1.12}

\begin{document}

\begin{tikzpicture}

\begin{axis}[
xmax=9, xmin=-5,
ymax=4, ymin=-3,
x=1cm,
y=1cm,
axis x line = middle,
axis y line = middle,
axis line style =ultra thick,
major tick style=black,
grid=both,
major grid style=lightgray,
minor grid style=lightgray,
minor tick num=1,
xtick={-5,...,8},
ytick={-3,...,3},
>=stealth,
clip=false,% <--- otherwise $x$ will be clipped
]

draw=none,% <- this plot is INVISIBLE
tension=0.6,
name path=plot]
coordinates{
(-4,0) (-2,-3) %(-0.6,0)
(0,1) (1,2) %(1.4,1.8)
(2,1)(3,0.4)
(5,0.1) (7,0)
};

\path[name path=cut line] (-4,1) -- (10,1);

\draw[red,ultra thick,
intersection segments={of=plot and cut line,sequence=L1}];

\draw[blue,ultra thick,
intersection segments={of=plot and cut line,sequence=L2}];

\draw[green,ultra thick,
intersection segments={of=plot and cut line,sequence=L3}];

\node[fill=black,circle,scale=0.4] at (-4,0){};
\node[fill=black,circle,scale=0.4] at (7,0){};

\node[below left] at (0,0) {$0$};
\node[below] at (9.8,-0.1) {$x$};
\node[left] at (-0.1,3.8) {$y$};

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

You see that I combined you interpolation points into one \addplot. That plot uses tikz's smooth plot handler which results in a smooth transition and controls the degrees of freedom using some tension parameter. The \addplot has draw=none, name path=plot, i.e. it is remembered only, not drawn.

Then we have \path[name path=cut line] (-4,1) -- (10,1); which defines and names cut line.

Finally, there are three \draw instructions which defines colors for specific intersection segments. The instruction belongs to the fillbetween library shipped with pgfplots. The argument of=plot and cut line computes intersections of these two plots, and sequence allows to select individual items of the result: "L" is the 'th item of the Left argument in of=left and right and "R" is the 'th item of the right one (not used here).

• Just curious: is tension documented? I couldn't find it in the pgfplots manual. I'm interested in how it works. – Chris Chudzicki Nov 15 '15 at 16:31
• Hm. I suppose it is not. And it is a feature of tikz, not of pgfplots. I'll add a reference of it to the pgfplots manual since it should be mentioned, but the ownership is in the pgf manual. – Christian Feuersänger Nov 15 '15 at 21:26
• regarding "interested in how it works": it makes no promises whatsoever. All that I ever understood is "it makes it smooth". It is unrelated to any kind of numerical interpolation scheme, though. I suspect it is more a "pretty graphical tool". – Christian Feuersänger Nov 15 '15 at 21:27
• Ah, thanks. I should have thought to look in tikz manual. The explanation on p672 (in v3.01.a) makes some sense to me: "Sets the factor used by the curve plot handlers to determine the distance of the control points from the points they control." – Chris Chudzicki Nov 15 '15 at 21:36
• @Christan First of all, I admire your work, and I who used PSTricks, I dropped pgfplots to use. Your response is complete and a little sharp, I will look closely. In terms of color, it was only to indicate the use of three times \ addplot, because the curve will be drawn in black. – Fabrice Nov 16 '15 at 9:39

Just for completeness, here's what you could do with to[in=<angle>, out=<angle>, looseness=<value>]. The major downside is that you have to guess and improve the values, so you might need a few iterations until the result is satisfactory.

## Code

\documentclass[tikz]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pgfplots}
\pgfplotsset{compat=1.12}

\begin{document}

\begin{tikzpicture}

\begin{axis}
[   xmin=-4.5,
xmax=7.5,
ymin=-3.5,
ymax=2.5,
x=1cm,
y=1cm,
domain=-4:7,
axis x line = middle,
axis y line = middle,
axis line style =ultra thick,
major tick style=black,
grid=both,
major grid style=lightgray,
minor grid style=lightgray,
minor tick num=1,
xtick={-4,...,7},
ytick={-3,...,2},
samples=100,
>=stealth,
]

\draw[thick, red]
(-4,0)  to[out=-80, in=180, looseness=0.6]
(-2,-3) to[out=0, in=250, looseness=0.4]
(-0.5,0) to[out=70, in=240, looseness=0.8]
(0,1) to[out=60, in=180, looseness=0.7]
(1,2) to[out=0, in=120, looseness=0.8]
(2,1) to[out=300, in=180, looseness=0.5]
(7,0);

\node[fill=black,circle,scale=0.4] at (-4,0){};
\node[fill=black,circle,scale=0.4] at (7,0){};

\node[below left] at (0,0) {$0$};
\node[above left] at (7.5,0) {$x$};
\node[below right] at (0,2.5) {$y$};
\end{axis}
\end{tikzpicture}

\end{document}

## Output

A solution with TikZ and ..controls :

\documentclass[tikz]{standalone}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{pgfplots}
\usepgfplotslibrary{patchplots}

\begin{document}

\begin{tikzpicture}

\draw[step=1.0,lightgray,thin] (-6,-4) grid (9,4);

\draw[ultra thick,->,>=stealth](-6,0)--(9,0);
\draw[ultra thick,->,>=stealth](0,-4)--(0,4);

\draw [thick,red](-4,0)..controls(-2,-4)..(-0.5,0)..controls(0,1)..(0,1)..controls(1,2.31)..(2,1)..controls(3.1,0.2)..(7,0);

\draw [thick](1,0.1)--(1,-0.1);
\draw [thick](-0.1,1)--(0.1,1);

\node[below] at (1,0) {$1$};
\node[left] at (0,1) {$1$};
\node[below left] at (0,0) {$0$};

\node[below] at (8.8,-0.1) {$x$};
\node[left] at (-0.1,3.8) {$y$};

\node[fill=black,circle,scale=0.4] at (-4,0){};
\node[fill=black,circle,scale=0.4] at (7,0){};

\end{tikzpicture}

\end{document}

• @ Tom Thank you a lot. I understand the in or out parameter that indicates the angle which the tangent to the curve with the x-axis, but I do not understand the parameter looseness. – Fabrice Nov 16 '15 at 17:00
• looseness determines how "wide" a curve can be. With a value of 0 it will be just a straight line, just like using (A) --(B). I illustrated the effect of looseness e.g. in [this question](tex.stackexchange.com/questions/69216/increase-the-bending-distance-of-a-to-path-in-tikz/69253#69253) – Tom Bombadil Nov 17 '15 at 14:08