diff --git a/components/Article.jsx b/components/Article.jsx index 2fea049f..c4619c7d 100644 --- a/components/Article.jsx +++ b/components/Article.jsx @@ -34,7 +34,8 @@ var Article = React.createClass({ generateNavItem: function(section, entry) { var name = section.props.name; - return
With that in place, all that's left now is to "restart" the procedure by treating the found arc's end point as the new to-be-determined arc's starting point, and using points further down the curve. We @@ -246,7 +245,7 @@ var Introduction = React.createClass({ so you can see how picking a different threshold changes the number of arcs that are necessary to reasonably approximate a curve:
-So... what is this good for? Obviously, If you're working with technologies that can't do curves,
but can do lines and circles, then the answer is pretty straight-forward, but what else? There are
@@ -265,4 +264,4 @@ var Introduction = React.createClass({
}
});
-module.exports = Introduction;
+module.exports = keyHandling(Introduction);
diff --git a/components/sections/arclengthapprox/index.js b/components/sections/arclengthapprox/index.js
index 734821ea..5c162b08 100644
--- a/components/sections/arclengthapprox/index.js
+++ b/components/sections/arclengthapprox/index.js
@@ -1,8 +1,24 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
+var keyHandling = require("../../decorators/keyhandling-decorator.jsx");
var ArclengthApprox = React.createClass({
+ statics: {
+ keyHandlingOptions: {
+ propName: "steps",
+ values: {
+ "38": 1, // up arrow
+ "40": -1 // down arrow
+ },
+ controller: function(api) {
+ if (api.steps < 1) {
+ api.steps = 1;
+ }
+ }
+ }
+ },
+
getDefaultProps: function() {
return {
title: "Approximated arc length"
@@ -51,23 +67,6 @@ var ArclengthApprox = React.createClass({
api.text("Approximate length, "+api.steps+" steps: "+alen+" (true: "+len+")", {x:10, y: 15});
},
- values: {
- "38": 1, // up arrow
- "40": -1 // down arrow
- },
-
- onKeyDown: function(e, api) {
- var v = this.values[e.keyCode];
- if(v) {
- e.preventDefault();
- api.steps += v;
- if (api.steps < 1) {
- api.steps = 1;
- }
- console.log(api.steps);
- }
- },
-
render: function() {
return (
If we combine the work done in the previous sections on curve flattening and arc length computation, we can
implement these with minimal effort: Try clicking on the sketch and using your up and down arrow keys to lower the number of segments for both
the quadratic and cubic curve. You may notice that the error in length is actually pretty significant, even if
@@ -94,87 +93,4 @@ var ArclengthApprox = React.createClass({
}
});
-module.exports = ArclengthApprox;
-
-/*
-
- void setupCurve() {
- setupDefaultQuadratic();
- offsetting();
- offset = 16;
- }
-
- void drawCurve(BezierCurve curve) {
- additionals();
- curve.draw();
-
- nextPanel();
- stroke(0);
- float x = curve.getXValue(0),
- y = curve.getYValue(0),
- x2, y2, step = 1/offset, t,
- length=0;
- for(int i=1; i<=offset; i++) {
- t = i*step;
- x2 = curve.getXValue(t);
- y2 = curve.getYValue(t);
- line(x,y,x2,y2);
- length += dist(x,y,x2,y2);
- x = x2;
- y = y2;
- }
-
- float arclength = curve.getCurveLength();
- float error = 100 * (arclength - length) / arclength;
-
- length = nfc(length, 3, 3);
- arclength = nfc(arclength, 3, 3);
- error = nfc(error, 3, 3);
- if(error.indexOf(".")===0) { error = "0" + error; }
-
- fill(0);
- text("Approximate arc length based on "+offset+" segments: " + length, -dim/4, dim-20);
- text("True length: " + arclength + ", error: " + error + "%", -dim/4, dim-5);
- }
-
-
- void setupCurve() {
- setupDefaultCubic();
- offsetting();
- offset = 24;
- }
-
- void drawCurve(BezierCurve curve) {
- additionals();
- curve.draw();
-
- nextPanel();
- stroke(0);
- float x = curve.getXValue(0),
- y = curve.getYValue(0),
- x2, y2, step = 1/offset, t,
- length=0;
- for(int i=1; i<=offset; i++) {
- t = i*step;
- x2 = curve.getXValue(t);
- y2 = curve.getYValue(t);
- line(x,y,x2,y2);
- length += dist(x,y,x2,y2);
- x = x2;
- y = y2;
- }
-
- float arclength = curve.getCurveLength();
- float error = 100 * (arclength - length) / arclength;
-
- length = nfc(length, 3, 3);
- arclength = nfc(arclength, 3, 3);
- error = nfc(error, 3, 3);
- if(error.indexOf(".")===0) { error = "0" + error; }
-
- fill(0);
- text("Approximate arc length based on "+offset+" segments: " + length, -dim/4, dim-20);
- text("True length: " + arclength + ", error: " + error + "%", -dim/4, dim-5);
- }
-
- */
\ No newline at end of file
+module.exports = keyHandling(ArclengthApprox);
\ No newline at end of file
diff --git a/components/sections/catmullmoulding/index.js b/components/sections/catmullmoulding/index.js
index f3a4f25e..57563774 100644
--- a/components/sections/catmullmoulding/index.js
+++ b/components/sections/catmullmoulding/index.js
@@ -1,8 +1,19 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
+var keyHandling = require("../../decorators/keyhandling-decorator.jsx");
var CatmullRomMoulding = React.createClass({
+ statics: {
+ keyHandlingOptions: {
+ propName: "distance",
+ values: {
+ "38": 1, // up arrow
+ "40": -1 // down arrow
+ }
+ }
+ },
+
getDefaultProps: function() {
return {
title: "Creating a Catmull-Rom curve from three points"
@@ -19,16 +30,6 @@ var CatmullRomMoulding = React.createClass({
api.distance = 0;
},
- onKeyDown: function(evt, api) {
- if (evt.key === "ArrowUp") {
- evt.preventDefault();
- api.distance += 1;
- } else if (evt.key === "ArrowDown") {
- evt.preventDefault();
- api.distance -= 1;
- }
- },
-
convert: function(p1, p2, p3, p4) {
var t = 0.5;
return [
@@ -167,7 +168,7 @@ var CatmullRomMoulding = React.createClass({
we want to do this? Because the line p0--p2 acts as departure tangent at p1, and the line p2--p4 acts as
arrival tangent at p3. Play around with the graphic a bit to get an idea of what all of that meant: As should be obvious by now, Catmull-Rom curves are great for "fitting a curvature to some points", but if we want
to convert that curve to Bézier form we're going to end up with a lot of separate (but visually joined) Bézier curves.
@@ -178,4 +179,4 @@ var CatmullRomMoulding = React.createClass({
}
});
-module.exports = CatmullRomMoulding;
+module.exports = keyHandling(CatmullRomMoulding);
diff --git a/components/sections/explanation/index.js b/components/sections/explanation/index.js
index e99d5e0e..7d99e7d2 100644
--- a/components/sections/explanation/index.js
+++ b/components/sections/explanation/index.js
@@ -1,30 +1,30 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
+var keyHandling = require("../../decorators/keyhandling-decorator.jsx");
var Explanation = React.createClass({
+ statics: {
+ keyHandlingOptions: {
+ propName: "step",
+ values: {
+ "38": 0.1, // up arrow
+ "40": -0.1 // down arrow
+ },
+ controller: function(api) {
+ if (api.step < 0.1) {
+ api.step = 0.1;
+ }
+ }
+ }
+ },
+
getDefaultProps: function() {
return {
title: "The mathematics of Bézier curves"
};
},
- values: {
- "38": 0.1, // up arrow
- "40": -0.1 // down arrow
- },
-
- onKeyDown: function(e, api) {
- var v = this.values[e.keyCode];
- if(v) {
- e.preventDefault();
- api.step += v;
- if (api.step < 0.1) {
- api.step = 0.1;
- }
- }
- },
-
setup: function(api) {
api.step = 5;
},
@@ -126,7 +126,7 @@ var Explanation = React.createClass({
radius 1 around the origin (0,0). If we plot it for t from 0 to 5, we get this (use
your up and down cursor keys to change the plot end value): Bézier curves are (one in many classes of) parametric functions, and are characterised
by using the same base function for all its dimensions. Unlike the above example,
@@ -277,4 +277,4 @@ function Bezier(3,t):
}
});
-module.exports = Explanation;
+module.exports = keyHandling(Explanation);
diff --git a/components/sections/flattening/index.js b/components/sections/flattening/index.js
index 5d2f39ed..9de250e6 100644
--- a/components/sections/flattening/index.js
+++ b/components/sections/flattening/index.js
@@ -1,8 +1,24 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
+var keyHandling = require("../../decorators/keyhandling-decorator.jsx");
var Flattening = React.createClass({
+ statics: {
+ keyHandlingOptions: {
+ propName: "steps",
+ values: {
+ "38": 1, // up arrow
+ "40": -1 // down arrow
+ },
+ controller: function(api) {
+ if (api.steps < 1) {
+ api.steps = 1;
+ }
+ }
+ }
+ },
+
getDefaultProps: function() {
return {
title: "Simplified drawing"
@@ -106,4 +122,4 @@ var Flattening = React.createClass({
}
});
-module.exports = Flattening;
+module.exports = keyHandling(Flattening);
diff --git a/components/sections/graduatedoffset/index.js b/components/sections/graduatedoffset/index.js
index c4be72d3..f91cbd1c 100644
--- a/components/sections/graduatedoffset/index.js
+++ b/components/sections/graduatedoffset/index.js
@@ -1,8 +1,19 @@
var React = require("react");
var Graphic = require("../../Graphic.jsx");
var SectionHeader = require("../../SectionHeader.jsx");
+var keyHandling = require("../../decorators/keyhandling-decorator.jsx");
var GraduatedOffsetting = React.createClass({
+ statics: {
+ keyHandlingOptions: {
+ propName: "distance",
+ values: {
+ "38": 1, // up arrow
+ "40": -1 // down arrow
+ }
+ }
+ },
+
getDefaultProps: function() {
return {
title: "Graduated curve offsetting"
@@ -35,19 +46,6 @@ var GraduatedOffsetting = React.createClass({
outline.curves.forEach(c => api.drawCurve(c));
},
- values: {
- "38": 1, // up arrow
- "40": -1 // down arrow
- },
-
- onKeyDown: function(e, api) {
- var v = this.values[e.keyCode];
- if(v) {
- e.preventDefault();
- api.distance += v;
- }
- },
-
render: function() {
return (
-
+
+
+
+
-
-
+
+
You may notice that this may still lead to small 'jumps' in the sub-curves when moving the curve around. This is caused by the fact that we're still performing a naive form of offsetting, @@ -196,4 +194,4 @@ var Offsetting = React.createClass({ } }); -module.exports = Offsetting; +module.exports = keyHandling(Offsetting); diff --git a/components/sections/preface/index.js b/components/sections/preface/index.js index f59caaeb..08776dde 100644 --- a/components/sections/preface/index.js +++ b/components/sections/preface/index.js @@ -47,15 +47,19 @@ var Preface = React.createClass({
So, what if you need to program them yourself? What are the pitfalls? How do you draw them? What are the bounding boxes, how do you determine intersections, how can you extrude a curve, in short: how do you do everything that you might want when you do with these curves? That's - what this page is for. Prepare to be mathed.
+ what this page is for. Prepare to be mathed! -—Pomax (or in the tweetworld, @TheRealPomax)
-This page uses interactive examples, as well as "real" maths (in LaTeX form) which - is typeset using the most excellent MathJax library. - This page is still in rewriting, but once done, all examples will also have a "view source" - option, which lets you see how things were implemented using the Bezier.js library.
+This page uses interactive examples, relying heavily on Bezier.js, + as well as "real" maths (in LaTeX form) which is typeset using the most excellent MathJax library. + The page is generated offline as a React application, using Webpack, which has made adding + "view source" options considerably more challenging. I'm still trying to figure out how to + add them back in, but it didn't feel like it should hold up deploying this update compared + to the previous years' version.
—Pomax (or in the tweetworld, @TheRealPomax)
We can apply this to a (semi) random curve, as is done in the following graphic. Select the sketch and press your up and down cursor keys to elevate or lower the curve order.
-There is a good, if mathematical, explanation on the matrices necessary for optimal reduction over on Sirver's Castle, @@ -157,4 +162,4 @@ var Reordering = React.createClass({ } }); -module.exports = Reordering; +module.exports = keyHandling(Reordering); diff --git a/components/sections/tracing/index.js b/components/sections/tracing/index.js index 42998fc8..bfd4ca39 100644 --- a/components/sections/tracing/index.js +++ b/components/sections/tracing/index.js @@ -1,8 +1,24 @@ var React = require("react"); var Graphic = require("../../Graphic.jsx"); var SectionHeader = require("../../SectionHeader.jsx"); +var keyHandling = require("../../decorators/keyhandling-decorator.jsx"); var Tracing = React.createClass({ + statics: { + keyHandlingOptions: { + propName: "steps", + values: { + "38": 1, // up arrow + "40": -1 // down arrow + }, + controller: function(api) { + if (api.steps < 1) { + api.steps = 1; + } + } + } + }, + getDefaultProps: function() { return { title: "Tracing a curve at fixed distance intervals" @@ -60,23 +76,6 @@ var Tracing = React.createClass({ } }, - values: { - "38": 1, // up arrow - "40": -1 // down arrow - }, - - onKeyDown: function(e, api) { - var v = this.values[e.keyCode]; - if(v) { - e.preventDefault(); - api.steps += v; - if (api.steps < 1) { - api.steps = 1; - } - console.log(api.steps); - } - }, - drawColoured: function(api, curve) { api.setPanelCount(3); var w = api.getPanelWidth(); @@ -155,11 +154,11 @@ var Tracing = React.createClass({ apart. In fact, let's look at the relation between "distance long a curve" and "t value", by plotting them against one another.
-The following graphic shows a particularly illustrative curve, and it's length-to-t plot. +
The following graphic shows a particularly illustrative curve, and it's length-to-t plot. For linear traversal, this line needs to be straight, running from (0,0) to (length,1). This is, it's safe to say, not what we'll see, we'll see something wobbly instead. To make matters even worse, the length-to-t function is also of a much higher order than our curve is: while - the curve we're using for this exercise is a cubic curve, able to switch concave/convex form twice + the curve we're using for this exercise is a cubic curve, which can switch concave/convex form once at best, the plot shows that the distance function along the curve is able to switch forms three times (to see this, try creating an S curve with the start/end close together, but the control points far apart).
@@ -183,7 +182,7 @@ var Tracing = React.createClass({ along the horizontal axis. It also shows the curve in an alternating colouring based on the t-for-distance values we find our LUT: -Use your up and down arrow keys to increase or decrease the number of equidistant segments used to colour the curve.
@@ -199,4 +198,4 @@ var Tracing = React.createClass({ } }); -module.exports = Tracing; +module.exports = keyHandling(Tracing); diff --git a/index.html b/index.html index 2785ddfc..c4508cf3 100644 --- a/index.html +++ b/index.html @@ -16,34 +16,41 @@ - -