From b745c59f86f6a337b85cf5bc2417883eee25c274 Mon Sep 17 00:00:00 2001 From: Pomax Date: Wed, 19 Aug 2020 22:24:01 -0700 Subject: [PATCH] inflections --- chapters/extremities/content.en-GB.md | 10 +- chapters/extremities/cubic.js | 20 +++- chapters/inflections/content.en-GB.md | 14 +-- chapters/inflections/handler.js | 17 ---- chapters/inflections/inflection.js | 62 ++++++++++++ .../1440c49b9192919163dc44d6b0cf156b.png | Bin 0 -> 24316 bytes .../68ed7f964bbfad946506cad184feb1b2.png | Bin 23452 -> 0 bytes .../e81a6573cf3ea31045eb7e8dca3eecb3.png | Bin 0 -> 10369 bytes .../04336edba7697ca91861821e32fc14be.svg | 1 - .../0ec5cc72a428d75defb480530b50d720.svg | 2 +- .../1679090a942a43d27f886f236fc8d62b.svg | 1 + .../2029bca9f4fa15739553636af99b70a8.svg | 2 +- .../4b5c7d0bf0fcd769db007dd98d4a024d.svg | 1 + .../4d78ebcf8626f777725d67d3672fa480.svg | 2 +- .../4dbe6398d0075b5b9ef39458ef620616.svg | 1 - .../7c9762c0e04693eb743905cdc0487f8b.svg | 1 + .../97b34ad5920612574d1b2a1a9d22d571.svg | 2 +- .../997a8cc704c0ab0e364cb8b532df90b0.svg | 2 +- .../b2433959e1f451fa3bf238fc37e04527.svg | 2 +- .../b94df866222bed63d123df6b839a4d14.svg | 1 - .../bafdb6583323bda71d9a15c02d1fdec2.svg | 2 +- .../d7a657089da19f032dd3b3e1d9ed1d89.svg | 1 - .../d9e66caeb45b6643112ce3d971b17e5b.svg | 2 +- .../ddc6f99a543afad25c55cf16b9deeed9.svg | 2 +- .../e06ec558d99b53e559d24524f4201951.svg | 2 +- .../ec28870926b6ed08625d942b578e6fbe.svg | 1 - index.html | 93 ++++++++++++------ ja-JP/index.html | 93 ++++++++++++------ lib/custom-element/lib/bezierjs/bezier.js | 5 + lib/custom-element/lib/bezierjs/utils.js | 2 + zh-CN/index.html | 93 ++++++++++++------ 31 files changed, 299 insertions(+), 138 deletions(-) delete mode 100644 chapters/inflections/handler.js create mode 100644 chapters/inflections/inflection.js create mode 100644 images/chapters/extremities/1440c49b9192919163dc44d6b0cf156b.png delete mode 100644 images/chapters/extremities/68ed7f964bbfad946506cad184feb1b2.png create mode 100644 images/chapters/inflections/e81a6573cf3ea31045eb7e8dca3eecb3.png delete mode 100644 images/latex/04336edba7697ca91861821e32fc14be.svg create mode 100644 images/latex/1679090a942a43d27f886f236fc8d62b.svg create mode 100644 images/latex/4b5c7d0bf0fcd769db007dd98d4a024d.svg delete mode 100644 images/latex/4dbe6398d0075b5b9ef39458ef620616.svg create mode 100644 images/latex/7c9762c0e04693eb743905cdc0487f8b.svg delete mode 100644 images/latex/b94df866222bed63d123df6b839a4d14.svg delete mode 100644 images/latex/d7a657089da19f032dd3b3e1d9ed1d89.svg delete mode 100644 images/latex/ec28870926b6ed08625d942b578e6fbe.svg diff --git a/chapters/extremities/content.en-GB.md b/chapters/extremities/content.en-GB.md index 7b963e83..56e3373d 100644 --- a/chapters/extremities/content.en-GB.md +++ b/chapters/extremities/content.en-GB.md @@ -71,6 +71,8 @@ This gives us three coefficients {a, b, c} that are expressed in terms of `v` va Easy-peasy. We can now almost trivially find the roots by plugging those values into the quadratic formula. +And as a cubic curve, there is also a meaningful second derivative, which we can compute by simple taking the derivative of the derivative. + ### Quartic curves: Cardano's algorithm. We haven't really looked at them before now, but the next step up would be a Quartic curve, a fourth degree Bézier curve. As expected, these have a derivative that is a cubic function, and now things get much harder. Cubic functions don't have a "simple" rule to find their roots, like the quadratic formula, and instead require quite a bit of rewriting to a form that we can even start to try to solve. @@ -185,6 +187,9 @@ function getCubicRoots(pa, pb, pc, pd) { And that's it. The maths is complicated, but the code is pretty much just "follow the maths, while caching as many values as we can to prevent recomputing things as much as possible" and now we have a way to find all roots for a cubic function and can just move on with using that to find extremities of our curves. +And of course, as a quartic curve also has meaningful second and third derivatives, we can quite easily compute those by using the derivative of the derivative (of the derivative), just as for cubic cuvers. + + ### Quintic and higher order curves: finding numerical solutions And this is where thing stop, because we _cannot_ find the roots for polynomials of degree 5 or higher using algebra (a fact known as [the Abel–Ruffini theorem](https://en.wikipedia.org/wiki/Abel%E2%80%93Ruffini_theorem)). Instead, for occasions like these, where algebra simply cannot yield an answer, we turn to [numerical analysis](https://en.wikipedia.org/wiki/Numerical_analysis). @@ -207,7 +212,10 @@ As it turns out, Newton-Raphson is so blindingly fast that we could get away wit ### In conclusion: -So now that we know how to do root finding, we can determine the first and second derivative roots for our Bézier curves, and show those roots overlaid on the previous graphics: +So now that we know how to do root finding, we can determine the first and second derivative roots for our Bézier curves, and show those roots overlaid on the previous graphics. For the quadratic curve, that means just the first derivative, in red: + +And for cubic curves, that means first and second derivatives, in red and purple respectively: + diff --git a/chapters/extremities/cubic.js b/chapters/extremities/cubic.js index 8d48ae0f..15df8d6c 100644 --- a/chapters/extremities/cubic.js +++ b/chapters/extremities/cubic.js @@ -46,7 +46,7 @@ plotDimension(dim, dimension) { dimension.drawCurve(); setFill(`red`); - setStroke(`red)`); + setStroke(`red`); // There are four possible extrema: t=0, t=1, and // up to two t values that solves B'(t)=0, provided @@ -80,15 +80,31 @@ plotDimension(dim, dimension) { } }); - // Done, show our extrema: + // Done, show our derivative-based extrema: circle(t1 * dim, y1, 3); text(`t = ${t1.toFixed(2)}`, map(t1, 0,1, 15,dim-15), y1 + 25); circle(t2 * dim, y2, 3); text(`t = ${t2.toFixed(2)}`, map(t2, 0,1, 15,dim-15), y2 + 25); + + // And then show the second derivate inflection, if there is one + setFill(`purple`); + setStroke(`purple`); + this.getRoots(...dimension.dpoints[1].map(p => p.y)).forEach(t =>{ + if (t > 0 && t < 1) { + let d = dimension.get(t); + circle(t * dim, d.y, 3); + text(`t = ${t.toFixed(2)}`, map(t, 0,1, 15,dim-15), d.y + 25); + } + }); + restoreStyle(); } getRoots(v1, v2, v3) { + if (v3 === undefined) { + return [-v1 / (v2 - v1)]; + } + const a = v1 - 2*v2 + v3, b = 2 * (v2 - v1), c = v1, diff --git a/chapters/inflections/content.en-GB.md b/chapters/inflections/content.en-GB.md index 804ac4c3..c3cc057b 100644 --- a/chapters/inflections/content.en-GB.md +++ b/chapters/inflections/content.en-GB.md @@ -60,10 +60,10 @@ That is... unwieldy. So, we note that there are a lot of terms that involve mult -Aligning our curve so that three of the eight coefficients become zero, we end up with the following simple term function for *C(t)*: +Aligning our curve so that three of the eight coefficients become zero, and observing that scale does not affect finding `t` values, we end up with the following simple term function for *C(t)*: \[ - 18 \left ( (3 x_3 y_2+2 x_4 y_2+3 x_2 y_3-x_4 y_3)t^2 + (3 x_3 y_2-x_4 y_2-3 x_2 y_3)t + (x_2 y_3-x_3 y_2) \right ) + \left ( 3 x_3 y_2+2 x_4 y_2+3 x_2 y_3-x_4 y_3 \right ) t^2 + \left ( 3 x_3 y_2-x_4 y_2-3 x_2 y_3 \right ) t + \left ( x_2 y_3-x_3 y_2 \right ) \] That's a lot easier to work with: we see a fair number of terms that we can compute and then cache, giving us the following simplification: @@ -75,16 +75,16 @@ That's a lot easier to work with: we see a fair number of terms that we can comp c = x_2 \cdot y_3 \\ d = x_4 \cdot y_3 \end{matrix}\right\} - \ C(t) = 18 \cdot \left ( (-3a + 2b + 3c - d)t^2 + (3a - b - 3c)t + (c - a) \right ) + \ C(t) = (-3a + 2b + 3c - d)t^2 + (3a - b - 3c)t + (c - a) \] This is a plain quadratic curve, and we know how to solve *C(t) = 0*; we use the quadratic formula: \[ \left.\begin{matrix} - x =& 18(-3a + 2b + 3c - d) \\ - y =& 18(3a - b - 3c) \\ - z =& 18(c - a) + x =& -3a + 2b + 3c - d \\ + y =& 3a - b - 3c \\ + z =& c - a \end{matrix}\right\} \ C(t) = 0 \ \Rightarrow\ t = \frac{-y \pm \sqrt{y^2 - 4 x z}}{2x} \] @@ -93,4 +93,4 @@ We can easily compute this value *if* the discriminator isn't a negative number Taking that into account, we compute *t*, we disregard any *t* value that isn't in the Bézier interval [0,1], and we now know at which *t* value(s) our curve will inflect. - + diff --git a/chapters/inflections/handler.js b/chapters/inflections/handler.js deleted file mode 100644 index e8245b4b..00000000 --- a/chapters/inflections/handler.js +++ /dev/null @@ -1,17 +0,0 @@ -module.exports = { - setupCubic: function(api) { - var curve = new api.Bezier(135,25, 25, 135, 215,75, 215,240); - api.setCurve(curve); - }, - - draw: function(api, curve) { - api.reset(); - api.drawSkeleton(curve); - api.drawCurve(curve); - - api.setColor("red"); - curve.inflections().forEach(function(t) { - api.drawCircle(curve.get(t), 5); - }); - } -}; diff --git a/chapters/inflections/inflection.js b/chapters/inflections/inflection.js new file mode 100644 index 00000000..bea57322 --- /dev/null +++ b/chapters/inflections/inflection.js @@ -0,0 +1,62 @@ +setup() { + const curve = this.curve = new Bezier(this, 70,250, 120,15, 20,95, 225,80); + setMovable(curve.points); +} + +draw() { + clear(); + + const curve = this.curve; + curve.drawSkeleton(); + curve.drawCurve(); + curve.drawPoints(); + + const p = curve.align().points, + + a = p[2].x * p[1].y, + b = p[3].x * p[1].y, + c = p[1].x * p[2].y, + d = p[3].x * p[2].y, + + x = -3*a + 2*b + 3*c - d, + y = 3*a - b - 3*c, + z = c - a, + + roots = []; + + if (this.almost(x, 0) ) { + if (!this.almost(y, 0) ) { + roots.push(-z / y); + } + } + + else { + const det = y * y - 4 * x * z, + sq = sqrt(det), + d2 = 2 * x; + + if (!this.almost(d2, 0) ) { + roots.push(-(y+sq) / d2); + roots.push((sq-y) / d2); + } + } + + setStroke(`red`); + setFill(`red`); + + roots.forEach(t => { + if (0 <= t && t <= 1) { + let p = curve.get(t); + circle(p.x, p.y, 3); + text(`t=${t.toFixed(2)}`, p.x + 5, p.y + 15); + } + }); +} + +almost(v1, v2, epsilon=0.00001) { + return abs(v1 - v2) < epsilon; +} + +onMouseMove() { + redraw(); +} diff --git a/images/chapters/extremities/1440c49b9192919163dc44d6b0cf156b.png b/images/chapters/extremities/1440c49b9192919163dc44d6b0cf156b.png new file mode 100644 index 0000000000000000000000000000000000000000..42b60982eee466053d6ca62b649c8807d81d5baa GIT binary patch literal 24316 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 \ No newline at end of file diff --git a/images/latex/0ec5cc72a428d75defb480530b50d720.svg b/images/latex/0ec5cc72a428d75defb480530b50d720.svg index 23d363e7..b8120594 100644 --- a/images/latex/0ec5cc72a428d75defb480530b50d720.svg +++ b/images/latex/0ec5cc72a428d75defb480530b50d720.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/1679090a942a43d27f886f236fc8d62b.svg b/images/latex/1679090a942a43d27f886f236fc8d62b.svg new file mode 100644 index 00000000..eb91f0b8 --- /dev/null +++ b/images/latex/1679090a942a43d27f886f236fc8d62b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/latex/2029bca9f4fa15739553636af99b70a8.svg b/images/latex/2029bca9f4fa15739553636af99b70a8.svg index 9b378ab4..0d596d81 100644 --- a/images/latex/2029bca9f4fa15739553636af99b70a8.svg +++ b/images/latex/2029bca9f4fa15739553636af99b70a8.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/4b5c7d0bf0fcd769db007dd98d4a024d.svg b/images/latex/4b5c7d0bf0fcd769db007dd98d4a024d.svg new file mode 100644 index 00000000..2b3ba2b2 --- /dev/null +++ b/images/latex/4b5c7d0bf0fcd769db007dd98d4a024d.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/latex/4d78ebcf8626f777725d67d3672fa480.svg b/images/latex/4d78ebcf8626f777725d67d3672fa480.svg index 43072ec5..cbd7521e 100644 --- a/images/latex/4d78ebcf8626f777725d67d3672fa480.svg +++ b/images/latex/4d78ebcf8626f777725d67d3672fa480.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/4dbe6398d0075b5b9ef39458ef620616.svg b/images/latex/4dbe6398d0075b5b9ef39458ef620616.svg deleted file mode 100644 index fa09da2f..00000000 --- a/images/latex/4dbe6398d0075b5b9ef39458ef620616.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/images/latex/7c9762c0e04693eb743905cdc0487f8b.svg b/images/latex/7c9762c0e04693eb743905cdc0487f8b.svg new file mode 100644 index 00000000..6b05bfed --- /dev/null +++ b/images/latex/7c9762c0e04693eb743905cdc0487f8b.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/images/latex/97b34ad5920612574d1b2a1a9d22d571.svg b/images/latex/97b34ad5920612574d1b2a1a9d22d571.svg index e3e08abb..96136043 100644 --- a/images/latex/97b34ad5920612574d1b2a1a9d22d571.svg +++ b/images/latex/97b34ad5920612574d1b2a1a9d22d571.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/997a8cc704c0ab0e364cb8b532df90b0.svg b/images/latex/997a8cc704c0ab0e364cb8b532df90b0.svg index b43f2a91..fe3ddf3d 100644 --- a/images/latex/997a8cc704c0ab0e364cb8b532df90b0.svg +++ b/images/latex/997a8cc704c0ab0e364cb8b532df90b0.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/b2433959e1f451fa3bf238fc37e04527.svg b/images/latex/b2433959e1f451fa3bf238fc37e04527.svg index 2d1be1d7..abd72ec8 100644 --- a/images/latex/b2433959e1f451fa3bf238fc37e04527.svg +++ b/images/latex/b2433959e1f451fa3bf238fc37e04527.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/b94df866222bed63d123df6b839a4d14.svg b/images/latex/b94df866222bed63d123df6b839a4d14.svg deleted file mode 100644 index d8555a3e..00000000 --- a/images/latex/b94df866222bed63d123df6b839a4d14.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg b/images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg index aa9f0b88..ec06373a 100644 --- a/images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg +++ b/images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/d7a657089da19f032dd3b3e1d9ed1d89.svg b/images/latex/d7a657089da19f032dd3b3e1d9ed1d89.svg deleted file mode 100644 index 27c50ac8..00000000 --- a/images/latex/d7a657089da19f032dd3b3e1d9ed1d89.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg b/images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg index ed0ae5f8..e3872290 100644 --- a/images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg +++ b/images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/ddc6f99a543afad25c55cf16b9deeed9.svg b/images/latex/ddc6f99a543afad25c55cf16b9deeed9.svg index f681f546..37076a3f 100644 --- a/images/latex/ddc6f99a543afad25c55cf16b9deeed9.svg +++ b/images/latex/ddc6f99a543afad25c55cf16b9deeed9.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/e06ec558d99b53e559d24524f4201951.svg b/images/latex/e06ec558d99b53e559d24524f4201951.svg index edc21914..b9b577a0 100644 --- a/images/latex/e06ec558d99b53e559d24524f4201951.svg +++ b/images/latex/e06ec558d99b53e559d24524f4201951.svg @@ -1 +1 @@ - \ No newline at end of file + \ No newline at end of file diff --git a/images/latex/ec28870926b6ed08625d942b578e6fbe.svg b/images/latex/ec28870926b6ed08625d942b578e6fbe.svg deleted file mode 100644 index 87e13ebf..00000000 --- a/images/latex/ec28870926b6ed08625d942b578e6fbe.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/index.html b/index.html index 5ee3fedf..4a1ec8bb 100644 --- a/index.html +++ b/index.html @@ -2962,8 +2962,8 @@ function drawCurve(points[], t):

So, if we can rewrite the Bézier component function as a plain @@ -2983,8 +2983,8 @@ function drawCurve(points[], t):

And then, using these v values, we can find out what our @@ -2993,8 +2993,8 @@ function drawCurve(points[], t):

This gives us three coefficients {a, b, c} that are expressed in @@ -3006,12 +3006,17 @@ function drawCurve(points[], t): class="LaTeX SVG" src="images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg" width="308px" - height="63px" + height="64px" />

Easy-peasy. We can now almost trivially find the roots by plugging those values into the quadratic formula.

+

+ And as a cubic curve, there is also a meaningful second derivative, + which we can compute by simple taking the derivative of the + derivative. +

Quartic curves: Cardano's algorithm.

We haven't really looked at them before now, but the next step up @@ -3034,8 +3039,8 @@ function drawCurve(points[], t):

We can see that the easier formula only has two constants, rather @@ -3180,6 +3185,12 @@ function getCubicRoots(pa, pb, pc, pd) { way to find all roots for a cubic function and can just move on with using that to find extremities of our curves.

+

+ And of course, as a quartic curve also has meaningful second and + third derivatives, we can quite easily compute those by using the + derivative of the derivative (of the derivative), just as for cubic + cuvers. +

Quintic and higher order curves: finding numerical solutions

And this is where thing stop, because we cannot find the @@ -3278,7 +3289,8 @@ function getCubicRoots(pa, pb, pc, pd) {

So now that we know how to do root finding, we can determine the first and second derivative roots for our Bézier curves, and show - those roots overlaid on the previous graphics: + those roots overlaid on the previous graphics. For the quadratic + curve, that means just the first derivative, in red:

+ +

+ And for cubic curves, that means first and second derivatives, in + red and purple respectively: +

Scripts are disabled. Showing fallback image. @@ -3562,7 +3579,7 @@ function getCubicRoots(pa, pb, pc, pd) { class="LaTeX SVG" src="images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg" width="59px" - height="16px" + height="17px" />

What we're saying here is that given the curvature function @@ -3576,8 +3593,8 @@ function getCubicRoots(pa, pb, pc, pd) {

The function C(t) is the cross product between the first @@ -3607,14 +3624,14 @@ function getCubicRoots(pa, pb, pc, pd) {

And of course the same functions for y:

@@ -3625,8 +3642,8 @@ function getCubicRoots(pa, pb, pc, pd) {

That is... unwieldy. So, we note that there are a lot of terms @@ -3638,14 +3655,15 @@ function getCubicRoots(pa, pb, pc, pd) {

Aligning our curve so that three of the eight coefficients become - zero, we end up with the following simple term function for - C(t): + zero, and observing that scale does not affect finding + t values, we end up with the following simple term + function for C(t):

That's a lot easier to work with: we see a fair number of terms that @@ -3654,8 +3672,8 @@ function getCubicRoots(pa, pb, pc, pd) {

@@ -3664,9 +3682,9 @@ function getCubicRoots(pa, pb, pc, pd) {

We can easily compute this value if the discriminator isn't @@ -3679,11 +3697,22 @@ function getCubicRoots(pa, pb, pc, pd) { t value that isn't in the Bézier interval [0,1], and we now know at which t value(s) our curve will inflect.

- + width="275" + height="275" + src="./chapters/inflections/inflection.js" + > + + + Scripts are disabled. Showing fallback image. +

Canonical form (for cubic curves)

diff --git a/ja-JP/index.html b/ja-JP/index.html index 89828154..eb222594 100644 --- a/ja-JP/index.html +++ b/ja-JP/index.html @@ -2634,8 +2634,8 @@ function drawCurve(points[], t):

So, if we can rewrite the Bézier component function as a plain @@ -2655,8 +2655,8 @@ function drawCurve(points[], t):

And then, using these v values, we can find out what our @@ -2665,8 +2665,8 @@ function drawCurve(points[], t):

This gives us three coefficients {a, b, c} that are expressed in @@ -2678,12 +2678,17 @@ function drawCurve(points[], t): class="LaTeX SVG" src="images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg" width="308px" - height="63px" + height="64px" />

Easy-peasy. We can now almost trivially find the roots by plugging those values into the quadratic formula.

+

+ And as a cubic curve, there is also a meaningful second derivative, + which we can compute by simple taking the derivative of the + derivative. +

Quartic curves: Cardano's algorithm.

We haven't really looked at them before now, but the next step up @@ -2706,8 +2711,8 @@ function drawCurve(points[], t):

We can see that the easier formula only has two constants, rather @@ -2852,6 +2857,12 @@ function getCubicRoots(pa, pb, pc, pd) { way to find all roots for a cubic function and can just move on with using that to find extremities of our curves.

+

+ And of course, as a quartic curve also has meaningful second and + third derivatives, we can quite easily compute those by using the + derivative of the derivative (of the derivative), just as for cubic + cuvers. +

Quintic and higher order curves: finding numerical solutions

And this is where thing stop, because we cannot find the @@ -2950,7 +2961,8 @@ function getCubicRoots(pa, pb, pc, pd) {

So now that we know how to do root finding, we can determine the first and second derivative roots for our Bézier curves, and show - those roots overlaid on the previous graphics: + those roots overlaid on the previous graphics. For the quadratic + curve, that means just the first derivative, in red:

+ +

+ And for cubic curves, that means first and second derivatives, in + red and purple respectively: +

Scripts are disabled. Showing fallback image. @@ -3236,7 +3253,7 @@ function getCubicRoots(pa, pb, pc, pd) { class="LaTeX SVG" src="images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg" width="59px" - height="16px" + height="17px" />

What we're saying here is that given the curvature function @@ -3250,8 +3267,8 @@ function getCubicRoots(pa, pb, pc, pd) {

The function C(t) is the cross product between the first @@ -3281,14 +3298,14 @@ function getCubicRoots(pa, pb, pc, pd) {

And of course the same functions for y:

@@ -3299,8 +3316,8 @@ function getCubicRoots(pa, pb, pc, pd) {

That is... unwieldy. So, we note that there are a lot of terms @@ -3312,14 +3329,15 @@ function getCubicRoots(pa, pb, pc, pd) {

Aligning our curve so that three of the eight coefficients become - zero, we end up with the following simple term function for - C(t): + zero, and observing that scale does not affect finding + t values, we end up with the following simple term + function for C(t):

That's a lot easier to work with: we see a fair number of terms that @@ -3328,8 +3346,8 @@ function getCubicRoots(pa, pb, pc, pd) {

@@ -3338,9 +3356,9 @@ function getCubicRoots(pa, pb, pc, pd) {

We can easily compute this value if the discriminator isn't @@ -3353,11 +3371,22 @@ function getCubicRoots(pa, pb, pc, pd) { t value that isn't in the Bézier interval [0,1], and we now know at which t value(s) our curve will inflect.

- + width="275" + height="275" + src="./chapters/inflections/inflection.js" + > + + + Scripts are disabled. Showing fallback image. +

diff --git a/lib/custom-element/lib/bezierjs/bezier.js b/lib/custom-element/lib/bezierjs/bezier.js index 2adcbacd..803d1b0f 100644 --- a/lib/custom-element/lib/bezierjs/bezier.js +++ b/lib/custom-element/lib/bezierjs/bezier.js @@ -356,6 +356,11 @@ class Bezier { return ret; } + align() { + let p = this.points; + return new Bezier(utils.align(p, { p1: p[0], p2: p[p.length - 1] })); + } + curvature(t) { return utils.curvature(t, this.points, this._3d); } diff --git a/lib/custom-element/lib/bezierjs/utils.js b/lib/custom-element/lib/bezierjs/utils.js index 3a55db4c..f086cae4 100644 --- a/lib/custom-element/lib/bezierjs/utils.js +++ b/lib/custom-element/lib/bezierjs/utils.js @@ -643,6 +643,8 @@ const utils = { } return []; } + + return []; }, curvature: function (t, points, _3d, kOnly) { diff --git a/zh-CN/index.html b/zh-CN/index.html index cae8202f..4fa34dce 100644 --- a/zh-CN/index.html +++ b/zh-CN/index.html @@ -2644,8 +2644,8 @@ function drawCurve(points[], t):

So, if we can rewrite the Bézier component function as a plain @@ -2665,8 +2665,8 @@ function drawCurve(points[], t):

And then, using these v values, we can find out what our @@ -2675,8 +2675,8 @@ function drawCurve(points[], t):

This gives us three coefficients {a, b, c} that are expressed in @@ -2688,12 +2688,17 @@ function drawCurve(points[], t): class="LaTeX SVG" src="images/latex/d9e66caeb45b6643112ce3d971b17e5b.svg" width="308px" - height="63px" + height="64px" />

Easy-peasy. We can now almost trivially find the roots by plugging those values into the quadratic formula.

+

+ And as a cubic curve, there is also a meaningful second derivative, + which we can compute by simple taking the derivative of the + derivative. +

Quartic curves: Cardano's algorithm.

We haven't really looked at them before now, but the next step up @@ -2716,8 +2721,8 @@ function drawCurve(points[], t):

We can see that the easier formula only has two constants, rather @@ -2862,6 +2867,12 @@ function getCubicRoots(pa, pb, pc, pd) { way to find all roots for a cubic function and can just move on with using that to find extremities of our curves.

+

+ And of course, as a quartic curve also has meaningful second and + third derivatives, we can quite easily compute those by using the + derivative of the derivative (of the derivative), just as for cubic + cuvers. +

Quintic and higher order curves: finding numerical solutions

And this is where thing stop, because we cannot find the @@ -2960,7 +2971,8 @@ function getCubicRoots(pa, pb, pc, pd) {

So now that we know how to do root finding, we can determine the first and second derivative roots for our Bézier curves, and show - those roots overlaid on the previous graphics: + those roots overlaid on the previous graphics. For the quadratic + curve, that means just the first derivative, in red:

+ +

+ And for cubic curves, that means first and second derivatives, in + red and purple respectively: +

Scripts are disabled. Showing fallback image. @@ -3246,7 +3263,7 @@ function getCubicRoots(pa, pb, pc, pd) { class="LaTeX SVG" src="images/latex/bafdb6583323bda71d9a15c02d1fdec2.svg" width="59px" - height="16px" + height="17px" />

What we're saying here is that given the curvature function @@ -3260,8 +3277,8 @@ function getCubicRoots(pa, pb, pc, pd) {

The function C(t) is the cross product between the first @@ -3291,14 +3308,14 @@ function getCubicRoots(pa, pb, pc, pd) {

And of course the same functions for y:

@@ -3309,8 +3326,8 @@ function getCubicRoots(pa, pb, pc, pd) {

That is... unwieldy. So, we note that there are a lot of terms @@ -3322,14 +3339,15 @@ function getCubicRoots(pa, pb, pc, pd) {

Aligning our curve so that three of the eight coefficients become - zero, we end up with the following simple term function for - C(t): + zero, and observing that scale does not affect finding + t values, we end up with the following simple term + function for C(t):

That's a lot easier to work with: we see a fair number of terms that @@ -3338,8 +3356,8 @@ function getCubicRoots(pa, pb, pc, pd) {

@@ -3348,9 +3366,9 @@ function getCubicRoots(pa, pb, pc, pd) {

We can easily compute this value if the discriminator isn't @@ -3363,11 +3381,22 @@ function getCubicRoots(pa, pb, pc, pd) { t value that isn't in the Bézier interval [0,1], and we now know at which t value(s) our curve will inflect.

- + width="275" + height="275" + src="./chapters/inflections/inflection.js" + > + + + Scripts are disabled. Showing fallback image. +