Bezier Curves from the Ground Up (2016)

vismit20001 pts0 comments

Bezier Curves from the Ground Up

Logo<br>Created using Figma

Zerø Wind

Jamie Wong

December 29, 2016

Bezier Curves from the Ground Up

This post is also available in Japanese: 一から学ぶベジェ曲線.

How do you describe a straight line segment? We might think about a line segment<br>in terms of its endpoints. Let&rsquo;s call those endpoints \( P_0 \) and \( P_1<br>\).

P0

P1

To define the line segment rigorously, we might say &ldquo;the set of all points along<br>the line through \( P_0 \) and \( P_1 \) which lie between \( P_0 \) and<br>\( P_1 \)&ldquo;, or perhaps this:

$$<br>L(t) = (1 - t) P_0 + t P_1, 0 \le t \le 1<br>$$

Conveniently, this definition let&rsquo;s us easily find the coordinate of the point<br>any portion of the way along that line segment. The midpoint, for instance, lies<br>at \( L(0.5) \).

P0

P1

L(0.5)

$$<br>L(0.5) = (1 - 0.5) P_0 + 0.5 P_1 = \begin{bmatrix}<br>0.5(P_{0_x} + P_{1_x}) \\<br>0.5(P_{0_y} + P_{1_y})<br>\end{bmatrix}<br>$$

We can, in fact, linearly interpolate to any value we want between the two<br>points, with arbitrary precision. This allows us to do fancier things, like<br>trace the line by having the \( t \) in \( L(t) \) be a function of time.

P0

P1

L(0.5)

If you got this far, you might now be wondering, &ldquo;What does this have to do with<br>curves?&ldquo;. Well, it seems quite intuitive that you can precisely describe a line<br>segment with only two points. How might you go about precisely describing this?

It turns out that this particular kind of curve can be described by only 3<br>points!

P0

P1

P2

This is called a Quadratic Bezier Curve. A line segment, donning a fancier<br>hat, might be called a Linear Bezier Curve. Let&rsquo;s investigate why.

First, let&rsquo;s consider what it looks like when we interpolate between \( P_0 \)<br>and \( P_1 \) while simultaneously interpolating between \( P_1 \) and \(<br>P_2 \).

P0

P1

P2

B0,1(0.00)

B1,2(0.00)

$$<br>\begin{aligned}<br>B_{0,1}(t) = (1 - t) P_0 + t P_1, 0 \le t \le 1 \\<br>B_{1,2}(t) = (1 - t) P_1 + t P_2, 0 \le t \le 1 \\<br>\end{aligned}<br>$$

Now let&rsquo;s linearly interpolate between \( B_{0, 1}(t) \) and \( B_{1, 2}(t)<br>\)…

P0

P1

P2

B0,1,2(0.00)

$$<br>\begin{aligned}<br>B_{0,1,2}(t) = (1 - t) B_{0,1}(t) + t B_{1,2}(t), 0 \le t \le 1 \\<br>\end{aligned}<br>$$

Notice that the equation for \( B_{0, 1, 2}(t) \) looks remarkably similar to<br>the equations for \( B_{0, 1} \) and \( B_{1, 2} \). Let&rsquo;s see what<br>happens when we trace the path of \( B_{0, 1, 2}(t) \).

P0

P1

P2

We get our curve!

P0

P1

P2

Higher Order Bezier Curves

Just as we get a quadratic bezier by interpolating between two linear bezier<br>curves, we get a cubic bezier curve by<br>interpolating between two quadratic bezier<br>curves:

P0

P1

P2

P3

$$<br>\begin{aligned}<br>B_{0,1,2,3}(t) = (1 - t) B_{0,1,2}(t) + t B_{1,2,3}(t), 0 \le t \le 1 \\<br>\end{aligned}<br>$$

P0

P1

P2

P3

You may have a sneaking suspicion at this point that there&rsquo;s a nice recursive<br>definition lurking here. And indeed there is:

$$<br>\begin{aligned}<br>B_{k,...,n}(t) &= (1 - t) B_{k,...,n-1}(t) + t B_{k+1,...,n}(t), 0 \le t \le 1<br>\\<br>B_{i}(t) &= P_{i}<br>\end{aligned}<br>$$

Or, expressed (concisely but inefficiently) in TypeScript, it might look like this:

type Point = [number, number];<br>function B(P: Point[], t: number): Point {<br>if (P.length === 1) return P[0];<br>const left: Point = B(P.slice(0, P.length - 1), t);<br>const right: Point = B(P.slice(1, P.length), t);<br>return [(1 - t) * left[0] + t * right[0],<br>(1 - t) * left[1] + t * right[1]];<br>// Evaluate a cubic spline at t=0.7<br>B([[0.0, 0.0], [0.0, 0.42], [0.58, 1.0], [1.0, 1.0]], 0.7)

Cubic Bezier Curves in Vector Images

As it happens, cubic bezier curves seem to be the right balance between<br>simplicity and accuracy for many purposes. These are the kind of curves you&rsquo;ll<br>most often see in vector editing tools like Figma.

A cubic bezier curve in Figma

You can think of the two filled in circles ●<br>as \( P_0 \) and \( P_3 \), and the two diamonds ◇ as \( P_1 \) and \( P_2 \). These are the fundamental<br>building blocks of more complex curved vector constructions.

Font glyphs are specified in terms of bezier curves in TrueType (.ttf) fonts.

A lower-case "e" in Free Serif Italic<br>shown as a vector<br>network of cubic bezier curves

The Scalable Vector Graphics (.svg) file format uses bezier curves as one of its<br>two curve primitives, which are used extensively in this:

The Cubic<br>Spline Tiger in SVG format.

Cubic Bezier Curves in Animation

While bezier curves have their most obvious uses in representing spacial curves,<br>there&rsquo;s no reason why they can&rsquo;t be used to represented curved relationships<br>between other quantities. For instance, rather than relating \( x \) and \(y<br>\), CSS transition timing functions relate a time ratio with an output<br>value ratio.

Transition timing functions defined by bezier curves

Cubic bezier curves are one of two ways of expressing timing functions in CSS<br>(steps() being the other). The cubic-bezier(x1, y1, x2, y2) notation<br>for CSS timing functions specifies the...

bezier curves rsquo cubic between line

Related Articles