mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-19 15:01:57 +02:00
source docs for [a] handlers
This commit is contained in:
@@ -1,17 +1,31 @@
|
||||
module.exports = {
|
||||
/**
|
||||
* Setup function for a default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup function for a default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* A coordinate rotation function that rotates and
|
||||
* translates the curve, such that the first coordinate
|
||||
* of the curve is (0,0) and the last coordinate is (..., 0)
|
||||
*/
|
||||
align: function(points, line) {
|
||||
var tx = line.p1.x,
|
||||
ty = line.p1.y,
|
||||
// The atan2 function is so important to computing
|
||||
// that most CPUs have a dedicated implementation
|
||||
// at the hardware level for it.
|
||||
a = -Math.atan2(line.p2.y-ty, line.p2.x-tx),
|
||||
cos = Math.cos,
|
||||
sin = Math.sin,
|
||||
@@ -24,6 +38,10 @@ module.exports = {
|
||||
return points.map(d);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a curve and its aligned counterpart
|
||||
* side by side across two panels.
|
||||
*/
|
||||
draw: function(api, curve) {
|
||||
api.setPanelCount(2);
|
||||
api.reset();
|
||||
|
@@ -1,6 +1,9 @@
|
||||
var atan2 = Math.atan2, PI = Math.PI, TAU = 2*PI, cos = Math.cos, sin = Math.sin;
|
||||
|
||||
module.exports = {
|
||||
// These are functions that can be called "From the page",
|
||||
// rather than being internal to the sketch. This is useful
|
||||
// for making on-page controls hook into the sketch code.
|
||||
statics: {
|
||||
keyHandlingOptions: {
|
||||
propName: "error",
|
||||
@@ -16,22 +19,39 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup up a skeleton curve that, when using its
|
||||
* points for a B-spline, can form a circle.
|
||||
*/
|
||||
setupCircle: function(api) {
|
||||
var curve = new api.Bezier(70,70, 140,40, 240,130);
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
api.error = 0.5;
|
||||
},
|
||||
|
||||
/**
|
||||
* Given three points, find the (only!) circle
|
||||
* that passes through all three points, based
|
||||
* on the fact that the perpendiculars of the
|
||||
* chords between the points all cross each
|
||||
* other at the center of that circle.
|
||||
*/
|
||||
getCCenter: function(api, p1, p2, p3) {
|
||||
// deltas
|
||||
var dx1 = (p2.x - p1.x),
|
||||
@@ -69,15 +89,9 @@ module.exports = {
|
||||
// determine arc direction (cw/ccw correction)
|
||||
var __;
|
||||
if (s<e) {
|
||||
// if s<m<e, arc(s, e)
|
||||
// if m<s<e, arc(e, s + TAU)
|
||||
// if s<e<m, arc(e, s + TAU)
|
||||
if (s>m || m>e) { s += TAU; }
|
||||
if (s>e) { __=e; e=s; s=__; }
|
||||
} else {
|
||||
// if e<m<s, arc(e, s)
|
||||
// if m<e<s, arc(s, e + TAU)
|
||||
// if e<s<m, arc(s, e + TAU)
|
||||
if (e<m && m<s) { __=e; e=s; s=__; } else { e += TAU; }
|
||||
}
|
||||
|
||||
@@ -88,6 +102,9 @@ module.exports = {
|
||||
return i;
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the circle-computation sketch
|
||||
*/
|
||||
drawCircle: function(api, curve) {
|
||||
api.reset();
|
||||
var pts = curve.points;
|
||||
@@ -127,6 +144,10 @@ module.exports = {
|
||||
api.text("Intersection point", C, {x:-25, y:10});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a single arc being fit to a Bezier curve,
|
||||
* to show off the general application.
|
||||
*/
|
||||
drawSingleArc: function(api, curve) {
|
||||
api.reset();
|
||||
var arcs = curve.arcs(api.error);
|
||||
@@ -143,6 +164,9 @@ module.exports = {
|
||||
api.text("Arc approximation with total error " + api.utils.round(api.error,1), {x:10, y:15});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw an arc approximation for an entire Bezier curve.
|
||||
*/
|
||||
drawArcs: function(api, curve) {
|
||||
api.reset();
|
||||
var arcs = curve.arcs(api.error);
|
||||
|
@@ -2,6 +2,11 @@ var sin = Math.sin;
|
||||
var tau = Math.PI*2;
|
||||
|
||||
module.exports = {
|
||||
/**
|
||||
* Set up a sinusoid generating function,
|
||||
* which we'll use to draw the "progressively
|
||||
* better looking" integral approximations.
|
||||
*/
|
||||
setup: function(api) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -22,6 +27,9 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the generator's sine function:
|
||||
*/
|
||||
drawSine: function(api, dheight) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -33,6 +41,12 @@ module.exports = {
|
||||
api.drawFunction(generator, {x:0, y:h/2});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sliced between the sine curve and
|
||||
* the x-axis, with a variable number of steps so
|
||||
* we can show the approximation becoming better
|
||||
* and better as we increase the step count.
|
||||
*/
|
||||
drawSlices: function(api, steps) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -44,11 +58,15 @@ module.exports = {
|
||||
api.setFill("rgba(150,150,255, 0.4)");
|
||||
for (var step=tau/steps, i=step/2, v, p1, p2; i<tau+step/2; i+=step) {
|
||||
v = this.generator(i);
|
||||
|
||||
// draw a rectangular strip between the curve and the x-axis:
|
||||
p1 = {x:v.x - f*step/2 + c, y: 0};
|
||||
p2 = {x:v.x + f*step/2 - c, y: v.y * this.generator.scale};
|
||||
|
||||
if (!c) { api.setFill("rgba(150,150,255,"+(0.4 + 0.3*Math.random())+")"); }
|
||||
api.drawRect(p1, p2, {x:0, y:h/2});
|
||||
|
||||
// and keep track of the (much simpler to compute) approximated area under the curve so far:
|
||||
area += step * Math.abs(v.y * this.generator.scale);
|
||||
}
|
||||
api.setFill("black");
|
||||
@@ -57,29 +75,45 @@ module.exports = {
|
||||
api.text("Approximating with "+steps+" strips (true area: "+trueArea+"): " + currArea, {x: 10, y: h-15});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 10 slice approximation:
|
||||
*/
|
||||
drawCoarseIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 10);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 24 slice approximation:
|
||||
*/
|
||||
drawFineIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 24);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 99 slice approximation:
|
||||
*/
|
||||
drawSuperFineIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 99);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up a default cubic curve for which we'll be determining
|
||||
* its length, using the iterative integral approach:
|
||||
*/
|
||||
setupCurve: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw our curve, and show its computed length:
|
||||
*/
|
||||
drawCurve: function(api, curve) {
|
||||
api.reset();
|
||||
api.drawSkeleton(curve);
|
||||
|
@@ -1,4 +1,7 @@
|
||||
module.exports = {
|
||||
// These are functions that can be called "From the page",
|
||||
// rather than being internal to the sketch. This is useful
|
||||
// for making on-page controls hook into the sketch code.
|
||||
statics: {
|
||||
keyHandlingOptions: {
|
||||
propName: "steps",
|
||||
@@ -14,18 +17,29 @@ module.exports = {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
api.steps = 10;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
api.steps = 16;
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a curve and its polygon-approximation,
|
||||
* showing the "true" length of the curve vs. the
|
||||
* length based on tallying up the polygon sections.
|
||||
*/
|
||||
draw: function(api, curve) {
|
||||
api.reset();
|
||||
api.drawSkeleton(curve);
|
||||
|
@@ -1161,19 +1161,33 @@ return {
|
||||
},
|
||||
"aligning": {
|
||||
handler: (function() { return {
|
||||
/**
|
||||
* Setup function for a default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup function for a default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* A coordinate rotation function that rotates and
|
||||
* translates the curve, such that the first coordinate
|
||||
* of the curve is (0,0) and the last coordinate is (..., 0)
|
||||
*/
|
||||
align: function(points, line) {
|
||||
var tx = line.p1.x,
|
||||
ty = line.p1.y,
|
||||
// The atan2 function is so important to computing
|
||||
// that most CPUs have a dedicated implementation
|
||||
// at the hardware level for it.
|
||||
a = -Math.atan2(line.p2.y-ty, line.p2.x-tx),
|
||||
cos = Math.cos,
|
||||
sin = Math.sin,
|
||||
@@ -1186,6 +1200,10 @@ return {
|
||||
return points.map(d);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a curve and its aligned counterpart
|
||||
* side by side across two panels.
|
||||
*/
|
||||
draw: function(api, curve) {
|
||||
api.setPanelCount(2);
|
||||
api.reset();
|
||||
@@ -1579,6 +1597,11 @@ return sketch;
|
||||
var tau = Math.PI*2;
|
||||
|
||||
return {
|
||||
/**
|
||||
* Set up a sinusoid generating function,
|
||||
* which we'll use to draw the "progressively
|
||||
* better looking" integral approximations.
|
||||
*/
|
||||
setup: function(api) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -1599,6 +1622,9 @@ return {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the generator's sine function:
|
||||
*/
|
||||
drawSine: function(api, dheight) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -1610,6 +1636,12 @@ return {
|
||||
api.drawFunction(generator, {x:0, y:h/2});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sliced between the sine curve and
|
||||
* the x-axis, with a variable number of steps so
|
||||
* we can show the approximation becoming better
|
||||
* and better as we increase the step count.
|
||||
*/
|
||||
drawSlices: function(api, steps) {
|
||||
var w = api.getPanelWidth();
|
||||
var h = api.getPanelHeight();
|
||||
@@ -1621,11 +1653,15 @@ return {
|
||||
api.setFill("rgba(150,150,255, 0.4)");
|
||||
for (var step=tau/steps, i=step/2, v, p1, p2; i<tau+step/2; i+=step) {
|
||||
v = this.generator(i);
|
||||
|
||||
// draw a rectangular strip between the curve and the x-axis:
|
||||
p1 = {x:v.x - f*step/2 + c, y: 0};
|
||||
p2 = {x:v.x + f*step/2 - c, y: v.y * this.generator.scale};
|
||||
|
||||
if (!c) { api.setFill("rgba(150,150,255,"+(0.4 + 0.3*Math.random())+")"); }
|
||||
api.drawRect(p1, p2, {x:0, y:h/2});
|
||||
|
||||
// and keep track of the (much simpler to compute) approximated area under the curve so far:
|
||||
area += step * Math.abs(v.y * this.generator.scale);
|
||||
}
|
||||
api.setFill("black");
|
||||
@@ -1634,29 +1670,45 @@ return {
|
||||
api.text("Approximating with "+steps+" strips (true area: "+trueArea+"): " + currArea, {x: 10, y: h-15});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 10 slice approximation:
|
||||
*/
|
||||
drawCoarseIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 10);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 24 slice approximation:
|
||||
*/
|
||||
drawFineIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 24);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the sine curve, with a 99 slice approximation:
|
||||
*/
|
||||
drawSuperFineIntegral: function(api) {
|
||||
api.reset();
|
||||
this.drawSlices(api, 99);
|
||||
this.drawSine(api);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up a default cubic curve for which we'll be determining
|
||||
* its length, using the iterative integral approach:
|
||||
*/
|
||||
setupCurve: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw our curve, and show its computed length:
|
||||
*/
|
||||
drawCurve: function(api, curve) {
|
||||
api.reset();
|
||||
api.drawSkeleton(curve);
|
||||
@@ -1670,6 +1722,9 @@ return {
|
||||
},
|
||||
"arclengthapprox": {
|
||||
handler: (function() { return {
|
||||
// These are functions that can be called "From the page",
|
||||
// rather than being internal to the sketch. This is useful
|
||||
// for making on-page controls hook into the sketch code.
|
||||
statics: {
|
||||
keyHandlingOptions: {
|
||||
propName: "steps",
|
||||
@@ -1685,18 +1740,29 @@ return {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
api.steps = 10;
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
api.steps = 16;
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a curve and its polygon-approximation,
|
||||
* showing the "true" length of the curve vs. the
|
||||
* length based on tallying up the polygon sections.
|
||||
*/
|
||||
draw: function(api, curve) {
|
||||
api.reset();
|
||||
api.drawSkeleton(curve);
|
||||
@@ -3599,6 +3665,9 @@ return {
|
||||
handler: (function() { var atan2 = Math.atan2, PI = Math.PI, TAU = 2*PI, cos = Math.cos, sin = Math.sin;
|
||||
|
||||
return {
|
||||
// These are functions that can be called "From the page",
|
||||
// rather than being internal to the sketch. This is useful
|
||||
// for making on-page controls hook into the sketch code.
|
||||
statics: {
|
||||
keyHandlingOptions: {
|
||||
propName: "error",
|
||||
@@ -3614,22 +3683,39 @@ return {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Setup up a skeleton curve that, when using its
|
||||
* points for a B-spline, can form a circle.
|
||||
*/
|
||||
setupCircle: function(api) {
|
||||
var curve = new api.Bezier(70,70, 140,40, 240,130);
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default quadratic curve.
|
||||
*/
|
||||
setupQuadratic: function(api) {
|
||||
var curve = api.getDefaultQuadratic();
|
||||
api.setCurve(curve);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set up the default cubic curve.
|
||||
*/
|
||||
setupCubic: function(api) {
|
||||
var curve = api.getDefaultCubic();
|
||||
api.setCurve(curve);
|
||||
api.error = 0.5;
|
||||
},
|
||||
|
||||
/**
|
||||
* Given three points, find the (only!) circle
|
||||
* that passes through all three points, based
|
||||
* on the fact that the perpendiculars of the
|
||||
* chords between the points all cross each
|
||||
* other at the center of that circle.
|
||||
*/
|
||||
getCCenter: function(api, p1, p2, p3) {
|
||||
// deltas
|
||||
var dx1 = (p2.x - p1.x),
|
||||
@@ -3667,15 +3753,9 @@ return {
|
||||
// determine arc direction (cw/ccw correction)
|
||||
var __;
|
||||
if (s<e) {
|
||||
// if s<m<e, arc(s, e)
|
||||
// if m<s<e, arc(e, s + TAU)
|
||||
// if s<e<m, arc(e, s + TAU)
|
||||
if (s>m || m>e) { s += TAU; }
|
||||
if (s>e) { __=e; e=s; s=__; }
|
||||
} else {
|
||||
// if e<m<s, arc(e, s)
|
||||
// if m<e<s, arc(s, e + TAU)
|
||||
// if e<s<m, arc(s, e + TAU)
|
||||
if (e<m && m<s) { __=e; e=s; s=__; } else { e += TAU; }
|
||||
}
|
||||
|
||||
@@ -3686,6 +3766,9 @@ return {
|
||||
return i;
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw the circle-computation sketch
|
||||
*/
|
||||
drawCircle: function(api, curve) {
|
||||
api.reset();
|
||||
var pts = curve.points;
|
||||
@@ -3725,6 +3808,10 @@ return {
|
||||
api.text("Intersection point", C, {x:-25, y:10});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw a single arc being fit to a Bezier curve,
|
||||
* to show off the general application.
|
||||
*/
|
||||
drawSingleArc: function(api, curve) {
|
||||
api.reset();
|
||||
var arcs = curve.arcs(api.error);
|
||||
@@ -3741,6 +3828,9 @@ return {
|
||||
api.text("Arc approximation with total error " + api.utils.round(api.error,1), {x:10, y:15});
|
||||
},
|
||||
|
||||
/**
|
||||
* Draw an arc approximation for an entire Bezier curve.
|
||||
*/
|
||||
drawArcs: function(api, curve) {
|
||||
api.reset();
|
||||
var arcs = curve.arcs(api.error);
|
||||
|
Reference in New Issue
Block a user