1
0
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:
Pomax
2018-11-16 14:57:46 -08:00
parent 9eb0692e1c
commit 9119af9e3b
5 changed files with 192 additions and 12 deletions

View File

@@ -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();

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);