1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-18 22:41:49 +02:00

fixed the tau typo

This commit is contained in:
Pomax
2020-01-20 15:17:10 +01:00
parent 01fe59110c
commit 92f00778c5
26 changed files with 395 additions and 173 deletions

View File

@@ -1,12 +1,12 @@
# Bézier curves and Catmull-Rom curves
Taking an excursion to different splines, the other common design curve is the [Catmull-Rom spline](https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline). Now, a Catmull-Rom spline is a form of cubic Hermite spline, and as it so happens the cubic Bézier curve is also a cubic Hermite spline, so maybe... maybe we can convert one into the other, and back, with some simple substitutions?
Taking an excursion to different splines, the other common design curve is the [Catmull-Rom spline](https://en.wikipedia.org/wiki/Cubic_Hermite_spline#Catmull.E2.80.93Rom_spline). Now, a Catmull-Rom spline is a form of [cubic Hermite spline](https://en.wikipedia.org/wiki/Cubic_Hermite_spline), and as it so happens the cubic Bézier curve is _also_ a cubic Hermite spline, so maybe... maybe we can convert one into the other, and back, with some simple substitutions?
Unlike Bézier curves, Catmull-Rom splines pass through each point used to define the curve, except the first and last, which makes sense if you read the "natural language" description for how a Catmull-Rom spline works: a Catmull-Rom spline is a curve that, at each point P<sub>x</sub>, has a tangent along the line P<sub>x-1</sub> to P<sub>x+1</sub>. The curve runs from points P<sub>2</sub> to P<sub>n-1</sub>, and has a "tension" that determines how fast the curve passes through each point. The lower the tension, the faster the curve goes through each point, and the bigger its local tangent is.
I'll be showing the conversion to and from Catmull-Rom curves for the tension that the Processing language uses for its Catmull-Rom algorithm.
We start with showing the Catmull-Rom matrix form:
We start with showing the Catmull-Rom matrix form, which looks similar to the Bézier matrix form, with slightly different values in the matrix:
\[
CatmullRom(t) =
@@ -26,8 +26,19 @@ We start with showing the Catmull-Rom matrix form:
\end{bmatrix}
\]
However, there's something funny going on here: the coordinate column matrix looks weird. The reason is that Catmull-Rom curves are actually curve segments that are described by two coordinate points, and two tangents; the curve starts at coordinate V1, and ends at coordinate V2, with the curve "departing" V1 with a tangent vector V'1 and "arriving" at V2 with tangent vector V'2.
However, there's something funny going on here: the coordinate column matrix looks weird. The reason is that Catmull-Rom curves are actually curve segments that are described by two points, and two tangents; the curve leaves a point V1 (if we have four coordinates instead, this is coordinate 2), arriving at a point V2 (coordinate 3), with the curve departing V1 with a tangent vector V'1 (equal to the tangent from coordinate 1 to coordinate 3) and arriving at V2 with tangent vector V'2 (equal to the tangent from coordinate 2 to coordinate 4). So if we want to express this as a matrix form based on four coordinates, we get this representation instead:
This is not particularly useful if we want to draw Catmull-Rom curves in the same way we draw Bézier curves, i.e. by providing four points. However, we can fairly easily go from the former to the latter, but it's going to require some linear algebra, so if you just want to know how to convert between the two coordinate systems: skip the following bit.
But... if you want to know <em>why</em> that conversion works, let's do some maths!
<div className="note">
## Deriving the conversion formulae
In order to convert betwen Catmull-Rom curves and Bézier curves, we need to know two things. Firstly, how to express the Catmull-Rom curve using a "set of four coordinates", rather than a mix of coordinates and tangents, and secondly, how to convert those Catmull-Rom coordinates to and from Bézier form.
So, let's start with the first, where we want to satisfy the following equality:
\[
\begin{bmatrix}
@@ -43,26 +54,13 @@ However, there's something funny going on here: the coordinate column matrix loo
\begin{bmatrix}
P_2 \\ P_3 \\ \frac{P_3 - P_1}{2} \\ \frac{P_4 - P_2}{2}
\end{bmatrix}
\ \Rightarrow \
T
=
\frac{1}{2}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
0 & 0 & 2 & 0 \\
-1 & 0 & 1 & 0 \\
0 & -1 & 0 & 1
\end{bmatrix}
\]
<div className="note">
That is to say, the "point + tangent" vector should be equal to "some mapping matrix <em>T</em> times a normal coordinate vector", such that the
## Where did that 2 come from?
This mapping says that in order to map a Catmull-Rom "point + tangent" vector to something based on an "all coordinates" vector, we need to determine the mapping matrix such that applying <em>T</em> yields P2 as start point, P3 as end point, and two tangents based on the lines between P1 and P3, and P2 nd P4, respectively.
Catmull-Rom splines are based on the concept of tension: the higher the tensions, the shorter the tangents at the departure and arrival points. The basic Catmull-Rom curve arrives and departs with tangents equal to half the distance between the two adjacent points, so that's where that 2 came from.
However, the "real" matrix is this:
Computing <em>T</em> is really more "arranging the numbers":
\[
T
@@ -72,28 +70,67 @@ However, the "real" matrix is this:
\end{bmatrix}
=
\begin{bmatrix}
P_2 \\ P_3 \\ \frac{P_3 - P_1}{2 \cdot τ} \\ \frac{P_4 - P_2}{2 \cdot τ}
P_2 \\ P_3 \\ \frac{P_3 - P_1}{2} \\ \frac{P_4 - P_2}{2}
\end{bmatrix}
\Rightarrow \
T
=
\frac{1}{2}
\begin{bmatrix}
0 \cdot P1 &+ 1 \cdot P2 &+ 0 \cdot P3 &+ 0 \cdot P4 \\
0 \cdot P1 &+ 0 \cdot P2 &+ 1 \cdot P3 &+ 0 \cdot P4 \\
\frac{-1}{2} \cdot P1 &+ 0 \cdot P2 &+ \frac{1}{2} \cdot P3 &+ 0 \cdot P4 \\
0 \cdot P1 & \frac{-1}{2} \cdot P2 &+ 0 \cdot P3 &+ \frac{1}{2} \cdot P4
\end{bmatrix}
=
\begin{bmatrix}
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
\frac{-1}{2} & 0 & \frac{1}{2} & 0 \\
0 & \frac{-1}{2} & 0 & \frac{1}{2}
\end{bmatrix}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
0 & 0 & 2 & 0 \\
\frac{-1}{τ} & 0 & \frac{1}{τ} & 0 \\
0 & \frac{-1}{τ} & 0 & \frac{1}{τ}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
This bakes in the tension factor τ explicitly.
</div>
Plugging this into the "two coordinates and two tangent vectors" matrix form, we get:
Thus:
\[
T
=
\begin{bmatrix}
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
\frac{-1}{2} & 0 & \frac{1}{2} & 0 \\
0 & \frac{-1}{2} & 0 & \frac{1}{2}
\end{bmatrix}
\]
However, we're not <em>quite</em> done, because Catmull-Rom curves have a parameter called "tension", written as τ ("tau"), which is a scaling factor for the tangent vectors: the bigger the tension, the smaller the tangents, and the smaller the tension, the bigger the tangents. As such, the tension factor goes in the denominator for the tangents, and before we continue, let's add that tension factor into both our coordinate vector representation, and mapping matrix <em>T</em>:
\[
\begin{bmatrix}
V_1 \\ V_2 \\ V'_1 \\ V'_2
\end{bmatrix}
=
\begin{bmatrix}
P_2 \\ P_3 \\ \frac{P_3 - P_1}{2τ} \\ \frac{P_4 - P_2}{2τ}
\end{bmatrix}
,\
T
=
\begin{bmatrix}
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
0 & \frac{-1}{2τ} & 0 & \frac{1}{2τ}
\end{bmatrix}
\]
With the mapping matrix properly done, let's rewrite the "point + tangent" Catmull-Rom matrix form to a matrix form in terms of four coordinates, and see what we end up with:
\[
CatmullRom(t)
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
@@ -110,6 +147,252 @@ Plugging this into the "two coordinates and two tangent vectors" matrix form, we
\end{bmatrix}
\]
Replace point/tangent vector with the expression for all-coordinates:
\[
CatmullRom(t)
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
-3 & 3 & -2 & -1 \\
2 & -2 & 1 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
0 & \frac{-1}{2τ} & 0 & \frac{1}{2τ}
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
and merge the matrices:
\[
CatmullRom(t)
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
This looks a lot like the Bézier matrix form, which as we saw in the chapter on Bézier curves, should look like this:
\[
Bézier(t)
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
So, if we want to express a Catmull-Rom curve using a Bézier curve, we'll need to turn this Catmull-Rom bit:
\[
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
Into somthing that looks like this:
\[
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
And the way we do that is with a fairly straight forward bit of matrix rewriting. We start with the equality we need to ensure:
\[
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
=
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
V
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
Then we remove the coordinate vector from both sides without affecting the equality:
\[
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
=
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
V
\]
Then we can "get rid of" the Bézier matrix on the right by left-multiply both with the inverse of the Bézier matrix:
\[
{
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
}^{-1}
\cdot
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
=
{
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
}^{-1}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
V
\]
A matrix times its inverse is the matrix equivalent of 1, and because "something times 1" is the same as "something", so we can just outright remove any matrix/inverse pair:
\[
{
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
}^{-1}
\cdot
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
=
V
\]
And now we're <em>basically</em> done. We just multiply those two matrices and we know what <em>V</em> is:
\[
\begin{bmatrix}
0 & 1 & 0 & 0 \\
\frac{-1}{6τ} & 1 & \frac{1}{6τ} & 0 \\
0 & \frac{1}{6τ} & 1 & \frac{-1}{6τ} \\
0 & 0 & 1 & 0
\end{bmatrix}
=
V
\]
We now have the final piece of our function puzzle. Let's run through each step.
1. Start with the Catmull-Rom function:
\[
CatmullRom(t)
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
-3 & 3 & -2 & -1 \\
2 & -2 & 1 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
V_1 \\ V_2 \\ V'_1 \\ V'_2
\end{bmatrix}
\]
2. rewrite to pure coordinate form:
\[
=
\begin{bmatrix}
@@ -123,35 +406,31 @@ Plugging this into the "two coordinates and two tangent vectors" matrix form, we
2 & -2 & 1 & 1
\end{bmatrix}
\cdot
\left (
\frac{1}{2}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
0 & 0 & 2 & 0 \\
& 0 & τ & 0 \\
0 && 0 & τ
\end{bmatrix}
\right )
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
P_2 \\ P_3 \\ \frac{P_3 - P_1}{2τ} \\ \frac{P_4 - P_2}{2τ}
\end{bmatrix}
\]
3. rewrite for "normal" coordinate vector:
\[
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\frac{1}{2}
\begin{bmatrix}
1 & 0 & 0 & 0 \\
0 & 0 & 1 & 0 \\
-3 & 3 & -2 & -1 \\
2 & -2 & 1 & 1
\end{bmatrix}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
& 0 & τ & 0 \\
& τ-6 & -2(τ-3) & \\
& 4-τ & τ-4 & τ
0 & 1 & 0 & 0 \\
0 & 0 & 1 & 0 \\
\frac{-1}{} & 0 & \frac{1}{2τ} & 0 \\
0 & \frac{-1}{2τ} & 0 & \frac{1}{2τ}
\end{bmatrix}
\cdot
\begin{bmatrix}
@@ -159,25 +438,29 @@ Plugging this into the "two coordinates and two tangent vectors" matrix form, we
\end{bmatrix}
\]
So let's find out which transformation matrix we need in order to convert from Catmull-Rom to Bézier:
4. merge the inner matrices:
\[
=
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\frac{1}{2}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
& 0 & τ & 0 \\
& τ-6 & -2(τ-3) & \\
& 4-τ & τ-4 & τ
0 & 1 & 0 & 0 \\
\frac{-1}{2τ} & 0 & \frac{1}{2τ} & 0 \\
\frac{1}{τ} & \frac{1}{2t} - 3 & 3 - \frac{1}{t} & \frac{-1}{2t} \\
\frac{-1}{2t} & 2 - \frac{1}{2τ} & \frac{1}{2τ} - 2 & \frac{1}{2t}
\end{bmatrix}
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
5. rewrite for Bézier matrix form:
\[
=
\begin{bmatrix}
1 & t & t^2 & t^3
@@ -190,115 +473,11 @@ So let's find out which transformation matrix we need in order to convert from C
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
A
\cdot
\begin{bmatrix}
P_1 \\ P_2 \\ P_3 \\ P_4
\end{bmatrix}
\]
The difference is somewhere in the actual Hermite matrix, since the <em>t</em> and coordinate values are identical, so let's solve that matrix equation:
\[
\frac{1}{2}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
& 0 & τ & 0 \\
& τ-6 & -2(τ-3) & -τ \\
& 4-τ & τ-4 & τ
\end{bmatrix}
=
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
A
\]
We left-multiply both sides by the inverse of the Bézier matrix, to get rid of the Bézier matrix on the right side of the equals sign:
\[
{
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
}^{-1}
\cdot
\frac{1}{2}
\cdot
\begin{bmatrix}
0 & 2 & 0 & 0 \\
& 0 & τ & 0 \\
& τ-6 & -2(τ-3) & -τ \\
& 4-τ & τ-4 & τ
\end{bmatrix}
=
{
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
}^{-1}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
A
\ =\
I \cdot A
\ =\
A
\]
Which gives us:
\[
\frac{1}{6}
\cdot
\begin{bmatrix}
0 & 6 & 0 & 0 \\
& 6 & τ & 0 \\
0 & τ & 0 & -τ \\
0 & 0 & 6 & 0
\end{bmatrix}
=
A
\]
Multiplying this ***A*** with our coordinates will give us a proper Bézier matrix expression again:
\[
\begin{bmatrix}
1 & t & t^2 & t^3
\end{bmatrix}
\cdot
\begin{bmatrix}
1 & 0 & 0 & 0 \\
-3 & 3 & 0 & 0 \\
3 & -6 & 3 & 0 \\
-1 & 3 & -3 & 1
\end{bmatrix}
\cdot
\frac{1}{6}
\cdot
\begin{bmatrix}
0 & 6 & 0 & 0 \\
& 6 & τ & 0 \\
0 & τ & 0 & -τ \\
0 & 0 & 6 & 0
0 & 1 & 0 & 0 \\
\frac{-1}{6τ} & 1 & \frac{1}{6τ} & 0 \\
0 & \frac{1}{6τ} & 1 & \frac{-1}{6τ} \\
0 & 0 & 1 & 0
\end{bmatrix}
\cdot
\begin{bmatrix}
@@ -306,6 +485,8 @@ Multiplying this ***A*** with our coordinates will give us a proper Bézier matr
\end{bmatrix}
\]
6. and transform the coordinates so we have a "pure" Bézier expression:
\[
=
\begin{bmatrix}
@@ -327,7 +508,11 @@ Multiplying this ***A*** with our coordinates will give us a proper Bézier matr
\end{bmatrix}
\]
So a Catmull-Rom to Bézier conversion, based on coordinates, requires turning the Catmull-Rom coordinates on the left into the Bézier coordinates on the right (with τ being our tension factor):
And we're done: we finally know how to convert these two curves!
</div>
If we have a Catmull-Rom curve defined by four coordinates P<sub>1</sub> through P<sub>4</sub>, then we can draw that curve using a Bézier curve that has the vector:
\[
\begin{bmatrix}
@@ -345,7 +530,7 @@ So a Catmull-Rom to Bézier conversion, based on coordinates, requires turning t
\end{bmatrix}_{Bézier}
\]
And the other way around, a Bézier to Catmull-Rom conversion requires turning the Bézier coordinates on the left this time into the Catmull-Rom coordinates on the right. Note that there is no tension this time, because Bézier curves don't have any. Converting from Bézier to Catmull-Rom is simply a default-tension Catmull-Rom curve:
Similarly, if we have a Bézier curve defined by four coordinates P<sub>1</sub> through P<sub>4</sub>, we can draw that using a standard tension Catmull-Rom curve with the following coordinate values:
\[
\begin{bmatrix}
@@ -356,11 +541,27 @@ And the other way around, a Bézier to Catmull-Rom conversion requires turning t
\end{bmatrix}_{Bézier}
\Rightarrow
\begin{bmatrix}
P_4 + 6 \cdot (P_1 - P_2) \\
P_4 + 6(P_1 - P_2) \\
P_1 \\
P_4 \\
P_1 + 6 \cdot (P_4 - P_3)
P_1 + 6(P_4 - P_3)
\end{bmatrix}_{CatmullRom}
\]
Done. We can now draw the curves we want using either Bézier curves or Catmull-Rom splines, the choice mostly being which drawing algorithms we have natively available.
or, if your API requires specifying Catmull-Rom curves using "point + tangent" form:
\[
\begin{bmatrix}
P_1 \\
P_2 \\
P_3 \\
P_4
\end{bmatrix}_{Bézier}
\Rightarrow
\begin{bmatrix}
P_1 \\
P_4 \\
P_4 + 3(P_1 - P_2) \\
P_1 + 3(P_4 - P_3)
\end{bmatrix}_{CatmullRom}
\]