1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-01-17 05:28:31 +01:00

Add a curvature section (#159)

* curvature and radius of curvature
This commit is contained in:
Pomax 2018-12-09 16:31:16 -08:00 committed by GitHub
parent 3e1a3c27f5
commit 4ad072c7a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 390 additions and 11 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,5 +1,9 @@
module.exports = {
"December 2018": [
"Added a section on curvature and calculating kappa."
],
"August 2018": [
"Added a section on finding a curve's y, if all you have is the x coordinate."
],

View File

@ -0,0 +1,71 @@
# Curvature of a curve
Imagine we have two curves, and we want to line them in up in a way that "looks right". What would we use as metric to let a computer decide what "looks right" means? For instance, we can start by ensuring that the two curves share an end coordinate, so that there is no "gap" between leaving one curve and entering the next, but that won't guarantee that things look right: both curves can be going in wildly different directions, and the resulting joined geometry will have a corner in it, rather than a smooth transition from one curve to the next. What we want is to ensure that the [_curvature_](https://en.wikipedia.org/wiki/Curvature) at the transition from one curve to the next "looks good". So, we could have them share an end coordinate, and then ensure that the derivatives for both curves match at that coordinate, and at a casual glance, that seems the perfect solution: if we make the derivatives match, then both the "direction" in which we travel from one curve to the next is the same, and the "speed" at which we travel the curve will be the same.
Problem solved!
But, if we think about this a little more, this cannot possible work, because of something that you may have noticed in the section on [reordering curves](#reordering): what a curve looks like, and the function that draws that curve, are not in some kind of universal, fixed, one-to-one relation. If we have some quadratic curve, then simply by raising the curve order we can get corresponding cubic, quartic, and higher and higher mathematical expressions that all draw the _exact same curve_ but with wildly different derivatives. So: if we want to make a transition from one curve to the next look good, and we want to use the derivative, then we suddenly need to answer the question: "Which derivative?".
How would you even decide? What makes the cubic derivatives better or less suited than, say, quintic derivatives? Wouldn't it be nicer if we could use something that was inherent to the curve, without being tied to the functions that yield that curve? And (of course) as it turns out, there is a way to define curvature in such a way that it only relies on what the curve actually looks like, and given where this section is in the larger body of this Primer, it should hopefully not be surprising that we thing we can use to define curvature is the thing we talked about in the previous section: arc length.
Intuitively, this should make sense, even if we have no idea what the maths would look like: if we travel some fixed distance along some curve, then the point at that distance is simply the point at that distance. It doesn't matter what function we used to draw the curve: once we know what the curve looks like, the function(s) used to draw it become irrelevant: a point a third along the full distance of the curve is simply the point a third along the distance of the curve.
You might think that in order to find the curvature of a curve, we now need to find and then solve the arc length function, and that would be a problem because we just saw that there is no way to actually do that: don't worry, we don't. We do need to know the _form_ of the arc length function, which we saw above, but it's not the thing we're actually interested in, and we're going to be rewriting it in a way that makes most of the crazy complex things about it just... disappear.
In fact, after [running through the steps necessary](http://mathworld.wolfram.com/Curvature.html) to determine what we're left with if we use the arclength function's derivative (with another run-through of the maths [here](https://math.stackexchange.com/a/275324/71940)), rather than the curve's original function's derivative, then the integral disappears entirely (because of the [fundamental therem of calculus](https://en.wikipedia.org/wiki/Fundamental_theorem_of_calculus)), and we're left with some surprisingly simple maths that relates curvature (denoted as κ, "kappa") to—and this is the truly surprising bit—a specific combination of derivatives of our original function.
Let me just highlight that before we move on: we calculate the curvature of a curve using the arc length function derivative, because the original function's derivative is entirely unreliable, and in doing so we end up with a formula that expresses curvature in terms of the original function's derivatives.
*That's crazy!*
But, that's what makes maths such an interesting thing: it can show you that all your assumptions are completely wrong, only to then go "but actually, you were on the right track all along, here: ..." with a solution that is so easy to work with as to almost seem mundane. So: enough of all this text, how do we calculate curvature? What is the function for κ? Concisely, the function is this:
\[
\kappa = \frac{{x}'{y}'' - {x}''{y}'}{({x}'^2+{y}'^2)^{\frac{2}{3}}}
\]
Which is really just a "short form" that glosses over the fact that we're dealing with functions:
\[
\kappa(t) = \frac{{B_x}'(t){B_y}''(t) - {B_x}''(t){B_y}'(t)}{({B_x}'(t)^2+{B_y}'(t)^2)^{\frac{2}{3}}}
\]
And while that's a litte more verbose, it's still just as simple to work with as the first function: the curvature at some point on any (and this cannot be overstated: _any_) curve is a ratio between the first and second derivative cross product, and something that looks oddly similar to the standard Euclidean distance function. And nothing in these functions is hard to calculate either: for Bézier curves, simply knowing our curve coordinates means [we know what the first and second derivatives are](#derivatives), and so evaluating this function for any **t** value is just a matter of basic arithematics.
<div className="howtocode">
### Implement the kappa function
In fact, let's just implement it right now:
```
function kappa(t, B):
d = B.getDerivative()
dd = d.getDerivative()
dx = d.getX(t)
dy = d.getY(t)
ddx = dd.getX(t)
ddy = dd.getY(t)
numerator = dx * ddy + dy * dx
denominator = pow(dx*dx + dy*dy, 2/3)
return numerator / denominator
```
That was easy!
In fact, it stays easy because we can also compute the associated "radius of curvature", which gives us the implicit circle that "fits" the curve's curvature at any point, using what is possibly the simplest relation in this entire primer:
\[
R(t) = \frac{1}{\kappa(t)}
\]
So that's a rather convenient fact to know, too.
</div>
So with all of that covered, let's line up some curves! The following graphic gives you two curves that look identical, but use quadratic and cubic functions, respectively. As you can see, despite their derivatives being necessarily different, their curvature (thanks to being derived based on maths that "ignores" specific function derivative, and instead gives a formulat that smooths out any differences) is exactly the same. And because of that, we can put them together such that the point where they overlap has the same curvature for both curves, giving us the smoothest looking transition we could ask for.
<Graphic title="Matching curvatures for a quadratic and cubic Bézier curve" setup={this.setup} draw={this.draw} />
One thing you may have noticed in this sketch is that sometimes the curvature looks fine, but seems to be pointing in the wrong direction, making it hard to line up the curves properly. In your code you typically solve this by matching absolute values, but that's not super easy to program visually... however, we _can_ just show the curvature on both sides of the curve, making lining things up a bit easier:
<Graphic title="(Easier) curvature matching for a quadratic and cubic Bézier curve" setup={this.setup} draw={this.drawOmni} />

View File

@ -0,0 +1,70 @@
module.exports = {
setup: function(api) {
let d = api.defaultWidth;
api.setSize(d*3, api.defaultHeight);
// Set up two curves with identical form, but different functions:
var q = this.q = new api.Bezier(115, 250, 10, 35, 190, 45);
var c = this.c = q.raise();
q.points.forEach(p => (p.x += d/2));
c.points.forEach(p => (p.x += 3*d/2));
// And "fake" a master curve that we'll never draw, but which
// will allow us to move interact with the curve points.
api.setCurve({
points: q.points.concat(c.points)
});
},
updateCurves(api, curve) {
// update the quadratic and cubic curves by grabbing
// whatever the points in our "fake" master curve are
let q = this.q;
q.points = curve.points.slice(0,3);
q.update();
let c = this.c;
c.points = curve.points.slice(3,7);
c.update();
},
drawCurvature(api, curve, omni) {
api.drawSkeleton(curve);
api.drawCurve(curve);
var s, t, p, n, c, ox, oy;
for( s=0; s<256; s++) {
// Draw the curvature as a coloured line at the
// current point, along the normal.
api.setColor('rgba(255,127,'+s+',0.6)');
t = s/255;
p = curve.get(t);
n = curve.normal(t);
c = curve.curvature(t);
ox = c.k * n.x;
oy = c.k * n.y;
api.drawLine(p, { x: p.x + ox, y: p.y + oy });
// And if requested, also draw it along the anti-normal.
if (omni) {
api.setColor('rgba('+s+',127,255,0.6)');
api.drawLine(p, { x: p.x - ox, y: p.y - oy });
}
}
},
proxyDraw: function(api, curve, omni) {
api.reset();
this.updateCurves(api, curve);
[this.q, this.c].forEach(curve => this.drawCurvature(api, curve, omni));
},
draw: function(api, curve) {
this.proxyDraw(api, curve);
},
drawOmni: function(api, curve) {
this.proxyDraw(api, curve, true);
}
};

View File

@ -40,6 +40,7 @@ module.exports = {
// accurate arc length is hard, yo
arclength: require("./arclength"),
arclengthapprox: require("./arclengthapprox"),
curvature: require("./curvature"),
tracing: require("./tracing"),
// curve intersections

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="61pt" height="28pt" viewBox="0 0 61 28"><defs><symbol overflow="visible" id="a"><path d="M7.766-.094V-.53c-.61-.078-.657-.14-.985-.64L4.703-4.267c.438-.078.875-.265 1.313-.578.687-.5 1.093-1.25 1.093-1.984 0-1.031-1.234-1.703-2.218-1.703-.594 0-1.204.031-1.797.031l-1.938-.047-.062.61.828.03c.297 0 .281-.03.281.188 0 .172-.047.547-.11.907l-.905 5.187C1-.531 1.125-.641.64-.594l-.61.031-.093.61L1.688 0 3.28.047l.047-.61-.719-.03c-.328-.032-.296.015-.296-.235 0-.11 0-.219.046-.422l1.016-5.813.11-.484.046-.203c.25-.063.485-.094.813-.094 1.031 0 1.437.344 1.437 1.219 0 1.14-.781 1.844-2.031 1.844h-.625l-.094.281C4.687-2.094 5.062-1.516 5.984.047 6.36.016 6.641 0 6.938 0c.25 0 .468.016.828.063zm0 0"/></symbol><symbol overflow="visible" id="b"><path d="M4.203-7.828a.735.735 0 0 1-.187-.14c-.063-.063-.11-.126-.22-.329-1.593 1.61-2.5 3.266-2.5 4.781v.797c0 1.516.907 3.172 2.5 4.781.11-.203.157-.265.22-.328.062-.062.125-.109.312-.203C2.875.063 2.281-1.344 2.281-2.719v-.797c0-1.39.594-2.78 2.047-4.25zm0 0"/></symbol><symbol overflow="visible" id="c"><path d="M3.703-5.516c-.453.047-.86.063-1.156.063.172-.984.297-1.578.531-2.25l-.25-.328a7.16 7.16 0 0 1-1.094.531l-.296 2.031c-.391.203-.704.328-1.063.407l-.047.406h1l-.64 3.25C.625-1.11.53-.813.53-.5c0 .297.266.61.5.61.422 0 .922-.282 1.86-1.032.218-.172.14-.125.437-.36l-.25-.437-.672.469c-.36.25-.484.313-.625.313-.093 0-.031.046-.031-.11 0-.297.156-1.234.516-3l.14-.61h1.266l.203-.89zm0 0"/></symbol><symbol overflow="visible" id="d"><path d="M3.766-2.719v-.797c0-1.515-.907-3.171-2.516-4.78-.11.202-.156.265-.203.327-.063.063-.125.11-.313.203 1.438 1.47 2.032 2.86 2.032 4.25v.797c0 1.375-.594 2.781-2.032 4.25.188.094.25.14.313.203.047.063.094.125.203.329C2.86.452 3.766-1.204 3.766-2.72zm0 0"/></symbol><symbol overflow="visible" id="e"><path d="M8.266-4.078a1.419 1.419 0 0 1-.047-.36c0-.109.015-.234.062-.484h-7.5c.063.25.063.375.063.484 0 .125 0 .235-.063.5h7.5zm0 2.625a1.332 1.332 0 0 1-.047-.36c0-.109.015-.234.062-.484h-7.5c.063.25.063.375.063.485 0 .125 0 .25-.063.5h7.5zm0 0"/></symbol><symbol overflow="visible" id="f"><path d="M5.125-.094v-.484l-.75-.047c-.656-.031-.64-.031-.64-.656v-7.172l-.313-.125c-.875.469-1.61.781-2.86 1.219l.125.718h.235l1.547-.687.031-.016c.063 0-.047-.015-.047.266v5.797c0 .625.016.625-.64.656L1-.578v.625L3.125 0l2 .047zm0 0"/></symbol><symbol overflow="visible" id="g"><path d="M6.281-5.922a1.98 1.98 0 0 0-.562-.11c-.782 0-1.922.954-3.516 3.048l.235.093.203-.796c.078-.266.187-.75.265-1.016l.078-.313c.063-.203.094-.343.094-.5.016-.25-.203-.5-.375-.5-.25 0-.828.282-1.75.907l-.375.28.14.5.579-.359c.344-.218.375-.234.484-.234.125 0 .047-.031.047.11-.031.718-.656 3.156-1.219 4.75l.235.187.937-.25.39-1.719c.126-.515.407-.906.657-1.125C3.468-.844 3.953.11 4.25.11c.156 0 .531-.187 1.094-.562l.625-.422-.188-.469-.687.375c-.188.094-.14.078-.25.078-.125 0-.094-.03-.203-.234-.391-.766-.579-1.313-.97-2.734l.126-.125c.765-.72 1.234-.985 1.828-.985.11 0 .234.016.516.094l.296-.984zm0 0"/></symbol></defs><use xlink:href="#a" x=".463" y="17.537"/><use xlink:href="#b" x="8.437" y="17.537"/><use xlink:href="#c" x="13.506" y="17.537"/><use xlink:href="#d" x="17.547" y="17.537"/><use xlink:href="#e" x="25.928" y="17.537"/><use xlink:href="#f" x="46.952" y="8.929"/><path d="M39.54 14.547h20.8" fill="none" stroke-width=".717" stroke="#000" stroke-miterlimit="10"/><use xlink:href="#g" x="39.539" y="25.499"/><g><use xlink:href="#b" x="46.162" y="25.499"/><use xlink:href="#c" x="51.231" y="25.499"/></g><g><use xlink:href="#d" x="55.272" y="25.499"/></g></svg>

After

Width:  |  Height:  |  Size: 3.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.0 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.4 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 9.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="172" height="36" viewBox="0 0 129 27"><defs><symbol overflow="visible" id="a"><path d="M6.813-6.844c0-.984-1.094-1.687-2.016-1.687-.594 0-1.203.031-1.797.031l-1.938-.047-.062.61.797.03c.281 0 .266-.03.266.188 0 .172-.047.547-.11.907L.922-.782C.89-.577.875-.624.25-.531L.14.048A21.28 21.28 0 0 1 1.407 0c.64 0 1.266.031 1.922.031.563 0 1.219-.156 1.781-.5.954-.562 1.516-1.469 1.516-2.375 0-.515-.203-1-.531-1.265-.313-.25-.766-.391-1.594-.516v.266c.688-.25 1.063-.438 1.453-.75.531-.485.86-1.125.86-1.735zM5.296-2.656c0 1.234-.734 1.984-1.922 1.984-.25 0-.594-.015-.984-.047-.079-.015-.22-.015-.25-.031l.562-3.313h.906c1.235 0 1.688.375 1.688 1.407zm.219-3.985c0 1.266-.75 1.891-2.235 1.891h-.453l.531-3.016c.22 0 .532-.062.844-.062.969 0 1.313.297 1.313 1.187zm0 0"/></symbol><symbol overflow="visible" id="b"><path d="M4.203-7.828a.735.735 0 0 1-.187-.14c-.063-.063-.11-.126-.22-.329-1.593 1.61-2.5 3.266-2.5 4.781v.797c0 1.516.907 3.172 2.5 4.781.11-.203.157-.265.22-.328.062-.062.125-.109.312-.203C2.875.063 2.281-1.344 2.281-2.719v-.797c0-1.39.594-2.78 2.047-4.25zm0 0"/></symbol><symbol overflow="visible" id="c"><path d="M3.703-5.516c-.453.047-.86.063-1.156.063.172-.984.297-1.578.531-2.25l-.25-.328a7.16 7.16 0 0 1-1.094.531l-.296 2.031c-.391.203-.704.328-1.063.407l-.047.406h1l-.64 3.25C.625-1.11.53-.813.53-.5c0 .297.266.61.5.61.422 0 .922-.282 1.86-1.032.218-.172.14-.125.437-.36l-.25-.437-.672.469c-.36.25-.484.313-.625.313-.093 0-.031.046-.031-.11 0-.297.156-1.234.516-3l.14-.61h1.266l.203-.89zm0 0"/></symbol><symbol overflow="visible" id="d"><path d="M3.766-2.719v-.797c0-1.515-.907-3.171-2.516-4.78-.11.202-.156.265-.203.327-.063.063-.125.11-.313.203 1.438 1.47 2.032 2.86 2.032 4.25v.797c0 1.375-.594 2.781-2.032 4.25.188.094.25.14.313.203.047.063.094.125.203.329C2.86.452 3.766-1.204 3.766-2.72zm0 0"/></symbol><symbol overflow="visible" id="f"><path d="M8.266-4.078a1.419 1.419 0 0 1-.047-.36c0-.109.015-.234.062-.484h-7.5c.063.25.063.375.063.484 0 .125 0 .235-.063.5h7.5zm0 2.625a1.332 1.332 0 0 1-.047-.36c0-.109.015-.234.062-.484h-7.5c.063.25.063.375.063.485 0 .125 0 .25-.063.5h7.5zm0 0"/></symbol><symbol overflow="visible" id="g"><path d="M5.875-8.86l-.219-.187c-.75.375-1.078.438-2.062.531l-.094.5h.75c.281 0 .25-.046.25.157 0 .109 0 .203-.016.296L4.188-5.89a3.109 3.109 0 0 0-.875-.14c-.829 0-2.063.906-2.61 1.937-.375.703-.64 1.938-.64 2.938C.063-.375.374.125.734.125c.313 0 .86-.234 1.266-.563.64-.515 1.031-.984 1.844-2.187l-.25-.094-.266 1.078c-.14.532-.203.907-.203 1.22 0 .25.25.546.453.546.219 0 .594-.203 1-.5l1.047-.766-.266-.468-.656.468c-.172.125-.25.172-.36.172-.093 0-.046.031-.046-.14 0-.094.031-.204.11-.547l1.515-7.157zM4.031-5.03l-.14.703A5.233 5.233 0 0 1 2.375-1.61c-.422.39-.781.64-1.016.64-.187 0-.171-.031-.171-.328 0-1.516.515-3.281 1.109-3.734.156-.125.281-.14.61-.14.53 0 .765.03 1.109.218zm0 0"/></symbol><symbol overflow="visible" id="h"><path d="M3.094-8.86l-.219-.187c-.75.375-1.063.438-2.047.531l-.094.5h.735c.281 0 .265-.046.265.141 0 .156-.046.422-.078.578L.516-1.703C.344-1.093.28-.75.28-.484c0 .28.281.593.5.593.313 0 .86-.296 2.094-1.218l-.25-.438-.469.297c-.344.234-.5.313-.61.313-.093 0-.03.03-.03-.11s.03-.297.078-.437L3.14-8.813zm0 0"/></symbol><symbol overflow="visible" id="e"><path d="M2.61-4.672l-.22-.203-1.093.39-.89 3.376.312.234.5-.266 1.453-3.468zm0 0"/></symbol></defs><use xlink:href="#a" x=".536" y="18.003"/><use xlink:href="#b" x="7.841" y="18.003"/><use xlink:href="#c" x="12.91" y="18.003"/><use xlink:href="#d" x="16.939" y="18.003"/><use xlink:href="#e" x="22.019" y="13.771"/><use xlink:href="#f" x="28.91" y="18.003"/><use xlink:href="#g" x="42.513" y="9.396"/><use xlink:href="#a" x="48.61" y="9.396"/><path d="M42.512 15.016h13.414" fill="none" stroke-width=".717" stroke="#000" stroke-miterlimit="10"/><use xlink:href="#g" x="44.145" y="26.049"/><use xlink:href="#c" x="50.242" y="26.049"/><use xlink:href="#f" x="60.443" y="18.003"/><use xlink:href="#g" x="74.404" y="9.396"/><use xlink:href="#h" x="80.501" y="9.396"/><path d="M74.047 15.016h10.148" fill="none" stroke-width=".717" stroke="#000" stroke-miterlimit="10"/><use xlink:href="#g" x="74.045" y="26.049"/><use xlink:href="#c" x="80.154" y="26.049"/><use xlink:href="#g" x="86.586" y="9.396"/><use xlink:href="#a" x="92.695" y="9.396"/><path d="M86.586 15.016H100" fill="none" stroke-width=".717" stroke="#000" stroke-miterlimit="10"/><use xlink:href="#g" x="88.577" y="26.049"/><use xlink:href="#h" x="94.674" y="26.049"/><use xlink:href="#f" x="104.516" y="18.003"/><use xlink:href="#g" x="118.477" y="9.396"/><use xlink:href="#h" x="124.586" y="9.396"/><path d="M118.117 15.016h10.153" fill="none" stroke-width=".717" stroke="#000" stroke-miterlimit="10"/><g><use xlink:href="#g" x="118.119" y="26.049"/></g><g><use xlink:href="#c" x="124.216" y="26.049"/></g></svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@ -1,5 +1,4 @@
<!-- AUTOGENERATED CONTENT, PLEASE EDIT 'index.template.html' INSTEAD! -->
<!-- AUTOGENERATED CONTENT, PLEASE EDIT 'index.template.html' INSTEAD! -->
<!doctype html>
<html>
<head>

File diff suppressed because one or more lines are too long

View File

@ -1796,6 +1796,79 @@ return {
}()),
withKeys: true
},
"curvature": {
handler: (function() { return {
setup: function(api) {
let d = api.defaultWidth;
api.setSize(d*3, api.defaultHeight);
// Set up two curves with identical form, but different functions:
var q = this.q = new api.Bezier(115, 250, 10, 35, 190, 45);
var c = this.c = q.raise();
q.points.forEach(p => (p.x += d/2));
c.points.forEach(p => (p.x += 3*d/2));
// And "fake" a master curve that we'll never draw, but which
// will allow us to move interact with the curve points.
api.setCurve({
points: q.points.concat(c.points)
});
},
updateCurves(api, curve) {
// update the quadratic and cubic curves by grabbing
// whatever the points in our "fake" master curve are
let q = this.q;
q.points = curve.points.slice(0,3);
q.update();
let c = this.c;
c.points = curve.points.slice(3,7);
c.update();
},
drawCurvature(api, curve, omni) {
api.drawSkeleton(curve);
api.drawCurve(curve);
var s, t, p, n, c, ox, oy;
for( s=0; s<256; s++) {
// Draw the curvature as a coloured line at the
// current point, along the normal.
api.setColor('rgba(255,127,'+s+',0.6)');
t = s/255;
p = curve.get(t);
n = curve.normal(t);
c = curve.curvature(t);
ox = c.k * n.x;
oy = c.k * n.y;
api.drawLine(p, { x: p.x + ox, y: p.y + oy });
// And if requested, also draw it along the anti-normal.
if (omni) {
api.setColor('rgba('+s+',127,255,0.6)');
api.drawLine(p, { x: p.x - ox, y: p.y - oy });
}
}
},
proxyDraw: function(api, curve, omni) {
api.reset();
this.updateCurves(api, curve);
[this.q, this.c].forEach(curve => this.drawCurvature(api, curve, omni));
},
draw: function(api, curve) {
this.proxyDraw(api, curve);
},
drawOmni: function(api, curve) {
this.proxyDraw(api, curve, true);
}
};
}())
},
"tracing": {
handler: (function() { return {
statics: {

155
package-lock.json generated
View File

@ -2296,9 +2296,9 @@
}
},
"bezier-js": {
"version": "2.2.18",
"resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-2.2.18.tgz",
"integrity": "sha512-RHAp07NiRCgqOVPjy1ZerP9zIghN6mKwsCnx2IinExqnKDomaZSpk6GvPxt+0L6E3F7c0rxfh+yniHnkT3SizQ==",
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/bezier-js/-/bezier-js-2.3.0.tgz",
"integrity": "sha512-no2TDnnCi3u+FQjFEy+Zh4ksrBGXue7ayDhiVLJ4io9FFyBIPvQNtZdA1OEsrR43sbJnVhfzbuDQ9paqpStx+Q==",
"dev": true
},
"big.js": {
@ -2967,6 +2967,12 @@
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=",
"dev": true
},
"corser": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/corser/-/corser-2.0.1.tgz",
"integrity": "sha1-jtolLsqrWEDc2XXOuQ2TcMgZ/4c=",
"dev": true
},
"create-ecdh": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.3.tgz",
@ -3559,6 +3565,32 @@
"jsbn": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz"
}
},
"ecstatic": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/ecstatic/-/ecstatic-3.3.0.tgz",
"integrity": "sha512-EblWYTd+wPIAMQ0U4oYJZ7QBypT9ZUIwpqli0bKDjeIIQnXDBK2dXtZ9yzRCOlkW1HkO8gn7/FxLK1yPIW17pw==",
"dev": true,
"requires": {
"he": "1.2.0",
"mime": "1.6.0",
"minimist": "1.2.0",
"url-join": "2.0.5"
},
"dependencies": {
"mime": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true
},
"minimist": {
"version": "1.2.0",
"resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
"dev": true
}
}
},
"electron-to-chromium": {
"version": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.8.tgz",
"integrity": "sha1-ssiix5u4n7v9NyTZVV4VCVtfX7Y=",
@ -4038,6 +4070,12 @@
"es5-ext": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.15.tgz"
}
},
"eventemitter3": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.0.tgz",
"integrity": "sha512-ivIvhpq/Y0uSjcHDcOIccjmYjGLcP09MFGE7ysAwkAvkXfpZlC985pH2/ui64DKazbTW/4kN3yqozUxlXzI6cA==",
"dev": true
},
"events": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
@ -4362,6 +4400,32 @@
"readable-stream": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.2.9.tgz"
}
},
"follow-redirects": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.5.10.tgz",
"integrity": "sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==",
"dev": true,
"requires": {
"debug": "3.1.0"
},
"dependencies": {
"debug": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
"integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
"dev": true,
"requires": {
"ms": "2.0.0"
}
},
"ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=",
"dev": true
}
}
},
"for-in": {
"version": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=",
@ -5293,6 +5357,12 @@
"sntp": "https://registry.npmjs.org/sntp/-/sntp-1.0.9.tgz"
}
},
"he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"dev": true
},
"history": {
"version": "https://registry.npmjs.org/history/-/history-1.17.0.tgz",
"integrity": "sha1-xUg8qlodH+oAoafY0ZuHQBZxHSk=",
@ -5341,6 +5411,41 @@
"integrity": "sha1-DfKTUfByEWNRXfueVUPl9u7VFi8=",
"dev": true
},
"http-proxy": {
"version": "1.17.0",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.17.0.tgz",
"integrity": "sha512-Taqn+3nNvYRfJ3bGvKfBSRwy1v6eePlm3oc/aWVxZp57DQr5Eq3xhKJi7Z4hZpS8PC3H4qI+Yly5EmFacGuA/g==",
"dev": true,
"requires": {
"eventemitter3": "3.1.0",
"follow-redirects": "1.5.10",
"requires-port": "1.0.0"
}
},
"http-server": {
"version": "0.11.1",
"resolved": "https://registry.npmjs.org/http-server/-/http-server-0.11.1.tgz",
"integrity": "sha512-6JeGDGoujJLmhjiRGlt8yK8Z9Kl0vnl/dQoQZlc4oeqaUoAKQg94NILLfrY3oWzSyFaQCVNTcKE5PZ3cH8VP9w==",
"dev": true,
"requires": {
"colors": "1.0.3",
"corser": "2.0.1",
"ecstatic": "3.3.0",
"http-proxy": "1.17.0",
"opener": "1.4.3",
"optimist": "0.6.1",
"portfinder": "1.0.19",
"union": "0.4.6"
},
"dependencies": {
"colors": {
"version": "1.0.3",
"resolved": "http://registry.npmjs.org/colors/-/colors-1.0.3.tgz",
"integrity": "sha1-BDP0TYCWgP3rYO0mDxsMJi6CpAs=",
"dev": true
}
}
},
"http-signature": {
"version": "https://registry.npmjs.org/http-signature/-/http-signature-1.1.1.tgz",
"integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=",
@ -8718,6 +8823,12 @@
"integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=",
"dev": true
},
"opener": {
"version": "1.4.3",
"resolved": "https://registry.npmjs.org/opener/-/opener-1.4.3.tgz",
"integrity": "sha1-XG2ixdflgx6P+jlklQ+NZnSskLg=",
"dev": true
},
"optimist": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz",
@ -9281,6 +9392,17 @@
"find-up": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz"
}
},
"portfinder": {
"version": "1.0.19",
"resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.19.tgz",
"integrity": "sha512-23aeQKW9KgHe6citUrG3r9HjeX6vls0h713TAa+CwTKZwNIr/pD2ApaxYF4Um3ZZyq4ar+Siv3+fhoHaIwSOSw==",
"dev": true,
"requires": {
"async": "1.5.2",
"debug": "https://registry.npmjs.org/debug/-/debug-2.6.4.tgz",
"mkdirp": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz"
}
},
"posix-character-classes": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
@ -9840,6 +9962,12 @@
"integrity": "sha1-3QG6ydBtMObyGa7LglPunr3DCPE=",
"dev": true
},
"qs": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-2.3.3.tgz",
"integrity": "sha1-6eha2+ddoLvkyOBHaghikPhjtAQ=",
"dev": true
},
"query-string": {
"version": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
"integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=",
@ -10298,6 +10426,12 @@
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=",
"dev": true
},
"requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=",
"dev": true
},
"resolve": {
"version": "https://registry.npmjs.org/resolve/-/resolve-1.3.3.tgz",
"integrity": "sha1-ZVkHw0aahoDcLeOidaj91paR8OU=",
@ -11566,6 +11700,15 @@
}
}
},
"union": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/union/-/union-0.4.6.tgz",
"integrity": "sha1-GY+9rrolTniLDvy2MLwR8kopWeA=",
"dev": true,
"requires": {
"qs": "2.3.3"
}
},
"union-value": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.0.tgz",
@ -11730,6 +11873,12 @@
}
}
},
"url-join": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/url-join/-/url-join-2.0.5.tgz",
"integrity": "sha1-WvIvGMBSoACkjXuCxenC4v7tpyg=",
"dev": true
},
"use": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz",

View File

@ -21,7 +21,7 @@
"make:localizedpages": "node tools/generate-page-content",
"default": "node tools/copy-default-locale",
"latex": "node tools/tex-to-svg",
"dev": "npm-run-all bootstrap --parallel dev:* http-server",
"dev": "npm-run-all bootstrap --parallel dev:en-GB server",
"dev:en-GB": "cross-env LOCALE=en-GB webpack",
"dev:zh-CN": "cross-env LOCALE=zh-CN webpack",
"dev:ja-JP": "cross-env LOCALE=ja-JP webpack",
@ -58,7 +58,7 @@
"babel-preset-es2015": "^6.3.13",
"babel-preset-react": "^6.3.13",
"babel-register": "^6.4.3",
"bezier-js": "^2.2.18",
"bezier-js": "^2.3.0",
"block-loader": "^2.0.0",
"chokidar": "^2.0.4",
"chroma-js": "^1.1.1",
@ -73,6 +73,7 @@
"glob": "^7.1.1",
"history": "^1.17.0",
"html-entities": "^1.2.0",
"http-server": "^0.11.1",
"image-size": "^0.4.0",
"jsmin": "^1.0.1",
"json-loader": "^0.5.4",

View File

@ -11,5 +11,4 @@ var html = fs.readFileSync(path.join(BASEDIR, "index.html")).toString();
html = html.replace(' <base href="..">\n', '');
html = html.replace('className=', 'class=');
html = html.replace('<script src="en-GB/article.js', '<script src="article.js');
html = "<!-- AUTOGENERATED CONTENT, PLEASE EDIT 'index.template.html' INSTEAD! -->\n" + html;
fs.writeFileSync(path.join(BASEDIR, "index.html"), html);

File diff suppressed because one or more lines are too long