1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-30 19:50:01 +02:00

poly-bezier

This commit is contained in:
Pomax
2020-09-03 22:21:05 -07:00
parent d2992ebd15
commit 83dcab57cb
19 changed files with 367 additions and 290 deletions

View File

@@ -1990,27 +1990,67 @@ for p = 1 to points.length-3 (inclusive):
</ol>
<p>Unless you want sharp corners, of course. Then you don't even need 2.</p>
<p>We'll cover three forms of poly-Bézier curves in this section. First, we'll look at the kind that just follows point 1. where the end point of a segment is the same point as the start point of the next segment. This leads to poly-Béziers that are pretty hard to work with, but they're the easiest to implement:</p>
<Graphic title="Unlinked quadratic poly-Bézier" setup={this.setupQuadratic} draw={this.draw}/>
<Graphic title="Unlinked cubic poly-Bézier" setup={this.setupCubic} draw={this.draw}/>
<graphics-element title="Unlinked quadratic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="quadratic" data-link="coordinate">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\0553872bf00ebc557f4b11d69d634fc6.png">
<label>Unlinked quadratic poly-Bézier</label>
</fallback-image></graphics-element>
<graphics-element title="Unlinked cubic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="cubic" data-link="coordinate">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\60adbd6fe091a72e1ed37355e49a506e.png">
<label>Unlinked cubic poly-Bézier</label>
</fallback-image></graphics-element>
<p>Dragging the control points around only affects the curve segments that the control point belongs to, and moving an on-curve point leaves the control points where they are, which is not the most useful for practical modelling purposes. So, let's add in the logic we need to make things a little better. We'll start by linking up control points by ensuring that the "incoming" derivative at an on-curve point is the same as it's "outgoing" derivative:</p>
<img class="LaTeX SVG" src="./images/chapters/polybezier/408dd95905a5f001179c4da6051e49c5.svg" width="124px" height="17px" loading="lazy">
<img class="LaTeX SVG" src="./images/chapters/polybezier/408dd95905a5f001179c4da6051e49c5.svg" width="129px" height="17px" loading="lazy">
<p>We can effect this quite easily, because we know that the vector from a curve's last control point to its last on-curve point is equal to the derivative vector. If we want to ensure that the first control point of the next curve matches that, all we have to do is mirror that last control point through the last on-curve point. And mirroring any point A through any point B is really simple:</p>
<img class="LaTeX SVG" src="./images/chapters/polybezier/8c1b570b3efdfbbc39ddedb4adcaaff6.svg" width="304px" height="40px" loading="lazy">
<img class="LaTeX SVG" src="./images/chapters/polybezier/8c1b570b3efdfbbc39ddedb4adcaaff6.svg" width="320px" height="40px" loading="lazy">
<p>So let's implement that and see what it gets us. The following two graphics show a quadratic and a cubic poly-Bézier curve again, but this time moving the control points around moves others, too. However, you might see something unexpected going on for quadratic curves...</p>
<Graphic title="Connected quadratic poly-Bézier" setup={this.setupQuadratic} draw={this.draw} onMouseMove={this.linkDerivatives}/>
<Graphic title="Connected cubic poly-Bézier" setup={this.setupCubic} draw={this.draw} onMouseMove={this.linkDerivatives}/>
<graphics-element title="Connected quadratic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="quadratic" data-link="derivative">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\1aeb331a5170c203c31c55ae8d55b809.png">
<label>Connected quadratic poly-Bézier</label>
</fallback-image></graphics-element>
<graphics-element title="Connected cubic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="cubic" data-link="derivative">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\04bc7b98ba019a4a90bedce6e10eaf08.png">
<label>Connected cubic poly-Bézier</label>
</fallback-image></graphics-element>
<p>As you can see, quadratic curves are particularly ill-suited for poly-Bézier curves, as all the control points are effectively linked. Move one of them, and you move all of them. Not only that, but if we move the on-curve points, it's possible to get a situation where a control point's positions is different depending on whether it's the reflection of its left or right neighbouring control point: we can't even form a proper rule-conforming curve! This means that we cannot use quadratic poly-Béziers for anything other than really, really simple shapes. And even then, they're probably the wrong choice. Cubic curves are pretty decent, but the fact that the derivatives are linked means we can't manipulate curves as well as we might if we relaxed the constraints a little.</p>
<p>As you can see, quadratic curves are particularly ill-suited for poly-Bézier curves, as all the control points are effectively linked. Move one of them, and you move all of them. Not only that, but if we move the on-curve points, it's possible to get a situation where a control point cannot satisfy the constraint that it's the reflection of its two neighbouring control points... This means that we cannot use quadratic poly-Béziers for anything other than really, really simple shapes. And even then, they're probably the wrong choice. Cubic curves are pretty decent, but the fact that the derivatives are linked means we can't manipulate curves as well as we might if we relaxed the constraints a little.</p>
<p>So: let's relax the requirement a little.</p>
<p>We can change the constraint so that we still preserve the <em>angle</em> of the derivatives across sections (so transitions from one section to the next will still look natural), but give up the requirement that they should also have the same <em>vector length</em>. Doing so will give us a much more useful kind of poly-Bézier curve:</p>
<Graphic title="Angularly connected quadratic poly-Bézier" setup={this.setupQuadratic} draw={this.draw} onMouseMove={this.linkDirection}/>
<Graphic title="Angularly connected cubic poly-Bézier" setup={this.setupCubic} draw={this.draw} onMouseMove={this.linkDirection}/>
<graphics-element title="Angularly connected quadratic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="quadratic" data-link="direction">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\acb8f004751017eaac4aae0b039c94cf.png">
<label>Angularly connected quadratic poly-Bézier</label>
</fallback-image></graphics-element>
<graphics-element title="Angularly connected cubic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="cubic" data-link="direction">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\1a3c6b24bea874d32334d62110507fcb.png">
<label>Angularly connected cubic poly-Bézier</label>
</fallback-image></graphics-element>
<p>Cubic curves are now better behaved when it comes to dragging control points around, but the quadratic poly-Bézier still has the problem that moving one control points will move the control points and may ending up defining "the next" control point in a way that doesn't work. Quadratic curves really aren't very useful to work with...</p>
<p>Finally, we also want to make sure that moving the on-curve coordinates preserves the relative positions of the associated control points. With that, we get to the kind of curve control that you might be familiar with from applications like Photoshop, Inkscape, Blender, etc.</p>
<Graphic title="Standard connected quadratic poly-Bézier" setup={this.setupQuadratic} draw={this.draw} onMouseDown={this.bufferPoints} onMouseMove={this.modelCurve}/>
<Graphic title="Standard connected cubic poly-Bézier" setup={this.setupCubic} draw={this.draw} onMouseDown={this.bufferPoints} onMouseMove={this.modelCurve}/>
<graphics-element title="Standard connected quadratic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="quadratic" data-link="conventional">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\7afd119dd93a581ec161e2cbfc3c1e63.png">
<label>Standard connected quadratic poly-Bézier</label>
</fallback-image></graphics-element>
<graphics-element title="Standard connected cubic poly-Bézier" width="275" height="275" src="./chapters/polybezier/poly.js" data-type="cubic" data-link="conventional">
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="275px" height="275px" src="images\chapters\polybezier\cfbfbbc56365ba547dc7e82b329c4007.png">
<label>Standard connected cubic poly-Bézier</label>
</fallback-image></graphics-element>>
<p>Again, we see that cubic curves are now rather nice to work with, but quadratic curves have a new, very serious problem: we can move an on-curve point in such a way that we can't compute what needs to "happen next". Move the top point down, below the left and right points, for instance. There is no way to preserve correct control points without a kink at the bottom point. Quadratic curves: just not that good...</p>
<p>A final improvement is to offer fine-level control over which points behave which, so that you can have "kinks" or individually controlled segments when you need them, with nicely well-behaved curves for the rest of the path. Implementing that, is left as an exercise for the reader.</p>