mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-18 22:41:49 +02:00
sections 1-10
This commit is contained in:
567
components/sections/matrixsplit/content.en-GB.md
Normal file
567
components/sections/matrixsplit/content.en-GB.md
Normal file
@@ -0,0 +1,567 @@
|
||||
# Splitting curves using matrices
|
||||
|
||||
Another way to split curves is to exploit the matrix representation of a Bézier curve. In <a href="#matrix">the section on matrices</a> we saw that we can represent curves as matrix multiplications. Specifically, we saw these two forms for the quadratic, and cubic curves, respectively (using the reversed Bézier coefficients vector for legibility):
|
||||
|
||||
\[
|
||||
B(t) = \begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
and
|
||||
|
||||
\[
|
||||
B(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}
|
||||
\]
|
||||
|
||||
Let's say we want to split the curve at some point `t = z`, forming two new (obviously smaller) Bézier curves. To find the coordinates for these two Bézier curves, we can use the matrix representation and some linear algebra. First, we split out the the actual "point on the curve" information as a new matrix multiplication:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & (z \cdot t) & (z \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
and
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & (z \cdot t) & (z \cdot t)^2 & (z \cdot 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}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2 & t^3
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 & 0\\
|
||||
0 & z & 0 & 0\\
|
||||
0 & 0 & z^2 & 0\\
|
||||
0 & 0 & 0 & z^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}
|
||||
\]
|
||||
|
||||
If we could compact these matrices back to a form **[t values] · [bezier matrix] · [column matrix]**, with the first two staying the same, then that column matrix on the right would be the coordinates of a new Bézier curve that describes the first segment, from `t = 0` to `t = z`. As it turns out, we can do this quite easily, by exploiting some simple rules of linear algebra (and if you don't care about the derivations, just skip to the end of the box for the results!).
|
||||
|
||||
<div className="note">
|
||||
|
||||
## Deriving new hull coordinates
|
||||
|
||||
Deriving the two segments upon splitting a curve takes a few steps, and the higher the curve order, the more work it is, so let's look at the quadratic curve first:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\underset{we\ turn\ this...}{\underbrace{\kern 2.25em Z \cdot M \kern 2.25em}}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\underset{...into\ this...}{\underbrace{ M \cdot M^{-1} \cdot Z \cdot M }}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\underset{...to\ get\ \ this!}{\underbrace{ \kern 1.25em \cdot \kern 1.25em Q \kern 1.25em \cdot \kern 1.25em}}
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
We do this, because [*M · M<sup>-1</sup>*] is the identity matrix (a bit like multiplying something by x/x in calculus. It doesn't do anything to the function, but it does allow you to rewrite it to something that may be easier to work with, or can be broken up differently). Adding that as matrix multiplication has no effect on the total formula, but it does allow us to change the matrix sequence [*something · M*] to a sequence [*M · something*], and that makes a world of difference: if we know what [*M<sup>-1</sup> · Z · M*] is, we can apply that to our coordinates, and be left with a proper matrix representation of a quadratic Bézier curve (which is [*T · M · P*]), with a new set of coordinates that represent the curve from *t = 0* to *t = z*. So let's get computing:
|
||||
|
||||
\[
|
||||
Q = M^{-1} \cdot Z \cdot M =
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
1 & \frac{1}{2} & 0 \\
|
||||
1 & 1 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
Excellent! Now we can form our new quadratic curve:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot M \cdot Q \cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\cdot
|
||||
\left (
|
||||
Q
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\left (
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z - 1)^2 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
***Brilliant***: if we want a subcurve from `t = 0` to `t = z`, we can keep the first coordinate the same (which makes sense), our control point becomes a z-ratio mixture of the original control point and the start point, and the new end point is a mixture that looks oddly similar to a bernstein polynomial of degree two, except it uses (z-1) rather than (1-z)... These new coordinates are actually really easy to compute directly!
|
||||
|
||||
Of course, that's only one of the two curves. Getting the section from `t = z` to `t = 1` requires doing this again. We first observe what what we just did is actually evaluate the general interval [0,`z`], which we wrote down simplified becuase of that zero, but we actually evaluated this:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & ( 0 + z \cdot t) & ( 0 + z \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
If we want the interval [*z*,1], we will be evaluating this instead:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & ( z + (1-z) \cdot t) & ( z + (1-z) \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & z & z^2 \\
|
||||
0 & 1-z & 2 \cdot z \cdot (1-z) \\
|
||||
0 & 0 & (1-z)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
We're going to do the same trick, to turn `[something · M]` into `[M · something]`:
|
||||
|
||||
\[
|
||||
Q' = M^{-1} \cdot Z' \cdot M =
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
1 & \frac{1}{2} & 0 \\
|
||||
1 & 1 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & z & z^2 \\
|
||||
0 & 1-z & 2 \cdot z \cdot (1-z) \\
|
||||
0 & 0 & (1-z)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
So, our final second curve looks like:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot M \cdot Q \cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\cdot
|
||||
\left (
|
||||
Q'
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\left (
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]
|
||||
|
||||
\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z \cdot P_3 - (z-1) \cdot P_2 \\
|
||||
P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
***Nice***: we see the same as before; can keep the last coordinate the same (which makes sense), our control point becomes a z-ratio mixture of the original control point and the end point, and the new start point is a mixture that looks oddly similar to a bernstein polynomial of degree two, except it uses (z-1) rather than (1-z). These new coordinates are *also* really easy to compute directly!
|
||||
|
||||
</div>
|
||||
|
||||
So, using linear algebra rather than de Casteljau's algorithm, we have determined that for any quadratic curve split at some value `t = z`, we get two subcurves that are described as Bézier curves with simple-to-derive coordinates.
|
||||
|
||||
\[
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z - 1)^2 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
and
|
||||
|
||||
\[
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z \cdot P_3 - (z-1) \cdot P_2 \\
|
||||
P_3
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
We can do the same for cubic curves. However, I'll spare you the actual derivation (don't let that stop you from writing that out yourself, though) and simply show you the resulting new coordinate sets:
|
||||
|
||||
\[
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 & 0 \\
|
||||
-(z-1) & z & 0 & 0 \\
|
||||
(z-1)^2 & -2 \cdot (z-1) \cdot z & z^2 & 0 \\
|
||||
-(z-1)^3 & 3 \cdot (z-1)^2 \cdot z & -3 \cdot (z-1) \cdot z^2 & z^3
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3 \\ P_4
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z^3 \cdot P_4 - 3 \cdot z^2 \cdot (z-1) \cdot P_3 + 3 \cdot z \cdot (z-1)^2 \cdot P_2 - (z-1)^3 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
and
|
||||
|
||||
\[
|
||||
\begin{bmatrix}
|
||||
-(z-1)^3 & 3 \cdot (z-1)^2 \cdot z & -3 \cdot (z-1)^3 \cdot z^2 & z^3 \\
|
||||
0 & (z-1)^2 & -2 \cdot (z-1) \cdot z & z^2 \\
|
||||
0 & 0 & -(z-1) & z \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3 \\ P_4
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
z^3 \cdot P_4 - 3 \cdot z^2 \cdot (z-1) \cdot P_3 + 3 \cdot z \cdot (z-1)^2 \cdot P_2 - (z-1)^3 \cdot P_1 \\
|
||||
z^2 \cdot P_4 - 2 \cdot z \cdot (z-1) \cdot P_3 + (z-1)^2 \cdot P_2 \\
|
||||
z \cdot P_4 - (z-1) \cdot P_3 \\
|
||||
P_4
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
So, looking at our matrices, did we really need to compute the second segment matrix? No, we didn't. Actually having one segment's matrix means we implicitly have the other: push the values of each row in the matrix ***Q*** to the right, with zeroes getting pushed off the right edge and appearing back on the left, and then flip the matrix vertically. Presto, you just "calculated" ***Q'***.
|
||||
|
||||
Implementing curve splitting this way requires less recursion, and is just straight arithmetic with cached values, so can be cheaper on systems were recursion is expensive. If you're doing computation with devices that are good at matrix multiplication, chopping up a Bézier curve with this method will be a lot faster than applying de Casteljau.
|
@@ -1,628 +1,19 @@
|
||||
var React = require("react");
|
||||
var SectionHeader = require("../../SectionHeader.jsx");
|
||||
|
||||
var Locale = require("../../../lib/locale");
|
||||
var locale = new Locale("en-GB");
|
||||
var page = "matrixsplit";
|
||||
|
||||
var MatrixSplit = React.createClass({
|
||||
getDefaultProps: function() {
|
||||
return {
|
||||
title: "Splitting curves using matrices"
|
||||
title: locale.getTitle(page)
|
||||
};
|
||||
},
|
||||
|
||||
render: function() {
|
||||
return (
|
||||
<section>
|
||||
<SectionHeader {...this.props} />
|
||||
|
||||
<p>Another way to split curves is to exploit the matrix representation of
|
||||
a Bézier curve. In <a href="#matrix">the section on matrices</a> we saw that
|
||||
we can represent curves as matrix multiplications. Specifically, we saw these
|
||||
two forms for the quadratic, and cubic curves, respectively (using the reversed
|
||||
Bézier coefficients vector for legibility):</p>
|
||||
|
||||
<p>\[
|
||||
B(t) = \begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>and</p>
|
||||
|
||||
<p>\[
|
||||
B(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}
|
||||
\]</p>
|
||||
|
||||
<p>Let's say we want to split the curve at some point <em>t = z</em>, forming
|
||||
two new (obviously smaller) Bézier curves. To find the coordinates for these
|
||||
two Bézier curves, we can use the matrix representation and some linear algebra.
|
||||
First, we split out the the actual "point on the curve" information as a new matrix
|
||||
multiplication:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & (z \cdot t) & (z \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>and</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & (z \cdot t) & (z \cdot t)^2 & (z \cdot 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}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2 & t^3
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 & 0\\
|
||||
0 & z & 0 & 0\\
|
||||
0 & 0 & z^2 & 0\\
|
||||
0 & 0 & 0 & z^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}
|
||||
\]</p>
|
||||
|
||||
<p>If we could compact these matrices back to a form <strong>[t values] · [bezier matrix] · [column matrix]</strong>,
|
||||
with the first two staying the same, then that column matrix on the right would be the coordinates
|
||||
of a new Bézier curve that describes the first segment, from <em>t = 0</em> to <em>t = z</em>.
|
||||
As it turns out, we can do this quite easily, by exploiting some simple rules of linear algebra
|
||||
(and if you don't care about the derivations, just skip to the end of the box for the results!).</p>
|
||||
|
||||
<div className="note">
|
||||
<h2>Deriving new hull coordinates</h2>
|
||||
|
||||
<p>Deriving the two segments upon splitting a curve takes a few steps, and the higher
|
||||
the curve order, the more work it is, so let's look at the quadratic curve first:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\underset{we\ turn\ this...}{\underbrace{\kern 2.25em Z \cdot M \kern 2.25em}}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\underset{...into\ this...}{\underbrace{ M \cdot M^{-1} \cdot Z \cdot M }}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\underset{...to\ get\ \ this!}{\underbrace{ \kern 1.25em \cdot \kern 1.25em Q \kern 1.25em \cdot \kern 1.25em}}
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>We do this, because [<em>M · M<sup>-1</sup></em>] is the identity matrix (a bit like
|
||||
multiplying something by x/x in calculus. It doesn't do anything to the function, but it
|
||||
does allow you to rewrite it to something that may be easier to work with, or can be
|
||||
broken up differently). Adding that as matrix multiplication has no effect on the total
|
||||
formula, but it does allow us to change the matrix sequence [<em>something · M</em>] to
|
||||
a sequence [<em>M · something</em>], and that makes a world of difference: if we know
|
||||
what [<em>M<sup>-1</sup> · Z · M</em>] is, we can apply that to our coordinates, and be
|
||||
left with a proper matrix representation of a quadratic Bézier curve (which is
|
||||
[<em>T · M · P</em>]), with a new set of coordinates that represent the curve from
|
||||
<em>t = 0</em> to <em>t = z</em>. So let's get computing:</p>
|
||||
|
||||
<p>\[
|
||||
Q = M^{-1} \cdot Z \cdot M =
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
1 & \frac{1}{2} & 0 \\
|
||||
1 & 1 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>Excellent! Now we can form our new quadratic curve:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot M \cdot Q \cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\cdot
|
||||
\left (
|
||||
Q
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\left (
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z - 1)^2 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p><strong><em>Brilliant</em></strong>: if we want a subcurve from <em>t = 0</em>
|
||||
to <em>t = z</em>, we can keep the first coordinate the same (which makes sense),
|
||||
our control point becomes a z-ratio mixture of the original control point and the start
|
||||
point, and the new end point is a mixture that looks oddly similar to a bernstein
|
||||
polynomial of degree two, except it uses (z-1) rather than (1-z)... These new
|
||||
coordinates are actually really easy to compute directly!</p>
|
||||
|
||||
<p>Of course, that's only one of the two curves. Getting the section from <em>t = z</em>
|
||||
to <em>t = 1</em> requires doing this again. We first observe what what we just did is
|
||||
actually evaluate the general interval [0,<em>z</em>], which we wrote down simplified
|
||||
becuase of that zero, but we actually evaluated this:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & ( 0 + z \cdot t) & ( 0 + z \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
0 & z & 0 \\
|
||||
0 & 0 & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>If we want the interval [<em>z</em>,1], we will be evaluating this instead:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & ( z + (1-z) \cdot t) & ( z + (1-z) \cdot t)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & z & z^2 \\
|
||||
0 & 1-z & 2 \cdot z \cdot (1-z) \\
|
||||
0 & 0 & (1-z)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>We're going to do the same trick, to turn <em>[something · M]</em> into <em>[M · something]</em>:</p>
|
||||
|
||||
<p>\[
|
||||
Q' = M^{-1} \cdot Z' \cdot M =
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
1 & \frac{1}{2} & 0 \\
|
||||
1 & 1 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & z & z^2 \\
|
||||
0 & 1-z & 2 \cdot z \cdot (1-z) \\
|
||||
0 & 0 & (1-z)^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>So, our final second curve looks like:</p>
|
||||
|
||||
<p>\[
|
||||
B(t) =
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot M \cdot Q \cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
M
|
||||
\cdot
|
||||
\left (
|
||||
Q'
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\left (
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
\right )
|
||||
\]</p>
|
||||
|
||||
<p>\[
|
||||
=
|
||||
\begin{bmatrix}
|
||||
1 & t & t^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-2 & 2 & 0 \\
|
||||
1 & -2 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z \cdot P_3 - (z-1) \cdot P_2 \\
|
||||
P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p><strong><em>Nice</em></strong>: we see the same as before; can keep the last
|
||||
coordinate the same (which makes sense), our control point becomes a z-ratio
|
||||
mixture of the original control point and the end point, and the new start point
|
||||
is a mixture that looks oddly similar to a bernstein polynomial of degree two,
|
||||
except it uses (z-1) rather than (1-z). These new coordinates are <em>also</em>
|
||||
really easy to compute directly!</p>
|
||||
</div>
|
||||
|
||||
<p>So, using linear algebra rather than de Casteljau's algorithm, we have determined
|
||||
that for any quadratic curve split at some value <em>t = z</em>, we get two subcurves
|
||||
that are described as Bézier curves with simple-to-derive coordinates.</p>
|
||||
|
||||
<p>\[
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 \\
|
||||
-(z-1) & z & 0 \\
|
||||
(z - 1)^2 & -2 \cdot (z-1) \cdot z & z^2
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z - 1)^2 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>and</p>
|
||||
|
||||
<p>\[
|
||||
\begin{bmatrix}
|
||||
(z-1)^2 & -2 \cdot z \cdot (z-1) & z^2 \\
|
||||
0 & -(z-1) & z \\
|
||||
0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z \cdot P_3 - (z-1) \cdot P_2 \\
|
||||
P_3
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>We can do the same for cubic curves. However, I'll spare you the actual derivation
|
||||
(don't let that stop you from writing that out yourself, though) and simply show you
|
||||
the resulting new coordinate sets:</p>
|
||||
|
||||
<p>\[
|
||||
\begin{bmatrix}
|
||||
1 & 0 & 0 & 0 \\
|
||||
-(z-1) & z & 0 & 0 \\
|
||||
(z-1)^2 & -2 \cdot (z-1) \cdot z & z^2 & 0 \\
|
||||
-(z-1)^3 & 3 \cdot (z-1)^2 \cdot z & -3 \cdot (z-1) \cdot z^2 & z^3
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3 \\ P_4
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
P_1 \\
|
||||
z \cdot P_2 - (z-1) \cdot P_1 \\
|
||||
z^2 \cdot P_3 - 2 \cdot z \cdot (z-1) \cdot P_2 + (z-1)^2 \cdot P_1 \\
|
||||
z^3 \cdot P_4 - 3 \cdot z^2 \cdot (z-1) \cdot P_3 + 3 \cdot z \cdot (z-1)^2 \cdot P_2 - (z-1)^3 \cdot P_1
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>and</p>
|
||||
|
||||
<p>\[
|
||||
\begin{bmatrix}
|
||||
-(z-1)^3 & 3 \cdot (z-1)^2 \cdot z & -3 \cdot (z-1)^3 \cdot z^2 & z^3 \\
|
||||
0 & (z-1)^2 & -2 \cdot (z-1) \cdot z & z^2 \\
|
||||
0 & 0 & -(z-1) & z \\
|
||||
0 & 0 & 0 & 1
|
||||
\end{bmatrix}
|
||||
\cdot
|
||||
\begin{bmatrix}
|
||||
P_1 \\ P_2 \\ P_3 \\ P_4
|
||||
\end{bmatrix}
|
||||
=
|
||||
\begin{bmatrix}
|
||||
z^3 \cdot P_4 - 3 \cdot z^2 \cdot (z-1) \cdot P_3 + 3 \cdot z \cdot (z-1)^2 \cdot P_2 - (z-1)^3 \cdot P_1 \\
|
||||
z^2 \cdot P_4 - 2 \cdot z \cdot (z-1) \cdot P_3 + (z-1)^2 \cdot P_2 \\
|
||||
z \cdot P_4 - (z-1) \cdot P_3 \\
|
||||
P_4
|
||||
\end{bmatrix}
|
||||
\]</p>
|
||||
|
||||
<p>So, looking at our matrices, did we really need to compute the second segment matrix?
|
||||
No, we didn't. Actually having one segment's matrix means we implicitly have the other:
|
||||
push the values of each row in the matrix <strong><em>Q</em></strong> to the right, with
|
||||
zeroes getting pushed off the right edge and appearing back on the left, and then flip
|
||||
the matrix vertically. Presto, you just "calculated" <strong><em>Q'</em></strong>.</p>
|
||||
|
||||
<p>Implementing curve splitting this way requires less recursion, and is just straight
|
||||
arithmetic with cached values, so can be cheaper on systems were recursion is expensive.
|
||||
If you're doing computation with devices that are good at matrix multiplication, chopping
|
||||
up a Bézier curve with this method will be a lot faster than applying de Casteljau.</p>
|
||||
</section>
|
||||
<section>{ locale.getContent(page, this) }</section>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user