An Interactive Guide for Bézier Curves
- Introduction
- Linear Interpolation
- Implementing Linear Interpolation
- Constructing the Quadratic Bézier Curve
- Implementing the Quadratic Bézier Curve
- The Quadratic Bézier Equation
- Optimizing the Quadratic Bézier Curve Implementation
- Constructing the Cubic Bézier Curve
- Implementing the Cubic Bézier Curve
- The Cubic Bézier Equation
- Optimizing the Cubic Bézier Curve Implementation
- Higher Order Bézier Curves
Introduction
Back in the 1960s, computers rapidly evolved and it became more and more apparent to scientists and engineers that the age of computer-aided design (CAD) was beginning to dawn. They quickly figured out how a computer can be used to draw straight lines and circles but for designing more complex shaped real world objects such as airplanes or cars this was not sufficient.
In the car manufacturing industry both aerodynamics and aesthetics are highly important which is why freeform curves are used very frequently. To enable designers to use computers to model cars, multiple car manufacturers started looking into how to best construct freeform curves with a computer.
Pierre Bézier at the French car manufacturer Renault eventually popularized what we know today as Bézier curves in reference to his name. However, Paul de Casteljau, working at the French car manufacturer Citroën, used Bézier curves even before Pierre Bézier but wasn't allowed to publish his work until much later.
Nowadays, Bézier curves are used ubiquitously in computer graphics. The very letters that you are currently reading consist of Bézier curves and many vector graphics editing programs such as Adobe Illustrator or Inkscape use them.
Contrary to what other resources might led you to believe, the math behind Bézier curves isn't actually complicated. This article explains how Bézier curves are geometrically constructed and derives the math to calculate points on curves from it. All you need to be able to follow is basic high school math.
The construction of a Bézier curve always starts with a straight line. The line has a direction in the sense that it starts at the start point, which is indicated below by the blue dot and ends at the end point, indicated below by the green dot. Note that all colored points in the images that follow are interactive. You can grab them and move them around to see how that changes things.
In order to define where the start point and end points are located in space we use a Cartesian coordinate system. That just means that we use two axes, x and y, that are perpendicular to each other. The point where both axes intersect is named the origin. By providing a dimension from the origin along each axis up to the corresponding point we can define where both the start point and the end point resides in space.
Linear Interpolation
The next step in constructing a Bézier curve is to be able to find the coordinates of arbitrary points on the line between the start point and end point. In Mathematics, finding a point between two other points is known as interpolation. If the point is restricted to being on the line between the two points it is called linear interpolation.
Don't worry, the term linear interpolation may sound intimidating but there isn't much behind it, mathematically speaking. To adhere to the naming convention established by Mathematics, we call the point that we want to find the interpolation point. It is highlighted in the image below by the magenta dot. The dimensions that are shown in the below image are the Cartesian coordinates of the interpolation point that we want to find.
In order to find the coordinates of the interpolation point we first have to define where the point should be located. That sounds paradoxical at first until we take a closer look at what is going on.
The coordinates of the start point and end point and the fact that the point must reside on the line between them limits the options of where the interpolation point can be. But there is still one degree of freedom which means that the interpolation point can move on the line towards the start point or towards the end point. You can verify that by dragging the interpolation point in the below image around.
To find the actual coordinates of the interpolation point we need to restrict that remaining degree of freedom and decide where the interpolation point should be. How could we do that?
Well, let's look at what we know so far. We know the coordinates of the start point, the end point and the origin which means that we have three points that we can rely on when formulating where the interpolation point should be.
Using these reference points we could for example say that the interpolation point must be as far away from the start point as it is from the end point. Or we could say that the interpolation point must be twice as far away from the end point as it is from the start point. Both of these descriptions eliminate the remaining degree of freedom of the interpolation point.
Both descriptions only refer to the start point and end point. Irrespective of where the start point and end point are actually located we can always make sure that these descriptions are fulfilled. If we simply say that the length of the line between the start point and the end is 100% we can specify the position of the interpolation point as a percentage based factor relative to the length of the line. The line length is represented by the dimension shown in the below image.
However, mathematically speaking, 100% is a ratio because 100 per cent means 100 parts out of 100 available parts or simply 100 divided by 100. So, calculating the result of the division means it is just 1. For 80% it would mean 80 divided by 100 which is simply 0.8. Instead of using a percentage based description we use a single floating point number from now on.
We can now describe the location of the interpolation point with a single floating point number ranging from 0 to 1. A value of 0 means the interpolation point has the exact same coordinates as the start point. A value of 1 means it has the exact same coordinates as the end point.
That single floating point number is all we need to restrict the remaining degree of freedom of the interpolation point. Traditionally, this value is simply called t by mathematicians and we stick to that naming convention throughout this article. The below image visualizes what the effect of the t value is.
The t value is a ratio that restricts the remaining degree of freedom of the interpolation point and, in addition to the coordinates of the start point and endpoint, is all that is required to enable us to calculate the position of an arbitrary point on the line between the start point and the end point.
Great. So, how do we calculate the actual Cartesian coordinates of the interpolation point using that t value? First of all, we can picture the line that runs from the start point to the end point as a triangle. The mentioned line forms the hypotenuse of the triangle and the catheti are formed by following the x- and y-axis of the Cartesian coordinate system as shown in the image below.
The width and height of that triangle is simply the difference between the coordinates of those two points as described by the equations below.
Similar to picturing the entire line as a triangle we can picture a triangle for which the line running from the start point to the interpolation point forms the hypotenuse. Just like in the triangle above, the catheti are formed by following the x- and y-axis of the Cartesian coordinate system.
Note that changing the t value does not change the angles of the above triangle. Hence, setting the t value to 1 results in a triangle that is congruent with the triangle we constructed above. This means that the t value acts as a scale factor for the entire triangle.
According to the rules of triangle similarity, scaling a triangle with a factor means that each side of the triangle is scaled by that factor. This means we can find the width and height of the scaled triangle by simply multiplying the width and height of the original triangle with the scale factor which gives us the below equations.
By inserting the width and height of the original triangle which we described above, we can expand the equations as shown below.
That way we can now calculate the coordinates of the interpolation point relative to the start point of the line.
If we want to calculate the absolute coordinates of the interpolation point, which just means that the coordinates are relative to the origin of the Cartesian coordinate system, we need to add the coordinates of the start point. Expressed as equations, the result looks as shown below.
Note that the start point coordinates occur twice in the above equations. By applying some basic algebra rules we can change the equations so that those coordinates only occur once. To do so, we first expand the brackets as follows.
Then we change the positions of the individual factors which gives us the following equations.
Finally, by factoring out we end up with the following equations.
Both pairs of highlighted equations yield the same result. For the calculation of the interpolation point coordinates it doesn't matter which one is used. However, the second pair of equations will come in handy at a later point in this article.
Implementing Linear Interpolation
Many software packages already contain a built-in function to calculate the value of a linear interpolation. This function is sometimes called lerp which is a Nerdism that stands for linear interpolation.
If there is no such predefined function available it is trivial to add it yourself. It comes down to turning the equations shown above into code. Because both the x- and the y-coordinate of the interpolation point are calculated using the same equation it is sufficient to add it as a single function.
In JavaScript, that function could look as shown below. The reason for using JavaScript is that this article internally uses that function itself. It should be straight forward to use another programming language to do the same.
In order to calculate a two-dimensional interpolation point we need to call the above function twice. To operate with two-dimensional points more conveniently, we introduce a data structure that contains both the x- and the y-coordinate below.
We can then use this structure as argument for our function that calculates and returns the interpolation point from the start point, end point and t that are passed as argument to the function. Note that we use the more descriptive name ratio instead of just t. Making your code more descriptive helps others and yourself to better understand what the code does.
Constructing the Quadratic Bézier Curve
Now that we know what linear interpolation is and how an interpolation point can be calculated we got everything that we need to know to start the construction of the quadratic Bézier curve. To do so, we draw two straight lines where the end point of one line becomes the start point of the other line as shown by the below image.
The point where both lines are connected is called the control point and it is indicated by a red dot. The name derives from the fact that this point controls the shape and bending direction of the quadratic Bézier curve.
The next step is to create two interpolation points. The first interpolation point is created by linearly interpolating between the start point and the control point while the second interpolation point is created by linearly interpolating between the control point and the end point. Both interpolation points are calculated using the exact same t value.
By using the linear interpolation equations formulated above we get the below equations that are used to calculate the Cartesian coordinates of both interpolation points.
Once both interpolation points have been created they are connected using a straight line as shown by the image below.
Next, we create another interpolation point on the line between the previously created interpolation points. To do so, we again use linear interpolation and the same t value already used to create the other two interpolation points. This means that a single t value is used to define where all three interpolation points are located in space.
The equations for that third interpolation point would therefore look as shown below.
If we now turn that third interpolation point into a brush we see a distinctive shape occurring. That shape is the quadratic Bézier curve.
If we draw the full quadratic Bézier curve it becomes apparent that the line between the first and second interpolation point is always tangential to the quadratic Bézier curve itself.
Once the quadratic Bézier curve is constructed we can remove the scaffolding that was used during its construction. The final quadratic Bézier curve then looks as shown below.
You can now see how the control point influences the shape and bending direction of the quadratic Bézier curve.
This way of constructing a Bézier curve is known as the De Casteljau's algorithm.
Implementing the Quadratic Bézier Curve
At this stage we have what we need to implement the quadratic Bézier curve. We have mathematically formulated how to calculate the first, second and third interpolation point. By using the code to calculate an interpolation point given above we can write a new function that calculates a point on the quadratic Bézier curve as shown below.
However, be aware that there is a more efficient way of implementing quadratic Bézier curves. To get to that implementation we need to do some additional math.
The Quadratic Bézier Equation
The equations given above for the third interpolation point take the coordinates for the first and second interpolation points as input. We also have equations to calculate the coordinates of the first and second interpolation points which take the coordinates of the start point, end point and control point as inputs. By inserting the equations of the first and second interpolation point into the third interpolation point we get new equations as shown below.
Expanding the brackets in those newly formulated equations leads to what is shown below.
If we now combine the terms as shown below we get new equations again.
Finally, we receive equations that calculate the coordinates of points on the quadratic Bézier curve by directly relying on the coordinates of the start point, control point and end point as shown below.
The resulting equations for the x- and y-coordinates are know under the name Bernstein polynomial. The quadratic terms in these equations also explain why this type of Bézier curve has been named the quadratic Bézier curve.
Optimizing the Quadratic Bézier Curve Implementation
The Bernstein polynomial form allows us to directly write a function that calculates points on the quadratic Bézier point that does not rely on other functions. This implementation is a bit more efficient than our original implementation shown above because overall less calculations are necessary to get the result.
Constructing the Cubic Bézier Curve
The next type of Bézier curve starts where the quadratic Bézier curve left of. The construction of the cubic Bézier curve starts with a single quadratic Bézier curve. If you observe the below image carefully you will see that unlike previously the Bézier curve below does not end at the end point but at a second control point.
That is the case because we append another straight line to the second control point which now ends at end point.
Then we create a another interpolation point on that appended line and connect the second interpolation point to that newly created interpolation point with a straight line. Then we create another interpolation point on the previously constructed straight line. At this stage we have constructed two quadratic Bézier curves that both rely on the same t value.
Because we have already formulated the equations to calculate points on quadratic Bézier curves above we can directly formulate the equations for the second level interpolation points as shown below.
Then we connect the second level interpolation points with another straight line as shown below.
On that newly created line we create another interpolation point using the same t value as for all the other interpolation points.
To create that interpolation point, all we need to do is two linear interpolations between the interpolation points resulting from the two quadratic Bézier curves. The equations therefore look as shown below.
If we now turn that newly created interpolation point into a brush we see the distinctive shape of the cubic Bézier curve.
If we draw the entire cubic Bézier curve it is notable that the straight line on which the last interpolation was created is always tangential to the curve.
After the cubic Bézier curve has been created the scaffolding that was used during its construction is no longer needed so we remove it. This leaves the straight lines that connects the start point, control points and the end point.
Typically, applications that offer cubic Bézier curves for drawing don't show the straight line connecting the two control points because there is little benefit in seeing it. Hence, we remove that line in the image below.
Implementing the Cubic Bézier Curve
We have seen while constructing the cubic Bézier curve that it is created by first constructing two quadratic Bézier curves and then creating an interpolation point on the line that connects the points on the two quadratic Bézier curves.
We have already written the code to calculate points on quadratic Bézier curves above. By combining that code with the code necessary to calculate an interpolation point shown above we get the following function to calculate points on the cubic Bézier curve.
However, be aware that there is a more efficient way of implementing cubic Bézier curves. To get to that implementation we need to do some additional math.
The Cubic Bézier Equation
We have formulated the equations that we need to calculate points on the two quadratic Bézier curves above. By inserting these equations into the equations to calculate the point on the cubic Bézier curve that we formulated above we get the equations shown below.
Expanding the brackets in those newly formulated equations leads to what is shown below.
If we now combine the terms as shown below we get new equations again.
Finally, we receive equations that calculate the coordinates of points on the cubic Bézier curve by directly relying on the coordinates of the start point, first and second control point and end point as shown below.
Like the equations to calculate the quadratic Bézier curve these equations are Bernstein polynomials and the cubic terms hint at why the cubic Bézier curve carries the word cubic in its name.
Optimizing the Cubic Bézier Curve Implementation
The Bernstein polynomial form allows us to directly write a function that calculates points on the cubic Bézier point that does not rely on other functions. This implementation is a bit more efficient than our original implementation shown above because overall less calculations are necessary to get the result.
Higher Order Bézier Curves
Now we are familiar with both quadratic and cubic Bézier curves and we could go on with higher-order Bézier curves. Next would be the quartic Bézier Curve with three control points and the quintic Bézier curve with four control points and so on.
Each higher curve adds another control point which means that they allow more and more complex curve shapes. But unfortunately with each higher order curve the computation cost goes up as well. This is the reason why higher-order Bézier curves besides the quadratic and cubic Bézier curves are rarely used.
Instead, it is more common to form complex curve shapes by appending additional quadratic or cubic Bézier curves. But that is a topic for another article.