mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-02-25 10:02:58 +01:00
Edits to simplify matrix-splitting section (#186)
* Many style edits to matrix splitting chapter, because this stuff is complicated and we want to make it simple. * *You*'re not using LaTeX...
This commit is contained in:
parent
3de2ee1cbf
commit
11e2ab3286
@ -1,6 +1,6 @@
|
||||
# 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):
|
||||
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: (we'll reverse the Bézier coefficients vector for legibility)
|
||||
|
||||
\[
|
||||
B(t) = \begin{bmatrix}
|
||||
@ -37,7 +37,7 @@ and
|
||||
\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 actual "point on the curve" information as a new matrix multiplication:
|
||||
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 separate out the actual "point on the curve" information into a new matrix multiplication:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
@ -118,7 +118,7 @@ and
|
||||
\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!).
|
||||
If we could compact these matrices back to the form **[t values] · [Bézier 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">
|
||||
|
||||
@ -188,7 +188,7 @@ Deriving the two segments upon splitting a curve takes a few steps, and the high
|
||||
\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:
|
||||
We can do this because [*M · M<sup>-1</sup>*] is the identity matrix. It's 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. In the same way, multiplying our matrix by [*M · M<sup>-1</sup>*] 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 =
|
||||
@ -290,7 +290,7 @@ Excellent! Now we can form our new quadratic curve:
|
||||
|
||||
***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](https://en.wikipedia.org/wiki/Bernstein_polynomial) of degree two. 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 we just did is actually evaluate the general interval [0,`z`], which we wrote down simplified because of that zero, but we actually evaluated this:
|
||||
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 that in the previous calculation, we actually evaluated the general interval [0,`z`]. We were able to write it down in a more simple form because of the zero, but what we *actually* evaluated, making the zero explicit, was:
|
||||
|
||||
\[
|
||||
B(t) =
|
||||
@ -374,7 +374,7 @@ If we want the interval [*z*,1], we will be evaluating this instead:
|
||||
\end{bmatrix}
|
||||
\]
|
||||
|
||||
We're going to do the same trick, to turn `[something · M]` into `[M · something]`:
|
||||
We're going to do the same trick of multiplying by the identity matrix, to turn `[something · M]` into `[M · something]`:
|
||||
|
||||
\[
|
||||
Q' = M^{-1} \cdot Z' \cdot M =
|
||||
@ -474,11 +474,11 @@ So, our final second curve looks like:
|
||||
\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!
|
||||
***Nice***. We see the same thing as before: we 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 this time 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.
|
||||
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}
|
||||
@ -564,4 +564,4 @@ and
|
||||
|
||||
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.
|
||||
Implementing curve splitting this way requires less recursion, and is just straight arithmetic with cached values, so can be cheaper on systems where 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.
|
||||
|
Loading…
x
Reference in New Issue
Block a user