Skip to content

Commit

Permalink
grammar checking
Browse files Browse the repository at this point in the history
  • Loading branch information
Pomax committed Sep 20, 2020
1 parent 792bd0d commit f2f2c5a
Show file tree
Hide file tree
Showing 12 changed files with 78 additions and 105 deletions.
12 changes: 6 additions & 6 deletions chapters/bsplines/content.en-GB.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ What do they look like? They look like this! Tap on the graphic to add more poin

<graphics-element title="A B-Spline example" width="600" height="300" src="./basic.js"></graphics-element>

The important part to notice here is that we are **not** doing the same thing with B-Splines that we do for poly-Béziers or Catmull-Rom curves: both of the latter simply define new sections as literally "new sections based on new points", so a 12 point cubic poly-Bézier curve is actually impossible, because we start with a four point curve, and then add three more points for each section that follows, so we can only have 4, 7, 10, 13, 16, etc point Poly-Béziers. Similarly, while Catmull-Rom curves can grow by adding single points, this addition of a single point introduces three implicit Bézier points. Cubic B-Splines, on the other hand, are smooth interpolations of *each possible curve involving four consecutive points*, such that at any point along the curve except for our start and end points, our on-curve coordinate is defined by four control points.
The important part to notice here is that we are **not** doing the same thing with B-Splines that we do for poly-Béziers or Catmull-Rom curves: both of the latter simply define new sections as literally "new sections based on new points", so a 12 point cubic poly-Bézier curve is actually impossible, because we start with a four point curve, and then add three more points for each section that follows, so we can only have 4, 7, 10, 13, 16, etc. point Poly-Béziers. Similarly, while Catmull-Rom curves can grow by adding single points, this addition of a single point introduces three implicit Bézier points. Cubic B-Splines, on the other hand, are smooth interpolations of *each possible curve involving four consecutive points*, such that at any point along the curve except for our start and end points, our on-curve coordinate is defined by four control points.

Consider the difference to be this:

Expand All @@ -34,7 +34,7 @@ Given a B-Spline of degree `d` and thus order `k=d+1` (so a quadratic B-Spline i

Which, honestly, doesn't tell us all that much. All we can see is that a point on a B-Spline curve is defined as "a mix of all the control points, weighted somehow", where the weighting is achieved through the *N(...)* function, subscripted with an obvious parameter `i`, which comes from our summation, and some magical parameter `k`. So we need to know two things: 1. what does N(t) do, and 2. what is that `k`? Let's cover both, in reverse order.

The parameter `k` represents the "knot interval" over which a section of curve is defined. As we learned earlier, a B-Spline curve is itself an interpoliation of curves, and we can treat each transition where a control point starts or stops influencing the total curvature as a "knot on the curve".
The parameter `k` represents the "knot interval" over which a section of curve is defined. As we learned earlier, a B-Spline curve is itself an interpolation of curves, and we can treat each transition where a control point starts or stops influencing the total curvature as a "knot on the curve".
Doing so for a degree `d` B-Spline with `n` control point gives us `d + n + 1` knots, defining `d + n` intervals along the curve, and it is these intervals that the above `k` subscript to the N() function applies to.

Then the N() function itself. What does it look like?
Expand All @@ -43,7 +43,7 @@ Then the N() function itself. What does it look like?
N_{i,k}(t) = \left ( \frac{t-knot_i}{knot_{(i+k-1)} - knot_i}\right ) \cdot N_{i,k-1}(t) + \left ( \frac{knot_{(i+k)}-t}{knot_{(i+k)} - knot_{(i+1)}} \right ) \cdot N_{i+1,k-1}(t)
\]

So this is where we see the interpolation: N(t) for an (i,k) pair (that is, for a step in the above summation, on a specific knot interval) is a mix between N(t) for (i,k-1) and N(t) for (i+1,k-1), so we see that this is a recursive iteration where `i` goes up, and `k` goes down, so it seem reasonable to expect that this recursion has to stop at some point; obviously, it does, and specifically it does so for the following `i`/`k` values:
So this is where we see the interpolation: N(t) for an `(i,k)` pair (that is, for a step in the above summation, on a specific knot interval) is a mix between N(t) for `(i,k-1)` and N(t) for `(i+1,k-1)`, so we see that this is a recursive iteration where `i` goes up, and `k` goes down, so it seem reasonable to expect that this recursion has to stop at some point; obviously, it does, and specifically it does so for the following `i`/`k` values:

\[
N_{i,1}(t) = \left\{\begin{matrix}
Expand All @@ -59,7 +59,7 @@ And this function finally has a straight up evaluation: if a `t` value lies with

We can, yes.

People far smarter than us have looked at this work, and two in particular — [Maurice Cox](https://www.npl.co.uk/people/maurice-cox) and [Carl de Boor](https://en.wikipedia.org/wiki/Carl_R._de_Boor) — came to a mathematically pleasing solution: to compute a point P(t), we can compute this point by evaluating *d(t)* on a curve section between knots *i* and *i+1*:
People far smarter than us have looked at this work, and two in particular — [Maurice Cox](https://www.npl.co.uk/people/maurice-cox) and [Carl de Boor](https://en.wikipedia.org/wiki/Carl_R._de_Boor) — came to a mathematically pleasing solution: to compute a point P(t), we can compute this point by evaluating *d(t)* on a curve section between knots `i` and `i+1`:

\[
d^k_i(t) = \alpha_{i,k} \cdot d^{k-1}_i(t) + (1-\alpha_{i,k}) \cdot d^{k-1}_{i-1}(t)
Expand Down Expand Up @@ -139,7 +139,7 @@ One thing we need to keep in mind is that we're working with a spline that is co

Unlike the de Casteljau algorithm, where the `t` value stays the same at every iteration, for B-Splines that is not the case, and so we end having to (for each point we evaluate) run a fairly involving bit of recursive computation. The algorithm is discussed on [this Michigan Tech](https://pages.mtu.edu/~shene/COURSES/cs3621/NOTES/spline/de-Boor.html) page, but an easier to read version is implemented by [b-spline.js](https://github.com/thibauts/b-spline/blob/master/index.js#L59-L71), so we'll look at its code.

Given an input value `t`, we first map the input to a value from the domain [0,1] to the domain [knots[degree], knots[knots.length - 1 - degree]. Then, we find the section number `s` that this mapped `t` value lies on:
Given an input value `t`, we first map the input to a value from the domain `[0,1]` to the domain `[knots[degree], knots[knots.length - 1 - degree]`. Then, we find the section number `s` that this mapped `t` value lies on:

```
for(s=domain[0]; s < domain[1]; s++) {
Expand Down Expand Up @@ -233,7 +233,7 @@ While a true non-uniform rational B-Spline would be hard to work with, when we t

## Extending our implementation to cover rational splines

The algorithm for working with Rational B-Splines is virtually identical to the regular algorithm, and the extension to work in the control point weights is fairly simple: we extend each control point from a point in its original number of dimensions (2D, 3D, etc) to one dimension higher, scaling the original dimensions by the control point's weight, and then assigning that weight as its value for the extended dimension.
The algorithm for working with Rational B-Splines is virtually identical to the regular algorithm, and the extension to work in the control point weights is fairly simple: we extend each control point from a point in its original number of dimensions (2D, 3D, etc.) to one dimension higher, scaling the original dimensions by the control point's weight, and then assigning that weight as its value for the extended dimension.

For example, a 2D point `(x,y)` with weight `w` becomes a 3D point `(w * x, w * y, w)`.

Expand Down
6 changes: 3 additions & 3 deletions chapters/extremities/extremities.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ drawComponentY(dim, degree) {
}

plotDimension(dim, dimension) {
cacheStyle();
save();
dimension.drawCurve();

setFill(`red`);
Expand Down Expand Up @@ -118,7 +118,7 @@ plotQuadraticDimension(t1, y1, t2, y2, dim, dimension, reverse) {
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);
restoreStyle();
restore();
}


Expand Down Expand Up @@ -159,7 +159,7 @@ plotCubicDimension(t1, y1, t2, y2, dim, dimension, reverse) {
}
});

restoreStyle();
restore();
}

getRoots(v1, v2, v3) {
Expand Down
27 changes: 14 additions & 13 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
<meta property="og:locale" content="en-GB" />
<meta property="og:type" content="article" />
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
<meta property="og:updated_time" content="2020-09-20T05:43:12+00:00" />
<meta property="og:updated_time" content="2020-09-20T21:20:31+00:00" />
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
<meta property="og:section" content="Bézier Curves" />
<meta property="og:tag" content="Bézier Curves" />
Expand Down Expand Up @@ -2490,7 +2490,7 @@ <h3>In conclusion:</h3>
>
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\extremities\1b70524bfb7d159a48f0b370d81ee2f6.png" loading="lazy" />
<img width="825px" height="275px" src="images\chapters\extremities\fd68347a917c9b703ff8005287ac6ca4.png" loading="lazy" />
<label></label> </fallback-image
></graphics-element>

Expand All @@ -2504,7 +2504,7 @@ <h3>In conclusion:</h3>
>
<fallback-image>
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
<img width="825px" height="275px" src="images\chapters\extremities\a77025630019ef3d90ffa279879a205a.png" loading="lazy" />
<img width="825px" height="275px" src="images\chapters\extremities\fbfe9464c9653f5efcd04411e683faf9.png" loading="lazy" />
<label></label> </fallback-image
></graphics-element>
</section>
Expand Down Expand Up @@ -5721,7 +5721,7 @@ <h1>
The important part to notice here is that we are <strong>not</strong> doing the same thing with B-Splines that we do for poly-Béziers or
Catmull-Rom curves: both of the latter simply define new sections as literally "new sections based on new points", so a 12 point cubic
poly-Bézier curve is actually impossible, because we start with a four point curve, and then add three more points for each section that
follows, so we can only have 4, 7, 10, 13, 16, etc point Poly-Béziers. Similarly, while Catmull-Rom curves can grow by adding single
follows, so we can only have 4, 7, 10, 13, 16, etc. point Poly-Béziers. Similarly, while Catmull-Rom curves can grow by adding single
points, this addition of a single point introduces three implicit Bézier points. Cubic B-Splines, on the other hand, are smooth
interpolations of <em>each possible curve involving four consecutive points</em>, such that at any point along the curve except for our
start and end points, our on-curve coordinate is defined by four control points.
Expand Down Expand Up @@ -5761,18 +5761,18 @@ <h2>How to compute a B-Spline curve: some maths</h2>
</p>
<p>
The parameter <code>k</code> represents the "knot interval" over which a section of curve is defined. As we learned earlier, a B-Spline
curve is itself an interpoliation of curves, and we can treat each transition where a control point starts or stops influencing the total
curve is itself an interpolation of curves, and we can treat each transition where a control point starts or stops influencing the total
curvature as a "knot on the curve". Doing so for a degree <code>d</code> B-Spline with <code>n</code> control point gives us
<code>d + n + 1</code> knots, defining <code>d + n</code> intervals along the curve, and it is these intervals that the above
<code>k</code> subscript to the N() function applies to.
</p>
<p>Then the N() function itself. What does it look like?</p>
<img class="LaTeX SVG" src="./images/chapters/bsplines/cf45d1ea00d4866abc8a058b130299b4.svg" width="584px" height="49px" loading="lazy" />
<p>
So this is where we see the interpolation: N(t) for an (i,k) pair (that is, for a step in the above summation, on a specific knot
interval) is a mix between N(t) for (i,k-1) and N(t) for (i+1,k-1), so we see that this is a recursive iteration where <code>i</code> goes
up, and <code>k</code> goes down, so it seem reasonable to expect that this recursion has to stop at some point; obviously, it does, and
specifically it does so for the following <code>i</code>/<code>k</code> values:
So this is where we see the interpolation: N(t) for an <code>(i,k)</code> pair (that is, for a step in the above summation, on a specific
knot interval) is a mix between N(t) for <code>(i,k-1)</code> and N(t) for <code>(i+1,k-1)</code>, so we see that this is a recursive
iteration where <code>i</code> goes up, and <code>k</code> goes down, so it seem reasonable to expect that this recursion has to stop at
some point; obviously, it does, and specifically it does so for the following <code>i</code>/<code>k</code> values:
</p>
<img class="LaTeX SVG" src="./images/chapters/bsplines/adac18ea69cc58e01c8d5e15498e4aa6.svg" width="245px" height="40px" loading="lazy" />
<p>
Expand All @@ -5789,7 +5789,7 @@ <h2>Can we simplify that?</h2>
People far smarter than us have looked at this work, and two in particular —
<a href="https://www.npl.co.uk/people/maurice-cox">Maurice Cox</a> and
<a href="https://en.wikipedia.org/wiki/Carl_R._de_Boor">Carl de Boor</a> — came to a mathematically pleasing solution: to compute a point
P(t), we can compute this point by evaluating <em>d(t)</em> on a curve section between knots <em>i</em> and <em>i+1</em>:
P(t), we can compute this point by evaluating <em>d(t)</em> on a curve section between knots <code>i</code> and <code>i+1</code>:
</p>
<img class="LaTeX SVG" src="./images/chapters/bsplines/763838ea6f9e6c6aa63ea5f9c6d9542f.svg" width="287px" height="21px" loading="lazy" />
<p>
Expand Down Expand Up @@ -5836,8 +5836,9 @@ <h2>Running the computation</h2>
is implemented by <a href="https://github.com/thibauts/b-spline/blob/master/index.js#L59-L71">b-spline.js</a>, so we'll look at its code.
</p>
<p>
Given an input value <code>t</code>, we first map the input to a value from the domain [0,1] to the domain [knots[degree],
knots[knots.length - 1 - degree]. Then, we find the section number <code>s</code> that this mapped <code>t</code> value lies on:
Given an input value <code>t</code>, we first map the input to a value from the domain <code>[0,1]</code> to the domain
<code>[knots[degree], knots[knots.length - 1 - degree]</code>. Then, we find the section number <code>s</code> that this mapped
<code>t</code> value lies on:
</p>
<pre><code>for(s=domain[0]; s &lt; domain[1]; s++) {
if(knots[s] &lt;= t && t &lt;= knots[s+1]) break;
Expand Down Expand Up @@ -5996,7 +5997,7 @@ <h2>One last thing: Rational B-Splines</h2>
<h2>Extending our implementation to cover rational splines</h2>
<p>
The algorithm for working with Rational B-Splines is virtually identical to the regular algorithm, and the extension to work in the
control point weights is fairly simple: we extend each control point from a point in its original number of dimensions (2D, 3D, etc) to
control point weights is fairly simple: we extend each control point from a point in its original number of dimensions (2D, 3D, etc.) to
one dimension higher, scaling the original dimensions by the control point's weight, and then assigning that weight as its value for the
extended dimension.
</p>
Expand Down
Loading

0 comments on commit f2f2c5a

Please sign in to comment.