[Tex/LaTex] How does one pick control points to control Bézier curves in TikZ

tikz-pgf

[Note: the system didn't like the word 'you' in my question. It prefers 'one'. Go figure.]

When I first used TikZ, I struggled to draw curves using control points.

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

\begin{document}

\begin{tikzpicture}

  \draw (0,0) .. controls (1,1) and (2,-1) .. (3,0);

\end{tikzpicture}

\end{document}

This works great if I happen to want a curve like this

curve

But if I want a curve like this

curve

I have no idea how to figure out how to substitute for the question marks

  \draw (0,0) .. controls (??,??) and (??,??) .. (3,0);

Note that I know the two images look identical. That is because they are the same image. That's my point.

When I discovered TikZ offered other ways to draw curves, I essentially gave up on Bézier curves altogether.

But in many cases, Bézier curves look nicer and Wikipedia assures me that they can be controlled 'intuitively' by control points which is why they are so popular in drawing computer graphics.

I understand that what Wikipedia probably has in mind is a GUI, where the curves can be controlled more-or-less intuitively by adjusting control points. (I take it this is what I do in GIMP, for example.)

But how can I figure out which control points to specify in order to draw a particular curve without doing it by mere trial-and-error?

Indeed, how can I decide when to draw a curve using this method rather than one of the other curve-drawing methods TikZ provides?

I'm not asking how to calculate precise values. I want to know how to get an intuitive idea of roughly what might be about right. I want to have a sense of when doing it this way rather than some other way might make sense.

Best Answer

The analogy that I've always used is to think of control points as points that "pull the path towards them". In the examples below, control points are drawn using the same color than the corresponding path in which they were used; when there are two control points, the number below the point indicates which one goes first in the code.

enter image description here

The example with the loop is particularly good to explain why I meant with "pull the curve towards them": the path starts in (1,0) then the path is pulled towards (10,2) and then it goes backwards when it is pulled towards (-2,2) and finally it heads towards (7,0). Immediately you can see the loop forming in your head.

The code for the image:

\documentclass[parskip=full]{scrartcl}
\usepackage[margin=2cm,paperheight=40cm]{geometry}
\usepackage{tikz}

\newcommand\DrawControl[3]{
  node[#2,circle,fill=#2,inner sep=2pt,label={above:$#1$},label={[black]below:{\footnotesize#3}}] at #1 {}
}

\pagestyle{empty}

\begin{document}
\centering

One control point:\\
\begin{tikzpicture}[baseline]
\draw[help lines] (0,0) grid (8,5);
\draw[ultra thick] 
  (1,0) 
    .. controls (4,0) .. 
  (7,0) \DrawControl{(4,0)}{black}{};  
\draw[ultra thick,blue] 
  (1,0) 
    .. controls (4,2) .. 
  (7,0) \DrawControl{(4,2)}{blue}{};  
\draw[ultra thick,red] 
  (1,0) 
    .. controls (4,6) .. 
  (7,0) \DrawControl{(4,6)}{red}{};  
\end{tikzpicture}\hfill
\begin{tikzpicture}[baseline]
\draw[help lines] (0,0) grid (8,5);
\draw[ultra thick] 
  (1,0) 
    .. controls (2,0) .. 
  (7,0) \DrawControl{(2,0)}{black}{};  
\draw[ultra thick,blue] 
  (1,0) 
    .. controls (2,2) .. 
  (7,0) \DrawControl{(2,2)}{blue}{};  
\draw[ultra thick,red] 
  (1,0) 
    .. controls (2,6) .. 
  (7,0) \DrawControl{(2,6)}{red}{};  
\end{tikzpicture}

\rule{\textwidth}{2pt}

Two control points:\\
\begin{tikzpicture}[baseline]
\draw[help lines] (0,0) grid (8,3);
\draw[ultra thick,blue] 
  (1,0) 
    .. controls (3,2) and (5,2) .. 
  (7,0) \DrawControl{(3,2)}{blue}{1}\DrawControl{(5,2)}{blue}{2} ;  
\draw[ultra thick,red] 
  (1,0) 
    .. controls (3,4) and (5,4) .. 
  (7,0) \DrawControl{(3,4)}{red}{1}\DrawControl{(5,4)}{red}{2};  
\end{tikzpicture}\hfill
\begin{tikzpicture}[baseline]
\draw[help lines] (0,0) grid (8,3);
\draw[ultra thick,blue] 
  (1,0) 
    .. controls (2,2) and (6,2) .. 
  (7,0) \DrawControl{(2,2)}{blue}{1}\DrawControl{(6,2)}{blue}{2};  
\draw[ultra thick,red] 
  (1,0) 
    .. controls (2,4) and (6,4) .. 
  (7,0) \DrawControl{(2,4)}{red}{1}\DrawControl{(6,4)}{red}{2};  
\end{tikzpicture}

\rule{\textwidth}{2pt}

\vspace{3cm}

\begin{tikzpicture}[baseline]
\draw[help lines] (0,0) grid (8,3);
\draw[overlay,ultra thick,blue] 
  (1,0) 
    .. controls (10,2) and (-2,2) .. 
  (7,0) \DrawControl{(10,2)}{blue}{1}\DrawControl{(-2,2)}{blue}{2};  
\draw[overlay,ultra thick,red] 
  (1,0) 
    .. controls (12,4) and (-4,4) .. 
  (7,0) \DrawControl{(12,4)}{red}{1}\DrawControl{(-4,4)}{red}{2};  
\end{tikzpicture}

\rule{\textwidth}{2pt}

\begin{tikzpicture}[baseline]
\draw[help lines] (0,-2) grid (8,2);
\draw[ultra thick,blue] 
  (1,0) 
    .. controls (3,2) and (5,-2) .. 
  (7,0) \DrawControl{(3,2)}{blue}{1}\DrawControl{(5,-2)}{blue}{2};  
\draw[ultra thick,red] 
  (1,0) 
    .. controls (-1,5) and (8,-5) .. 
  (7,0) \DrawControl{(-1,5)}{red}{1}\DrawControl{(8,-5)}{red}{2};  
\end{tikzpicture}

\rule{\textwidth}{2pt}

\end{document}

With the examples and, hopefully with the help of the "pull towards" analogy, it should become clear that, in order to get a path like the one in your question, you should use two control points with these characteristics:

  • Both control points should have same absolute value for the y-coordinate (given the symmetry with respect to the x-axis). The y-coordinate for the first control point should be positive (to pull the path upwards), whilst the y-coordinate for the second control point should be negative (to pull the path downwards).

  • The distance between the x-coordinates for the initial point and the first control point should be equal to the one between the x-coordinates for the second control point and the final point (given the symmetry with respect to the "middle" point on the path).

So

\draw (0,0) .. controls (??,??) and (??,??) .. (3,0);

will become something like

\draw (0,0) .. controls (1,2) and (2,-2) .. (3,0);