code comments
@@ -5,21 +5,23 @@ setup() {
|
|||||||
const degree = this.parameters.degree ?? 3;
|
const degree = this.parameters.degree ?? 3;
|
||||||
|
|
||||||
if (degree === 3) {
|
if (degree === 3) {
|
||||||
this.f = [
|
// there are three interpolation functions for quadratic curves
|
||||||
|
this.interpolationFunctions = [
|
||||||
t => ({ x: t * w, y: h * (1-t) ** 2 }),
|
t => ({ x: t * w, y: h * (1-t) ** 2 }),
|
||||||
t => ({ x: t * w, y: h * 2 * (1-t) * t }),
|
t => ({ x: t * w, y: h * 2 * (1-t) * t }),
|
||||||
t => ({ x: t * w, y: h * t ** 2 })
|
t => ({ x: t * w, y: h * t ** 2 })
|
||||||
];
|
];
|
||||||
} else if (degree === 4) {
|
} else if (degree === 4) {
|
||||||
this.f = [
|
// there are four interpolation functions for cubic curves
|
||||||
|
this.interpolationFunctions = [
|
||||||
t => ({ x: t * w, y: h * (1-t) ** 3 }),
|
t => ({ x: t * w, y: h * (1-t) ** 3 }),
|
||||||
t => ({ x: t * w, y: h * 3 * (1-t) ** 2 * t }),
|
t => ({ x: t * w, y: h * 3 * (1-t) ** 2 * t }),
|
||||||
t => ({ x: t * w, y: h * 3 * (1-t) * t ** 2 }),
|
t => ({ x: t * w, y: h * 3 * (1-t) * t ** 2 }),
|
||||||
t => ({ x: t * w, y: h * t ** 3})
|
t => ({ x: t * w, y: h * t ** 3})
|
||||||
];
|
];
|
||||||
} else {
|
} else {
|
||||||
this.triangle = [[1], [1,1]];
|
// there are many interpolations functions for more complex curves
|
||||||
this.f = [...new Array(degree + 1)].map((_,i) => {
|
this.interpolationFunctions = [...new Array(degree + 1)].map((_,i) => {
|
||||||
return t => ({
|
return t => ({
|
||||||
x: t * w,
|
x: t * w,
|
||||||
y: h * binomial(degree,i) * (1-t) ** (degree-i) * t ** (i)
|
y: h * binomial(degree,i) * (1-t) ** (degree-i) * t ** (i)
|
||||||
@@ -27,7 +29,11 @@ setup() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
this.s = this.f.map(f => plot(f, 0, 1, degree*5) );
|
// Build the graph for each interpolation function by plotting them,
|
||||||
|
// and capturing the resulting Shape object that yields. We'll draw
|
||||||
|
// those in the draw() function.
|
||||||
|
this.shapes = this.interpolationFunctions.map(f => plot(f, 0, 1, degree*5) );
|
||||||
|
|
||||||
setSlider(`.slide-control`, `position`, 0)
|
setSlider(`.slide-control`, `position`, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -36,39 +42,48 @@ draw() {
|
|||||||
setFill(`black`);
|
setFill(`black`);
|
||||||
setStroke(`black`);
|
setStroke(`black`);
|
||||||
|
|
||||||
|
// In order to plot things nicely, lets scale
|
||||||
|
// down, and plot things in a graph:
|
||||||
scale(0.8, 0.9);
|
scale(0.8, 0.9);
|
||||||
translate(40,20);
|
translate(40,20);
|
||||||
drawAxes(`t`, 0, 1, `S`, `0%`, `100%`);
|
drawAxes(`t`, 0, 1, `S`, `0%`, `100%`);
|
||||||
|
|
||||||
noFill();
|
noFill();
|
||||||
|
|
||||||
this.s.forEach((s,i) => {
|
// draw each of the function plots we built in setup()
|
||||||
|
this.shapes.forEach((shape,i) => {
|
||||||
|
// first, draw that plot's mid-line
|
||||||
setStroke(randomColor(0.2));
|
setStroke(randomColor(0.2));
|
||||||
line(
|
line(
|
||||||
i/(this.s.length-1) * this.width, 0,
|
i/(this.shapes.length-1) * this.width, 0,
|
||||||
i/(this.s.length-1) * this.width, this.height
|
i/(this.shapes.length-1) * this.width, this.height
|
||||||
)
|
)
|
||||||
|
// and then draw the plot itself
|
||||||
setStroke(randomColor(1.0, false ));
|
setStroke(randomColor(1.0, false ));
|
||||||
drawShape(s);
|
drawShape(shape);
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// depending on the slider, also highlight all values at t=...
|
||||||
this.drawHighlight();
|
this.drawHighlight();
|
||||||
}
|
}
|
||||||
|
|
||||||
drawHighlight() {
|
drawHighlight() {
|
||||||
const t = this.position;
|
const t = this.position;
|
||||||
|
|
||||||
|
// 0 and 1 are not meaningful to look at. They're just "100% start/end"
|
||||||
if (t===0) return;
|
if (t===0) return;
|
||||||
if (t===1) return;
|
if (t===1) return;
|
||||||
|
|
||||||
|
// draw a little highlighting bar that runs frop top to bottom
|
||||||
noStroke();
|
noStroke();
|
||||||
setFill(`rgba(255,0,0,0.3)`);
|
setFill(`rgba(255,0,0,0.3)`);
|
||||||
rect(t*this.width - 2, 0, 5, this.height);
|
rect(t*this.width - 2, 0, 5, this.height);
|
||||||
|
|
||||||
const p = this.f.map(f => f(t));
|
// then calculate each interpolation point for our `t` value
|
||||||
|
// and draw it, with a label that says how much it contributes
|
||||||
|
const points = this.interpolationFunctions.map(f => f(t));
|
||||||
setFill(`black`);
|
setFill(`black`);
|
||||||
p.forEach(p => {
|
points.forEach(p => {
|
||||||
circle(p.x, p.y, 3);
|
circle(p.x, p.y, 3);
|
||||||
text(`${ round(100 * p.y/this.height) }%`, p.x + 10, p.y);
|
text(`${ round(100 * p.y/this.height) }%`, p.x + 10, p.y);
|
||||||
});
|
});
|
||||||
|
@@ -1,34 +1,80 @@
|
|||||||
|
let curve;
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
this.curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
|
curve = new Bezier(this, 90, 200, 25, 100, 220, 40, 210, 240);
|
||||||
setMovable(this.curve.points);
|
setMovable(curve.points);
|
||||||
setSlider(`.slide-control`, `position`, 0);
|
setSlider(`.slide-control`, `position`, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
clear();
|
clear();
|
||||||
const curve = this.curve;
|
|
||||||
curve.drawSkeleton();
|
curve.drawSkeleton();
|
||||||
curve.drawCurve();
|
curve.drawCurve();
|
||||||
|
|
||||||
|
noFill();
|
||||||
setStroke("rgb(200,100,100)");
|
setStroke("rgb(200,100,100)");
|
||||||
|
|
||||||
let t = this.position;
|
const t = this.position;
|
||||||
if (0 < t && t < 1) {
|
if (0 < t && t < 1) {
|
||||||
curve.drawStruts(t);
|
this.drawStruts(t);
|
||||||
}
|
}
|
||||||
|
|
||||||
curve.drawPoints();
|
curve.drawPoints();
|
||||||
|
|
||||||
if (0 < t && t < 1) {
|
if (0 < t && t < 1) {
|
||||||
let p = curve.get(t);
|
const p = curve.get(t);
|
||||||
circle(p.x, p.y, 5);
|
circle(p.x, p.y, 5);
|
||||||
|
|
||||||
let perc = (t*100)|0;
|
const perc = (t*100)|0;
|
||||||
let rt = perc/100;
|
const rt = perc/100;
|
||||||
text(`Sequential interpolation for ${perc}% (t=${rt})`, 10, 15);
|
text(`Sequential interpolation for ${perc}% (t=${rt})`, 10, 15);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawStruts(t) {
|
||||||
|
// get all the "de Casteljau" points
|
||||||
|
const p = curve.getStrutPoints(t);
|
||||||
|
|
||||||
|
// and then draw them
|
||||||
|
let s = curve.points.length;
|
||||||
|
let n = curve.points.length;
|
||||||
|
while (--n > 1) {
|
||||||
|
start();
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
let pt = p[s + i];
|
||||||
|
vertex(pt.x, pt.y);
|
||||||
|
circle(pt.x, pt.y, 5);
|
||||||
|
}
|
||||||
|
end();
|
||||||
|
s += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getStrutPoints(t) {
|
||||||
|
const mt = 1 - t;
|
||||||
|
|
||||||
|
// run de Casteljau's algorithm, starting with the base points
|
||||||
|
const points = curve.points.map((p) => new Vector(p));
|
||||||
|
|
||||||
|
let s = 0;
|
||||||
|
let n = p.length + 1;
|
||||||
|
|
||||||
|
// Every iteration will interpolate between `n` points,
|
||||||
|
// as well as decrease that `n` by one. So 4 points yield
|
||||||
|
// 3 new points, which yield 2 new points, which yields 1
|
||||||
|
// final point that is our on-curve point for `t`
|
||||||
|
while (--n > 1) {
|
||||||
|
let list = points.slice(s, s + n);
|
||||||
|
for (let i = 0, e = list.length - 1; i < e; i++) {
|
||||||
|
let pt = list[i + 1].subtract(list[i + 1].subtract(list[i]).scale(mt));
|
||||||
|
points.push(pt);
|
||||||
|
}
|
||||||
|
s += n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
onMouseMove() {
|
onMouseMove() {
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
@@ -8,29 +8,36 @@ draw() {
|
|||||||
const dim = this.height,
|
const dim = this.height,
|
||||||
w = dim,
|
w = dim,
|
||||||
h = dim,
|
h = dim,
|
||||||
|
// midpoints
|
||||||
w2 = w/2,
|
w2 = w/2,
|
||||||
h2 = h/2,
|
h2 = h/2,
|
||||||
w4 = w2/2,
|
// quarterpoints
|
||||||
h4 = h2/2;
|
q = dim/4;
|
||||||
|
|
||||||
|
// draw axes with (0,0) in the middle of the graphic
|
||||||
setStroke(`black`);
|
setStroke(`black`);
|
||||||
line(0, h2, w, h2);
|
line(0, h2, w, h2);
|
||||||
line(w2, 0, w2, h);
|
line(w2, 0, w2, h);
|
||||||
|
|
||||||
var offset = {x:w2, y:h2};
|
for(let t=0, p, step=0.1; t<=this.steps; t+=step) {
|
||||||
|
// create a point at distance 'q' from the midpoint
|
||||||
for(let t=0, p, mod; t<=this.steps; t+=0.1) {
|
|
||||||
p = {
|
p = {
|
||||||
x: w2 + w4 * cos(t),
|
x: w2 + q * cos(t),
|
||||||
y: h2 + h4 * sin(t)
|
y: h2 + q * sin(t)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// and draw it.
|
||||||
circle(p.x, p.y, 1);
|
circle(p.x, p.y, 1);
|
||||||
|
|
||||||
mod = t % 1;
|
// then add a text label too, but only "near" each integer
|
||||||
if(mod >= 0.9) {
|
// step of `t`. Since we're using floating point numbers,
|
||||||
|
// we can't rely on x * 1/x to actually be x (if only life
|
||||||
|
// were that easy) so we need to check whether `t` is "near"
|
||||||
|
// an integer value instead.
|
||||||
|
if(approx(t % 1, 1, step)) {
|
||||||
text(`t = ${round(t)}`,
|
text(`t = ${round(t)}`,
|
||||||
w2 + 1.25 * w4 * cos(t) - 10,
|
w2 + 1.25 * q * cos(t) - 10,
|
||||||
h2 + 1.25 * h4 * sin(t) + 10
|
h2 + 1.25 * q * sin(t) + 10
|
||||||
);
|
);
|
||||||
circle(p.x, p.y, 2);
|
circle(p.x, p.y, 2);
|
||||||
}
|
}
|
||||||
|
@@ -8,20 +8,27 @@ setup() {
|
|||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
clear();
|
clear();
|
||||||
curve.drawCurve();
|
|
||||||
curve.drawSkeleton();
|
|
||||||
|
|
||||||
let step=0.05, min=-10, max=10;
|
// let's draw the curve from -10 to 10, instead of 0 to 1
|
||||||
|
setStroke(`skyblue`);
|
||||||
|
let min=-10, max=10, step=0.05;
|
||||||
|
|
||||||
|
// calculate the very first point
|
||||||
let pt = curve.get(min - step), pn;
|
let pt = curve.get(min - step), pn;
|
||||||
|
|
||||||
setStroke(`skyblue`);
|
|
||||||
|
|
||||||
for (let t=min; t<=step; t+=step) {
|
// then draw the section from -10 to 0
|
||||||
|
for (let t=min; t<step; t+=step) {
|
||||||
pn = curve.get(t);
|
pn = curve.get(t);
|
||||||
line(pt.x, pt.y, pn.x, pn.y);
|
line(pt.x, pt.y, pn.x, pn.y);
|
||||||
pt = pn;
|
pt = pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// then the regular curve, from 0 to 1
|
||||||
|
curve.drawSkeleton();
|
||||||
|
curve.drawCurve();
|
||||||
|
|
||||||
|
// then draw the section from 1 to 10
|
||||||
pt = curve.get(1);
|
pt = curve.get(1);
|
||||||
for (let t=1+step; t<=max; t+=step) {
|
for (let t=1+step; t<=max; t+=step) {
|
||||||
pn = curve.get(t);
|
pn = curve.get(t);
|
||||||
@@ -29,5 +36,7 @@ draw() {
|
|||||||
pt = pn;
|
pt = pn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// and just to make sure they show on top,
|
||||||
|
// draw the curve's control points last.
|
||||||
curve.drawPoints();
|
curve.drawPoints();
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,10 @@ setup() {
|
|||||||
draw() {
|
draw() {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
// draw the curve's polygon, but not the curve itself.
|
||||||
curve.drawSkeleton();
|
curve.drawSkeleton();
|
||||||
|
|
||||||
|
// sample the curve at a few points, and form a polygon with those points
|
||||||
noFill();
|
noFill();
|
||||||
start();
|
start();
|
||||||
for(let i=0, e=this.steps; i<=e; i++) {
|
for(let i=0, e=this.steps; i<=e; i++) {
|
||||||
@@ -20,6 +22,7 @@ draw() {
|
|||||||
}
|
}
|
||||||
end();
|
end();
|
||||||
|
|
||||||
|
// and for completelion, draw the curve's control points
|
||||||
curve.drawPoints();
|
curve.drawPoints();
|
||||||
|
|
||||||
setFill(`black`);
|
setFill(`black`);
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
let curve;
|
let curve;
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
|
// we're going to look at this as three different "views"
|
||||||
setPanelCount(3);
|
setPanelCount(3);
|
||||||
curve = Bezier.defaultCubic(this);
|
curve = Bezier.defaultCubic(this);
|
||||||
setMovable(curve.points);
|
setMovable(curve.points);
|
||||||
@@ -10,20 +11,23 @@ setup() {
|
|||||||
draw() {
|
draw() {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
|
// form our left and right curves, using the "de Casteljau" points
|
||||||
let p = curve.get(this.position);
|
let p = curve.get(this.position);
|
||||||
const struts = this.struts = curve.getStrutPoints(this.position);
|
const struts = this.struts = curve.getStrutPoints(this.position);
|
||||||
const c1 = new Bezier(this, [struts[0], struts[4], struts[7], struts[9]]);
|
const c1 = new Bezier(this, [struts[0], struts[4], struts[7], struts[9]]);
|
||||||
const c2 = new Bezier(this, [struts[9], struts[8], struts[6], struts[3]]);
|
const c2 = new Bezier(this, [struts[9], struts[8], struts[6], struts[3]]);
|
||||||
|
|
||||||
|
// first, draw the same thing we saw in the section on de Casteljau's algorithm
|
||||||
this.drawBasics(p);
|
this.drawBasics(p);
|
||||||
|
|
||||||
|
// then in the next panel, draw the subcurve to the "left" of point `t`
|
||||||
nextPanel();
|
nextPanel();
|
||||||
setStroke(`black`);
|
setStroke(`black`);
|
||||||
line(0, 0, 0, this.height);
|
line(0, 0, 0, this.height);
|
||||||
this.drawSegment(c1, p, `first`);
|
this.drawSegment(c1, p, `first`);
|
||||||
|
|
||||||
|
// and in the third panel, draw the subcurve to the "right" of point `t`
|
||||||
nextPanel();
|
nextPanel();
|
||||||
|
|
||||||
setStroke(`black`);
|
setStroke(`black`);
|
||||||
line(0, 0, 0, this.height);
|
line(0, 0, 0, this.height);
|
||||||
this.drawSegment(c2, p, `second`);
|
this.drawSegment(c2, p, `second`);
|
||||||
@@ -33,12 +37,14 @@ drawBasics(p) {
|
|||||||
curve.drawCurve(`lightgrey`);
|
curve.drawCurve(`lightgrey`);
|
||||||
curve.drawSkeleton(`lightgrey`);
|
curve.drawSkeleton(`lightgrey`);
|
||||||
curve.drawPoints(false);
|
curve.drawPoints(false);
|
||||||
|
|
||||||
noFill();
|
noFill();
|
||||||
setStroke(`red`);
|
setStroke(`red`);
|
||||||
circle(p.x, p.y, 3);
|
circle(p.x, p.y, 3);
|
||||||
|
|
||||||
setStroke(`lightblue`);
|
setStroke(`lightblue`);
|
||||||
curve.drawStruts(this.struts);
|
curve.drawStruts(this.struts);
|
||||||
|
|
||||||
setFill(`black`)
|
setFill(`black`)
|
||||||
text(`The full curve, with struts`, 10, 15);
|
text(`The full curve, with struts`, 10, 15);
|
||||||
}
|
}
|
||||||
@@ -47,12 +53,15 @@ drawSegment(c, p, halfLabel) {
|
|||||||
setStroke(`lightblue`);
|
setStroke(`lightblue`);
|
||||||
curve.drawCurve(`lightblue`);
|
curve.drawCurve(`lightblue`);
|
||||||
curve.drawSkeleton(`lightblue`);
|
curve.drawSkeleton(`lightblue`);
|
||||||
|
|
||||||
c.drawCurve();
|
c.drawCurve();
|
||||||
c.drawSkeleton(`black`);
|
c.drawSkeleton(`black`);
|
||||||
c.points.forEach(p => circle(p.x, p.y, 3));
|
c.points.forEach(p => circle(p.x, p.y, 3));
|
||||||
|
|
||||||
noFill();
|
noFill();
|
||||||
setStroke(`red`);
|
setStroke(`red`);
|
||||||
circle(p.x, p.y, 3);
|
circle(p.x, p.y, 3);
|
||||||
|
|
||||||
setFill(`black`)
|
setFill(`black`)
|
||||||
text(`The ${halfLabel} half`, 10, 15);
|
text(`The ${halfLabel} half`, 10, 15);
|
||||||
}
|
}
|
||||||
|
@@ -3,9 +3,15 @@ let curve, ratios=[1, 1, 1, 1];
|
|||||||
setup() {
|
setup() {
|
||||||
curve = Bezier.defaultCubic(this);
|
curve = Bezier.defaultCubic(this);
|
||||||
setMovable(curve.points);
|
setMovable(curve.points);
|
||||||
curve.points.forEach((p,i) => {
|
for (let i=0; i<4; i++) {
|
||||||
|
// Set up a slider, but in a way that does not tie it to a variable
|
||||||
|
// that is exposed through `this`, because we want to store its value
|
||||||
|
// in the "ratios" array we already declared globally.
|
||||||
|
//
|
||||||
|
// To make that happen, we tell the slider logic that it should be
|
||||||
|
// calling the setRatio function instead when the slider moves.
|
||||||
setSlider(`.ratio-${i+1}`, `!ratio-${i+1}`, 1, v => this.setRatio(i,v))
|
setSlider(`.ratio-${i+1}`, `!ratio-${i+1}`, 1, v => this.setRatio(i,v))
|
||||||
});
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setRatio(i, v) {
|
setRatio(i, v) {
|
||||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 31 KiB After Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
After Width: | Height: | Size: 11 KiB |
After Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 9.0 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 9.1 KiB After Width: | Height: | Size: 9.1 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 9.6 KiB |
@@ -31,7 +31,7 @@
|
|||||||
<meta property="og:locale" content="en-GB" />
|
<meta property="og:locale" content="en-GB" />
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||||
<meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
|
<meta property="og:updated_time" content="2020-09-19T21:15:30+00:00" />
|
||||||
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
||||||
<meta property="og:section" content="Bézier Curves" />
|
<meta property="og:section" content="Bézier Curves" />
|
||||||
<meta property="og:tag" content="Bézier Curves" />
|
<meta property="og:tag" content="Bézier Curves" />
|
||||||
@@ -581,7 +581,7 @@
|
|||||||
<graphics-element title="A (partial) circle: x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
<graphics-element title="A (partial) circle: x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\explanation\6d2f915735ebdc05e42c0ea7adc85343.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\explanation\959762e39ae32407e914a687d804ff3a.png" loading="lazy" />
|
||||||
<label>A (partial) circle: x=sin(t), y=cos(t)</label>
|
<label>A (partial) circle: x=sin(t), y=cos(t)</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
||||||
@@ -749,7 +749,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="Quadratic interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
<graphics-element title="Quadratic interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\2a0635829051977b265b64ef204f718e.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\f700cd59e6021b0e06b819105ec931da.png" loading="lazy" />
|
||||||
<label>Quadratic interpolations</label>
|
<label>Quadratic interpolations</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -758,7 +758,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="Cubic interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
<graphics-element title="Cubic interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\fca18b2602929f80e68d8964832f0f44.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\4b206c16ccf8a06a0834fe9e5254560c.png" loading="lazy" />
|
||||||
<label>Cubic interpolations</label>
|
<label>Cubic interpolations</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -767,7 +767,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="15th degree interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
<graphics-element title="15th degree interpolations" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\989f4ca49d7099802cc0345dbeddca8c.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\be82cd31c4892a8f0582b1b5285231d9.png" loading="lazy" />
|
||||||
<label>15th degree interpolations</label>
|
<label>15th degree interpolations</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -879,7 +879,7 @@ function Bezier(3,t,w[]):
|
|||||||
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\weightcontrol\be18e8119472af796329f3e2159bdf94.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\weightcontrol\3d71e2b9373684eebcb0dc8563f70b18.png" loading="lazy" />
|
||||||
<label>Our rational cubic Bézier curve</label>
|
<label>Our rational cubic Bézier curve</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
||||||
@@ -976,7 +976,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
>
|
>
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\391a61142c56b79260680aefb08cd9c4.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\37948bde4bf0d25bde85f172bf55b9fb.png" loading="lazy" />
|
||||||
<label>Quadratic infinite interval Bézier curve</label>
|
<label>Quadratic infinite interval Bézier curve</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
@@ -989,7 +989,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
>
|
>
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\baeceec6e1587794b8b275a90d5d85e9.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\2d17acb381ebdd28f0ff43be00d723c4.png" loading="lazy" />
|
||||||
<label>Cubic infinite interval Bézier curve</label>
|
<label>Cubic infinite interval Bézier curve</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
@@ -1093,7 +1093,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
>
|
>
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\decasteljau\715d1d2eecc762d6bc1470954b145018.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\decasteljau\df92f529841f39decf9ad62b0967855a.png" loading="lazy" />
|
||||||
<label>Traversing a curve using de Casteljau's algorithm</label>
|
<label>Traversing a curve using de Casteljau's algorithm</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -1157,7 +1157,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
>
|
>
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\3deec756c96e53127cd1d615c61043ae.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\6813bfc608aea11df1dda444b9f18123.png" loading="lazy" />
|
||||||
<label>Flattening a quadratic curve</label>
|
<label>Flattening a quadratic curve</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
||||||
@@ -1166,7 +1166,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="Flattening a cubic curve" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
<graphics-element title="Flattening a cubic curve" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\e2bb7113d5cda2e3fd29bbc54fbe8841.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\0e0e4a2ee46bd89bcfde9f75cfe43292.png" loading="lazy" />
|
||||||
<label>Flattening a cubic curve</label>
|
<label>Flattening a cubic curve</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
||||||
@@ -1213,7 +1213,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="Splitting a curve" width="825" height="275" src="./chapters/splitting/splitting.js">
|
<graphics-element title="Splitting a curve" width="825" height="275" src="./chapters/splitting/splitting.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="825px" height="275px" src="images\chapters\splitting\891133c5f0e140b8c7e179af04e497e0.png" loading="lazy" />
|
<img width="825px" height="275px" src="images\chapters\splitting\fce5eb16dfcd103797c5e17bd77f1437.png" loading="lazy" />
|
||||||
<label></label>
|
<label></label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
<meta property="og:locale" content="ja-JP" />
|
<meta property="og:locale" content="ja-JP" />
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||||
<meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
|
<meta property="og:updated_time" content="2020-09-19T21:15:30+00:00" />
|
||||||
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
||||||
<meta property="og:section" content="Bézier Curves" />
|
<meta property="og:section" content="Bézier Curves" />
|
||||||
<meta property="og:tag" content="Bézier Curves" />
|
<meta property="og:tag" content="Bézier Curves" />
|
||||||
@@ -528,7 +528,7 @@
|
|||||||
<graphics-element title="(部分)円 x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
<graphics-element title="(部分)円 x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\explanation\6d2f915735ebdc05e42c0ea7adc85343.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\explanation\959762e39ae32407e914a687d804ff3a.png" loading="lazy" />
|
||||||
<label>(部分)円 x=sin(t), y=cos(t)</label>
|
<label>(部分)円 x=sin(t), y=cos(t)</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
||||||
@@ -670,7 +670,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="2次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
<graphics-element title="2次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\2a0635829051977b265b64ef204f718e.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\f700cd59e6021b0e06b819105ec931da.png" loading="lazy" />
|
||||||
<label>2次の補間</label>
|
<label>2次の補間</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -679,7 +679,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="3次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
<graphics-element title="3次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\fca18b2602929f80e68d8964832f0f44.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\4b206c16ccf8a06a0834fe9e5254560c.png" loading="lazy" />
|
||||||
<label>3次の補間</label>
|
<label>3次の補間</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -688,7 +688,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="15次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
<graphics-element title="15次の補間" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\989f4ca49d7099802cc0345dbeddca8c.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\be82cd31c4892a8f0582b1b5285231d9.png" loading="lazy" />
|
||||||
<label>15次の補間</label>
|
<label>15次の補間</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -787,7 +787,7 @@ function Bezier(3,t,w[]):
|
|||||||
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\weightcontrol\be18e8119472af796329f3e2159bdf94.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\weightcontrol\3d71e2b9373684eebcb0dc8563f70b18.png" loading="lazy" />
|
||||||
<label>Our rational cubic Bézier curve</label>
|
<label>Our rational cubic Bézier curve</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
||||||
@@ -868,14 +868,14 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="無限区間の2次ベジエ曲線" width="275" height="275" src="./chapters/extended/extended.js" data-type="quadratic">
|
<graphics-element title="無限区間の2次ベジエ曲線" width="275" height="275" src="./chapters/extended/extended.js" data-type="quadratic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\391a61142c56b79260680aefb08cd9c4.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\37948bde4bf0d25bde85f172bf55b9fb.png" loading="lazy" />
|
||||||
<label>無限区間の2次ベジエ曲線</label>
|
<label>無限区間の2次ベジエ曲線</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
<graphics-element title="無限区間の3次ベジエ曲線" width="275" height="275" src="./chapters/extended/extended.js" data-type="cubic">
|
<graphics-element title="無限区間の3次ベジエ曲線" width="275" height="275" src="./chapters/extended/extended.js" data-type="cubic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\baeceec6e1587794b8b275a90d5d85e9.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\2d17acb381ebdd28f0ff43be00d723c4.png" loading="lazy" />
|
||||||
<label>無限区間の3次ベジエ曲線</label>
|
<label>無限区間の3次ベジエ曲線</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
@@ -965,7 +965,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="ド・カステリョのアルゴリズムで曲線をたどる" width="275" height="275" src="./chapters/decasteljau/decasteljau.js">
|
<graphics-element title="ド・カステリョのアルゴリズムで曲線をたどる" width="275" height="275" src="./chapters/decasteljau/decasteljau.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\decasteljau\715d1d2eecc762d6bc1470954b145018.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\decasteljau\df92f529841f39decf9ad62b0967855a.png" loading="lazy" />
|
||||||
<label>ド・カステリョのアルゴリズムで曲線をたどる</label>
|
<label>ド・カステリョのアルゴリズムで曲線をたどる</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -1015,7 +1015,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="2次ベジエ曲線の平坦化" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="quadratic">
|
<graphics-element title="2次ベジエ曲線の平坦化" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="quadratic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\3deec756c96e53127cd1d615c61043ae.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\6813bfc608aea11df1dda444b9f18123.png" loading="lazy" />
|
||||||
<label>2次ベジエ曲線の平坦化</label>
|
<label>2次ベジエ曲線の平坦化</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
||||||
@@ -1024,7 +1024,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="3次ベジエ曲線の平坦化" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
<graphics-element title="3次ベジエ曲線の平坦化" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\e2bb7113d5cda2e3fd29bbc54fbe8841.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\0e0e4a2ee46bd89bcfde9f75cfe43292.png" loading="lazy" />
|
||||||
<label>3次ベジエ曲線の平坦化</label>
|
<label>3次ベジエ曲線の平坦化</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
||||||
@@ -1066,7 +1066,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="曲線の分割" width="825" height="275" src="./chapters/splitting/splitting.js">
|
<graphics-element title="曲線の分割" width="825" height="275" src="./chapters/splitting/splitting.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="825px" height="275px" src="images\chapters\splitting\891133c5f0e140b8c7e179af04e497e0.png" loading="lazy" />
|
<img width="825px" height="275px" src="images\chapters\splitting\fce5eb16dfcd103797c5e17bd77f1437.png" loading="lazy" />
|
||||||
<label></label>
|
<label></label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
||||||
|
@@ -14,13 +14,17 @@ draw() {
|
|||||||
|
|
||||||
All code starts at `setup()`, automatically calling `draw()` after setup has been completed. Standard JS scoping applies, so any variable declared outside of `setup`/`draw` will be a "global" variable.
|
All code starts at `setup()`, automatically calling `draw()` after setup has been completed. Standard JS scoping applies, so any variable declared outside of `setup`/`draw` will be a "global" variable.
|
||||||
|
|
||||||
## User Events
|
Note that neither of these functions are _required_: without a `setup()` function the code will just jump straight to `draw()`, and without a `draw()` function the code will simply not draw anything beyond the initial empty canvas.
|
||||||
|
|
||||||
|
## User-initiated events
|
||||||
|
|
||||||
|
### Touch/mouse events
|
||||||
|
|
||||||
Graphics code can react to touch/mouse, which can be handled using:
|
Graphics code can react to touch/mouse, which can be handled using:
|
||||||
|
|
||||||
- `onMouseDown()` triggered by mouse/touch start events.
|
- `onMouseDown()` triggered by mouse/touch start events.
|
||||||
- `onMouseUp()` triggered by mouse/touch end events.
|
- `onMouseUp()` triggered by mouse/touch end events.
|
||||||
- `onMouseMose()` triggered by moving the mouse/your finger.
|
- `onMouseMove()` triggered by moving the mouse/your finger.
|
||||||
|
|
||||||
Mouse event data can be accessed via the `this.cursor` property, which encodes:
|
Mouse event data can be accessed via the `this.cursor` property, which encodes:
|
||||||
|
|
||||||
@@ -37,6 +41,35 @@ Mouse event data can be accessed via the `this.cursor` property, which encodes:
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
setup() {
|
||||||
|
this.defaultBgColor = this.bgColor = `green`;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
clear(this.bgColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseDown() {
|
||||||
|
this.bgColor = `blue`;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseMove() {
|
||||||
|
this.bgColor = `red`;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseUp() {
|
||||||
|
this.bgColor = this.defaultBgColor;
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Keyboard events
|
||||||
|
|
||||||
Graphics code can also react to keyboard events, although this is a great way to make sure your code won't work for mobile devices, so it's better to use range sliders to keep things accessible. That said, they can be handled using:
|
Graphics code can also react to keyboard events, although this is a great way to make sure your code won't work for mobile devices, so it's better to use range sliders to keep things accessible. That said, they can be handled using:
|
||||||
|
|
||||||
- `onKeyDown()` triggered by pressing a key
|
- `onKeyDown()` triggered by pressing a key
|
||||||
@@ -54,15 +87,45 @@ Additionally, the `this.keyboard` property can be consulted for named keys to se
|
|||||||
|
|
||||||
```js
|
```js
|
||||||
draw() {
|
draw() {
|
||||||
if (this.keyboard[`ArrowUp`]) {
|
if (this.keyboard[`w`] && this.keyboard[`d`]) {
|
||||||
...
|
// move up-left
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Example
|
||||||
|
|
||||||
|
```js
|
||||||
|
setup() {
|
||||||
|
this.y = this.height/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw() {
|
||||||
|
clear();
|
||||||
|
setColor(`black`);
|
||||||
|
rect(0, this.y-1, this.width, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
onKeyDown() {
|
||||||
|
const key = this.keyboard.currentKey;
|
||||||
|
if (key === `ArrowUp`) {
|
||||||
|
y -= 5
|
||||||
|
}
|
||||||
|
if (key === `ArrowDown`) {
|
||||||
|
y += 5;
|
||||||
|
}
|
||||||
|
y = constrain(y, 0, this.height);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Controllable parameters
|
## Controllable parameters
|
||||||
|
|
||||||
Graphics code can be passed external values from HTML using data attributes:
|
Graphics code can be provided with outside values in two different ways.
|
||||||
|
|
||||||
|
### Using fixed startup parameters
|
||||||
|
|
||||||
|
Graphics code can be passed fixed values from HTML using data attributes:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<graphics-element src="..." data-propname="somevalue"></graphics-element>
|
<graphics-element src="..." data-propname="somevalue"></graphics-element>
|
||||||
@@ -74,21 +137,38 @@ which can be access on the code side using
|
|||||||
this.parameters.propname;
|
this.parameters.propname;
|
||||||
```
|
```
|
||||||
|
|
||||||
Additionally, graphics code has special functions for range values, either directly in code:
|
Note that `this.parameters` is a protected object. Properties of the parameters object can be updated by your code, but you cannot reassign `this.parameters` itself.
|
||||||
|
|
||||||
|
|
||||||
|
### Using dynamic value sliders
|
||||||
|
|
||||||
|
Graphics code has also be provided with dynamic values by using range sliders. There are two ways to do this: purely in code, or by tying the graphics code to HTML sliders.
|
||||||
|
|
||||||
|
#### In code
|
||||||
|
|
||||||
|
If sliders may be dynamically required, the `addSlider` function can be used:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
setup() {
|
setup() {
|
||||||
// name, min, max, step, initial value
|
|
||||||
addSlider(`rangeValue`, 0, 1, 0.001, 0.5);
|
addSlider(`rangeValue`, 0, 1, 0.001, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw() {
|
draw() {
|
||||||
// values defined through sliders become accessible on `this`:
|
|
||||||
console.log(this.rangeValue);
|
console.log(this.rangeValue);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Alternatively, they can be hooked into a predefined slider:
|
Its function signature is `addSlider(property name, min, max, step, initial value)`, in which the arguments represent:
|
||||||
|
|
||||||
|
- `property name` a propertyname string that may start with `!`. If no `!` is used, the property name should follow the rules for variable names, as the property will be exposed as `this.propertyname` (e.g. is you use `rangeValue`, then `this.rangeValue` will exis and be kept up to date by the slider logic). If `!` is used, no `this.propertyname` will be be set up for use in your code. Regardless of whether `!` is used or not, the property name will also be displayed in the slider's UI.
|
||||||
|
- `min` the minimum numerical value this variable will be able to take on
|
||||||
|
- `max` the meximum numerical value this variable will be able to take on
|
||||||
|
- `step` the value increase/decrease per step of the slider.
|
||||||
|
- `initial value` the value that the associated variable will be assigned as part of the `addSlider` call.
|
||||||
|
|
||||||
|
#### From HTML
|
||||||
|
|
||||||
|
You can also "presupply" a graphic with sliders, if you know your graphic has a fixed number of dynamic variables. This uses the standard HTML `<input type="range">` element:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<graphics-element src="..." data-propname="somevalue">
|
<graphics-element src="..." data-propname="somevalue">
|
||||||
@@ -96,11 +176,10 @@ Alternatively, they can be hooked into a predefined slider:
|
|||||||
</graphics-element>
|
</graphics-element>
|
||||||
```
|
```
|
||||||
|
|
||||||
using the `setSlider` function:
|
With the graphic code using `setSlider` with a query selector to find your slider element and tie it to a variable:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
setup() {
|
setup() {
|
||||||
// local query selector, name, initial value
|
|
||||||
setSlider(`.my-slider`, `rangeValue`, 0.5);
|
setSlider(`.my-slider`, `rangeValue`, 0.5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -109,6 +188,17 @@ draw() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Its function signature is `setSlider(query selector, property name, initial value)`, in which the arguments represent:
|
||||||
|
|
||||||
|
- `query select` a CSS query selector for finding the right slider in your `<graphics-element>` tree. If you only have one slider then this query selector can simply be `input[type=range]`, but if you have multiple sliders it's a better idea to give each slider a CSS class that can be used to indentify it.
|
||||||
|
- `property name` a propertyname string that may start with `!`. If no `!` is used, the property name should follow the rules for variable names, as the property will be exposed as `this.propertyname` (e.g. is you use `rangeValue`, then `this.rangeValue` will exis and be kept up to date by the slider logic). If `!` is used, no `this.propertyname` will be be set up for use in your code. Regardless of whether `!` is used or not, the property name will also be displayed in the slider's UI.
|
||||||
|
- `initial value` the value that the associated variable will be assigned as part of the `addSlider` call.
|
||||||
|
|
||||||
|
Note that while it might seem that `<input>` elements can be made fully self-descriptive for both the property name (using the `name` attribute) and initial value (using the `value` attribute), this code still needs to do the right thing even in the absence of an HTML page, and so the property name and initial value are explicitly required.
|
||||||
|
|
||||||
|
**warning:** if you try to set up a slider for a property name that you have already defined, the code will throw a runtime error.
|
||||||
|
|
||||||
|
|
||||||
## Movable points
|
## Movable points
|
||||||
|
|
||||||
An important part of the Graphics API is showing shapes that are controlled or defined by coordinates, and as there are special functions for marking points as "movable" - that is, these points can be click/touch-dragged around a graphic. To fascilitate this, the following functions can be used:
|
An important part of the Graphics API is showing shapes that are controlled or defined by coordinates, and as there are special functions for marking points as "movable" - that is, these points can be click/touch-dragged around a graphic. To fascilitate this, the following functions can be used:
|
||||||
@@ -117,12 +207,12 @@ An important part of the Graphics API is showing shapes that are controlled or d
|
|||||||
- `resetMovable()` will clear the list of movable points.
|
- `resetMovable()` will clear the list of movable points.
|
||||||
- `resetMovable(points, ...)` is the same as calling `resetMovable()` followed by `setMovable(points, ...)`.
|
- `resetMovable(points, ...)` is the same as calling `resetMovable()` followed by `setMovable(points, ...)`.
|
||||||
|
|
||||||
|
|
||||||
## The API
|
## The API
|
||||||
|
|
||||||
The following is the list of API functions that can be used to draw... whatever you like, really.
|
The following is the list of API functions that can be used to draw... whatever you like, really.
|
||||||
|
|
||||||
|
### Global constants
|
||||||
### gGobal constants
|
|
||||||
|
|
||||||
- `PI` 3.14159265358979
|
- `PI` 3.14159265358979
|
||||||
- `TAU` 6.28318530717958
|
- `TAU` 6.28318530717958
|
||||||
@@ -247,7 +337,7 @@ In addition to transformations, there are also two functions to allow you to map
|
|||||||
- `drawShape(...shapes)` draw one or more saved full shapes (see below)
|
- `drawShape(...shapes)` draw one or more saved full shapes (see below)
|
||||||
- `image(img, x = 0, y = 0, w = auto, h = auto)` draw an image at some (x,y) coordinate, defaulting to (0,0), scaled to some width and height, defaulting to the native image dimensions
|
- `image(img, x = 0, y = 0, w = auto, h = auto)` draw an image at some (x,y) coordinate, defaulting to (0,0), scaled to some width and height, defaulting to the native image dimensions
|
||||||
- `line(x1, y1, x2, y2)` draw a line from (x1,y1) to (x2,y2)
|
- `line(x1, y1, x2, y2)` draw a line from (x1,y1) to (x2,y2)
|
||||||
- `plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1)` plot a function defined by `fn` (which must take a single numerical input, and output an object of the form `{x:..., y:...}`) for inputs in the interval [start,end], at a resolution of `steps` steps, with the resulting values scaled by `xscale` horizontally, and `yscale` vertically.
|
- `plot(fn, start = 0, end = 1, steps = 24, xscale = 1, yscale = 1)` plot a function defined by `fn` (which must take a single numerical input, and output an object of the form `{x:..., y:...}`) for inputs in the interval [start,end], at a resolution of `steps` steps, with the resulting values scaled by `xscale` horizontally, and `yscale` vertically. This function returns the plot as a `Shape` for later reuse.
|
||||||
- `point(x, y)` draw a single point at (x,y)
|
- `point(x, y)` draw a single point at (x,y)
|
||||||
- `rect(x, y, w, h)` draw a rectangle from (x,y) with width `w` and height `h`
|
- `rect(x, y, w, h)` draw a rectangle from (x,y) with width `w` and height `h`
|
||||||
- `redraw()` triggers a new draw loop. Use this instead of calling `draw()` directly when you wish to draw a new frame as part of event handling.
|
- `redraw()` triggers a new draw loop. Use this instead of calling `draw()` directly when you wish to draw a new frame as part of event handling.
|
||||||
@@ -263,7 +353,7 @@ In addition to transformations, there are also two functions to allow you to map
|
|||||||
- `saveShape()` returns the current shape for later reuse
|
- `saveShape()` returns the current shape for later reuse
|
||||||
|
|
||||||
|
|
||||||
## Built in object types
|
## Built-in object types
|
||||||
|
|
||||||
### Shape
|
### Shape
|
||||||
|
|
||||||
|
@@ -53,7 +53,10 @@ class BaseAPI {
|
|||||||
this.dataset = {};
|
this.dataset = {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.parameters = Object.fromEntries(
|
Object.defineProperty(this, `parameters`, {
|
||||||
|
writable: false,
|
||||||
|
configurable: false,
|
||||||
|
value: Object.fromEntries(
|
||||||
Object.entries(this.dataset)
|
Object.entries(this.dataset)
|
||||||
.map((pair) => {
|
.map((pair) => {
|
||||||
let name = pair[0];
|
let name = pair[0];
|
||||||
@@ -69,7 +72,8 @@ class BaseAPI {
|
|||||||
return [name, v];
|
return [name, v];
|
||||||
})
|
})
|
||||||
.filter((v) => v.length)
|
.filter((v) => v.length)
|
||||||
);
|
),
|
||||||
|
});
|
||||||
this.addListeners();
|
this.addListeners();
|
||||||
this.setSize(width, height);
|
this.setSize(width, height);
|
||||||
this.currentPoint = false;
|
this.currentPoint = false;
|
||||||
|
@@ -605,7 +605,7 @@ class GraphicsAPI extends BaseAPI {
|
|||||||
/**
|
/**
|
||||||
* Yield a snapshot of the current shape.
|
* Yield a snapshot of the current shape.
|
||||||
*/
|
*/
|
||||||
save() {
|
saveShape() {
|
||||||
return this.currentShape;
|
return this.currentShape;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -22,12 +22,12 @@
|
|||||||
<meta property="og:title" content="Rewriting the tech stack" />
|
<meta property="og:title" content="Rewriting the tech stack" />
|
||||||
<meta property="og:image" content="https://pomax.github.io/bezierinfo/images/og-image.png" />
|
<meta property="og:image" content="https://pomax.github.io/bezierinfo/images/og-image.png" />
|
||||||
<meta property="og:type" content="text" />
|
<meta property="og:type" content="text" />
|
||||||
<meta property="og:url" content="https://pomax.github.io/bezierinfo/news/2020-09-20.html" />
|
<meta property="og:url" content="https://pomax.github.io/bezierinfo/news/2020-09-18.html" />
|
||||||
<meta property="og:description" content="Rewriting the tech stack" />
|
<meta property="og:description" content="Rewriting the tech stack" />
|
||||||
<meta property="og:locale" content="en-GB" />
|
<meta property="og:locale" content="en-GB" />
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:published_time" content="2020-09-20T12:00:00+00:00" />
|
<meta property="og:published_time" content="2020-09-18T12:00:00+00:00" />
|
||||||
<meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
|
<meta property="og:updated_time" content="2020-09-19T21:15:30+00:00" />
|
||||||
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
||||||
<meta property="og:section" content="Bézier Curves" />
|
<meta property="og:section" content="Bézier Curves" />
|
||||||
<meta property="og:tag" content="Bézier Curves" />
|
<meta property="og:tag" content="Bézier Curves" />
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
|
|
||||||
<header>
|
<header>
|
||||||
<h1>Rewriting the tech stack</h1>
|
<h1>Rewriting the tech stack</h1>
|
||||||
<h5 class="post-date">Sun, 20 Sep 2020</h5>
|
<h5 class="post-date">Fri, 18 Sep 2020</h5>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
@@ -94,7 +94,7 @@
|
|||||||
</p>
|
</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="news/2020-09-20.html">Rewriting the tech stack</a> (Sun, 20 Sep 2020)</li>
|
<li><a href="news/2020-09-18.html">Rewriting the tech stack</a> (Fri, 18 Sep 2020)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Rewriting the tech stack</title>
|
<title>Rewriting the tech stack</title>
|
||||||
<link>https://pomax.github.io/bezierinfo/news/2020-09-20.html</link>
|
<link>https://pomax.github.io/bezierinfo/news/2020-09-18.html</link>
|
||||||
<description>
|
<description>
|
||||||
<p>Once upon a time, I needed to draw some Bezier curves because I was trying to create a Japanese kanji composition system that turned strokes into outlines, and that required knowing how to offset Bezier curves and... at the time (2011, time flies) there was no good single source of information for Bezier curves on the web. So I made one. Sure it started small, but it turns out that if you just keep adding bits to something, several years later you have quite the monster, and a single HTML file becomes intractible.</p>
|
<p>Once upon a time, I needed to draw some Bezier curves because I was trying to create a Japanese kanji composition system that turned strokes into outlines, and that required knowing how to offset Bezier curves and... at the time (2011, time flies) there was no good single source of information for Bezier curves on the web. So I made one. Sure it started small, but it turns out that if you just keep adding bits to something, several years later you have quite the monster, and a single HTML file becomes intractible.</p>
|
||||||
<p>So, in 2016, when <a href="">React.js</a> exploded onto the scene, I rewrote the primer as a React app, and it became a lot easier to maintain. Like, <em>a lot</em> a lot. However, there was a downside: no JS meant no content. Sure, server-side rendering sort of existed, but not really, and because the Primer is hosted through github, there was no "server" to run. Plus, trying to rehydrate an app the size of the Primer from a giant HTML file had truly <em>dire</em> performance.</p>
|
<p>So, in 2016, when <a href="">React.js</a> exploded onto the scene, I rewrote the primer as a React app, and it became a lot easier to maintain. Like, <em>a lot</em> a lot. However, there was a downside: no JS meant no content. Sure, server-side rendering sort of existed, but not really, and because the Primer is hosted through github, there was no "server" to run. Plus, trying to rehydrate an app the size of the Primer from a giant HTML file had truly <em>dire</em> performance.</p>
|
||||||
@@ -44,8 +44,8 @@
|
|||||||
<p>See you in the next post!</p>
|
<p>See you in the next post!</p>
|
||||||
<p>— Pomax</p>
|
<p>— Pomax</p>
|
||||||
</description>
|
</description>
|
||||||
<pubDate>2020-09-20</pubDate>
|
<pubDate>2020-09-18</pubDate>
|
||||||
<guid>2020-09-20.html</guid>
|
<guid>2020-09-18.html</guid>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
|
|
||||||
|
@@ -33,7 +33,7 @@
|
|||||||
<meta property="og:locale" content="zh-CN" />
|
<meta property="og:locale" content="zh-CN" />
|
||||||
<meta property="og:type" content="article" />
|
<meta property="og:type" content="article" />
|
||||||
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
<meta property="og:published_time" content="2013-06-13T12:00:00+00:00" />
|
||||||
<meta property="og:updated_time" content="2020-09-19T19:29:14+00:00" />
|
<meta property="og:updated_time" content="2020-09-19T21:15:30+00:00" />
|
||||||
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
<meta property="og:author" content="Mike 'Pomax' Kamermans" />
|
||||||
<meta property="og:section" content="Bézier Curves" />
|
<meta property="og:section" content="Bézier Curves" />
|
||||||
<meta property="og:tag" content="Bézier Curves" />
|
<meta property="og:tag" content="Bézier Curves" />
|
||||||
@@ -504,7 +504,7 @@
|
|||||||
<graphics-element title="(一部分的)圆: x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
<graphics-element title="(一部分的)圆: x=sin(t), y=cos(t)" width="275" height="275" src="./chapters/explanation/circle.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\explanation\6d2f915735ebdc05e42c0ea7adc85343.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\explanation\959762e39ae32407e914a687d804ff3a.png" loading="lazy" />
|
||||||
<label>(一部分的)圆: x=sin(t), y=cos(t)</label>
|
<label>(一部分的)圆: x=sin(t), y=cos(t)</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
<input type="range" min="0" max="10" step="0.1" value="5" class="slide-control" />
|
||||||
@@ -640,7 +640,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="二次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
<graphics-element title="二次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="3">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\2a0635829051977b265b64ef204f718e.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\f700cd59e6021b0e06b819105ec931da.png" loading="lazy" />
|
||||||
<label>二次插值</label>
|
<label>二次插值</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -649,7 +649,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="三次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
<graphics-element title="三次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="4">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\fca18b2602929f80e68d8964832f0f44.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\4b206c16ccf8a06a0834fe9e5254560c.png" loading="lazy" />
|
||||||
<label>三次插值</label>
|
<label>三次插值</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -658,7 +658,7 @@ function Bezier(3,t):
|
|||||||
<graphics-element title="15次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
<graphics-element title="15次插值" width="275" height="275" src="./chapters/control/lerp.js" data-degree="15">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\control\989f4ca49d7099802cc0345dbeddca8c.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\control\be82cd31c4892a8f0582b1b5285231d9.png" loading="lazy" />
|
||||||
<label>15次插值</label>
|
<label>15次插值</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -753,7 +753,7 @@ function Bezier(3,t,w[]):
|
|||||||
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
<graphics-element title="Our rational cubic Bézier curve" width="275" height="275" src="./chapters/weightcontrol/rational.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\weightcontrol\be18e8119472af796329f3e2159bdf94.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\weightcontrol\3d71e2b9373684eebcb0dc8563f70b18.png" loading="lazy" />
|
||||||
<label>Our rational cubic Bézier curve</label>
|
<label>Our rational cubic Bézier curve</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
<input type="range" min="0.01" max="2" value="1" step="0.01" class="ratio-1" />
|
||||||
@@ -830,14 +830,14 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="二次无限区间贝塞尔曲线" width="275" height="275" src="./chapters/extended/extended.js" data-type="quadratic">
|
<graphics-element title="二次无限区间贝塞尔曲线" width="275" height="275" src="./chapters/extended/extended.js" data-type="quadratic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\391a61142c56b79260680aefb08cd9c4.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\37948bde4bf0d25bde85f172bf55b9fb.png" loading="lazy" />
|
||||||
<label>二次无限区间贝塞尔曲线</label>
|
<label>二次无限区间贝塞尔曲线</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
<graphics-element title="三次无限区间贝塞尔曲线" width="275" height="275" src="./chapters/extended/extended.js" data-type="cubic">
|
<graphics-element title="三次无限区间贝塞尔曲线" width="275" height="275" src="./chapters/extended/extended.js" data-type="cubic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\extended\baeceec6e1587794b8b275a90d5d85e9.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\extended\2d17acb381ebdd28f0ff43be00d723c4.png" loading="lazy" />
|
||||||
<label>三次无限区间贝塞尔曲线</label>
|
<label>三次无限区间贝塞尔曲线</label>
|
||||||
</fallback-image></graphics-element
|
</fallback-image></graphics-element
|
||||||
>
|
>
|
||||||
@@ -920,7 +920,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="用de Casteljau算法来遍历曲线" width="275" height="275" src="./chapters/decasteljau/decasteljau.js">
|
<graphics-element title="用de Casteljau算法来遍历曲线" width="275" height="275" src="./chapters/decasteljau/decasteljau.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\decasteljau\715d1d2eecc762d6bc1470954b145018.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\decasteljau\df92f529841f39decf9ad62b0967855a.png" loading="lazy" />
|
||||||
<label>用de Casteljau算法来遍历曲线</label>
|
<label>用de Casteljau算法来遍历曲线</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0" class="slide-control" />
|
||||||
@@ -969,7 +969,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="拉平一条二次曲线" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="quadratic">
|
<graphics-element title="拉平一条二次曲线" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="quadratic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\3deec756c96e53127cd1d615c61043ae.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\6813bfc608aea11df1dda444b9f18123.png" loading="lazy" />
|
||||||
<label>拉平一条二次曲线</label>
|
<label>拉平一条二次曲线</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
<input type="range" min="1" max="16" step="1" value="4" class="slide-control" />
|
||||||
@@ -978,7 +978,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="拉平一条三次曲线" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
<graphics-element title="拉平一条三次曲线" width="275" height="275" src="./chapters/flattening/flatten.js" data-type="cubic">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="275px" height="275px" src="images\chapters\flattening\e2bb7113d5cda2e3fd29bbc54fbe8841.png" loading="lazy" />
|
<img width="275px" height="275px" src="images\chapters\flattening\0e0e4a2ee46bd89bcfde9f75cfe43292.png" loading="lazy" />
|
||||||
<label>拉平一条三次曲线</label>
|
<label>拉平一条三次曲线</label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
<input type="range" min="1" max="24" step="1" value="8" class="slide-control" />
|
||||||
@@ -1022,7 +1022,7 @@ function RationalBezier(3,t,w[],r[]):
|
|||||||
<graphics-element title="分割一条曲线" width="825" height="275" src="./chapters/splitting/splitting.js">
|
<graphics-element title="分割一条曲线" width="825" height="275" src="./chapters/splitting/splitting.js">
|
||||||
<fallback-image>
|
<fallback-image>
|
||||||
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
<span class="view-source">Scripts are disabled. Showing fallback image.</span>
|
||||||
<img width="825px" height="275px" src="images\chapters\splitting\891133c5f0e140b8c7e179af04e497e0.png" loading="lazy" />
|
<img width="825px" height="275px" src="images\chapters\splitting\fce5eb16dfcd103797c5e17bd77f1437.png" loading="lazy" />
|
||||||
<label></label>
|
<label></label>
|
||||||
</fallback-image>
|
</fallback-image>
|
||||||
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
<input type="range" min="0" max="1" step="0.01" value="0.5" class="slide-control" />
|
||||||
|