How LaTeX plots edges

In computer science, there are two types of books: Those using TikZ of graphs, and others First one have often harmonious figures such as the following one.

Which begs the question, what's there secret? How to the manage to plot nice edges?

It's like magic. As soon as you know the trick it feels too simple.

You've been warned.

The basic equation

Here start the deception. like most of the plotting tools, TikZ uses cubic Bezier.

You don't know what it is? If you remember your math classes about 2nd degree polynomial (the one with ax2+bx+ca x^2 + b x + c) it's nearly the same. Except that here we will go one step further with a power 3 (that's where"cubic" comes from).

The line will be point fo coordinate (x(t),y(t))(x(t), y(t)) for tt between 00 and 11.

{x(t)=axt3+bxt2+cxt+dxy(t)=ayt3+byt2+cyt+dy\begin{cases} x(t) = a_x t^3 + b_x t^2 + c_x t + d_x \\ y(t) = a_y t^3 + b_y t^2 + c_y t + d_y \end{cases}

Don't worries too much about those equations. The only interesting fact is that we hve 8 parameters (axa_x, aya_y; bxb_x, ..., dyd_y). And instead of manipulate those parameters, we will consiter 4 special points:

The best is to play with those points in the next example. You can try to create the edge from A to B. Having a nice one is not that easy.

Modifying parameters

One of the problems to create edge is the coordinate system.

Placing a point is not super easy. Should it be slightly on the left, right. Are they both aligned?

With TikZ you should not place start/end points by yourself. You're controlling the angle between the center of the nodes and their control points. It's the computer that will ensure the starting point is exactly on the border of the node.

By default, an edge has and angle of 30° between it's control point, and the straight line between the tow nodes.

Controlling this angle has two main advantages:

  1. It's simpler
  2. It allows consistency if you move nodes.

With fixed angles. We now need to define the distance between the starting point and the starting direction.

An interesting would be that plots stay the same when the distance between nodes varies. The edge should have the same shape is the distance between A and B is 1, 10, or 100.

Here is an experiment of two edges. You can move nodes A and B to test different values of dd the distance between them.

You're probably convinced now that having a fixed DD is a bad idea. For nodes close to each over, the edge will do some loops. Whereas proportional distance keep consistent shape while varying the distance. So D=αdD=\alpha \cdot d with α\alpha the number you want sounds a good idea.

But which value for α\alpha? We could pick 11, 12\frac{1}{2}, π\pi, ϕ\phi, or any other random value. But TikZ team had a nice idea for the default:

α=43(112)0.39\alpha=\frac{4}{3}\left(1 - \frac{1}{\sqrt{2}}\right) \approx 0.39. I let you try to see why this value is a bit special.

alpha: 0.1

angle: 30°

You got it?

When the difference between the start and end angle is 90° (so 45° on both side of the edge) you got the best approximation of a circle. You can find the computation of this constant in an blog post from Spencer Mortensen about circle approximation.

That's smart because it's easier to use. Drawing a circle by hand is not that easy. Our eye is good at spotting littl imperfection on the circle. So instead of having to keep in mind this constant, it's the default one.

And if you don't want it? you can change! There is an additional parameter \ell calles looseness such that d=0.39Dd = 0.39 \cdot \ell \cdot D.

So for, =1\ell=1 you have a perfect circle. If you want more looseness, you can increase it up to infinity. And for straighter lines, you can decrease it up to 0, which is a straight line.

looseness: 1

angle: 30°

Self loops

And for edges looping on the same node?

We keep the same parameters, let just modify their values.

You can define the starting angle θout\theta_{out} and the arriving angle θin\theta_{in}. But event easier: just define the angle of the loop θ\theta and then derive θin=θ+15°\theta_{in}=\theta+15° et θout=theta15°\theta_{out}=theta-15°.

Loops need more looseness so we will use =8\ell=8.

But the distance between starting point and ending point is of course very small, because they are on the same node. The proposed solution is to defined a minimal distance dmind_{min}. If the distance dd between those two point is less than dmind_{min}, we will use dmind_{min} instead of dd to compute DD.

Conclusion

Maths of this article are not supper complex. But it's interesting to see that for building nice tool you don't necessarily need fancy math. Sometime choosing a system that is well adapted for the use case, and with nice default configuration can be the best solution.

You can define Bezier cubic curves with 8 numbers, or 4 points. But in that case defining angles θin\theta_{in}, θout\theta_{out}, and looseness \ell is more user friendly.

For fun

Those curves are beautiful 😍 So just for pleasure here are curves with various values of α\alpha. Have fun :)

nb alpha: 10

angle: 30°