mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-18 22:41:49 +02:00
full regeneration
This commit is contained in:
@@ -1,17 +1,19 @@
|
||||
let points = [];
|
||||
|
||||
setup() {
|
||||
const w = this.width,
|
||||
h = this.height;
|
||||
for (let i=0; i<10; i++) {
|
||||
points.push({
|
||||
x: w/2 + random(20) + cos(PI*2 * i/10) * (w/2 - 40),
|
||||
y: h/2 + random(20) + sin(PI*2 * i/10) * (h/2 - 40)
|
||||
});
|
||||
}
|
||||
setMovable(points);
|
||||
this.bindButtons();
|
||||
const w = this.width,
|
||||
h = this.height;
|
||||
|
||||
// let's create a wiggle-circle by randomizing points on a circle
|
||||
for (let i=0; i<10; i++) {
|
||||
points.push({
|
||||
x: w/2 + random(20) + cos(PI*2 * i/10) * (w/2 - 40),
|
||||
y: h/2 + random(20) + sin(PI*2 * i/10) * (h/2 - 40)
|
||||
});
|
||||
}
|
||||
setMovable(points);
|
||||
this.bindButtons();
|
||||
}
|
||||
|
||||
bindButtons() {
|
||||
let rbutton = find(`.raise`);
|
||||
@@ -27,103 +29,105 @@ draw() {
|
||||
}
|
||||
|
||||
drawCurve() {
|
||||
// we can't "just draw" this curve, since it'll be an arbitrary order,
|
||||
// And the canvas only does 2nd and 3rd - we use de Casteljau's algorithm:
|
||||
start();
|
||||
noFill();
|
||||
setStroke(`black`);
|
||||
for(let t=0; t<=1; t+=0.01) {
|
||||
let q = JSON.parse(JSON.stringify(points));
|
||||
while(q.length > 1) {
|
||||
for (let i=0; i<q.length-1; i++) {
|
||||
q[i] = {
|
||||
x: q[i].x + (q[i+1].x - q[i].x) * t,
|
||||
y: q[i].y + (q[i+1].y - q[i].y) * t
|
||||
};
|
||||
}
|
||||
q.splice(q.length-1, 1);
|
||||
// we can't "just draw" this curve, since it'll be an arbitrary order,
|
||||
// And the canvas only does 2nd and 3rd - we use de Casteljau's algorithm:
|
||||
start();
|
||||
noFill();
|
||||
setStroke(`black`);
|
||||
for(let t=0; t<=1; t+=0.01) {
|
||||
let q = JSON.parse(JSON.stringify(points));
|
||||
while(q.length > 1) {
|
||||
for (let i=0; i<q.length-1; i++) {
|
||||
q[i] = {
|
||||
x: q[i].x + (q[i+1].x - q[i].x) * t,
|
||||
y: q[i].y + (q[i+1].y - q[i].y) * t
|
||||
};
|
||||
}
|
||||
vertex(q[0].x, q[0].y);
|
||||
q.splice(q.length-1, 1);
|
||||
}
|
||||
end();
|
||||
vertex(q[0].x, q[0].y);
|
||||
}
|
||||
end();
|
||||
|
||||
start();
|
||||
setStroke(`lightgrey`);
|
||||
points.forEach(p => vertex(p.x, p.y));
|
||||
end();
|
||||
start();
|
||||
setStroke(`lightgrey`);
|
||||
points.forEach(p => vertex(p.x, p.y));
|
||||
end();
|
||||
|
||||
setStroke(`black`);
|
||||
points.forEach(p => circle(p.x, p.y, 3));
|
||||
setStroke(`black`);
|
||||
points.forEach(p => circle(p.x, p.y, 3));
|
||||
}
|
||||
|
||||
raise() {
|
||||
const p = points,
|
||||
const p = points,
|
||||
np = [p[0]],
|
||||
k = p.length;
|
||||
for (let i = 1, pi, pim; i < k; i++) {
|
||||
pi = p[i];
|
||||
pim = p[i - 1];
|
||||
np[i] = {
|
||||
x: ((k - i) / k) * pi.x + (i / k) * pim.x,
|
||||
y: ((k - i) / k) * pi.y + (i / k) * pim.y,
|
||||
};
|
||||
}
|
||||
np[k] = p[k - 1];
|
||||
points = np;
|
||||
|
||||
resetMovable(points);
|
||||
redraw();
|
||||
// raising the order of a curve is lossless:
|
||||
for (let i = 1, pi, pim; i < k; i++) {
|
||||
pi = p[i];
|
||||
pim = p[i - 1];
|
||||
np[i] = {
|
||||
x: ((k - i) / k) * pi.x + (i / k) * pim.x,
|
||||
y: ((k - i) / k) * pi.y + (i / k) * pim.y,
|
||||
};
|
||||
}
|
||||
np[k] = p[k - 1];
|
||||
points = np;
|
||||
|
||||
resetMovable(points);
|
||||
redraw();
|
||||
}
|
||||
|
||||
lower() {
|
||||
// Based on https://www.sirver.net/blog/2011/08/23/degree-reduction-of-bezier-curves/
|
||||
// Based on https://www.sirver.net/blog/2011/08/23/degree-reduction-of-bezier-curves/
|
||||
|
||||
// TODO: FIXME: this is the same code as in the old codebase,
|
||||
// and it does something odd to the either the
|
||||
// first or last point... it starts to travel
|
||||
// A LOT more than it looks like it should... O_o
|
||||
// TODO: FIXME: this is the same code as in the old codebase,
|
||||
// and it does something odd to the either the
|
||||
// first or last point... it starts to travel
|
||||
// A LOT more than it looks like it should... O_o
|
||||
|
||||
const p = points,
|
||||
k = p.length,
|
||||
data = [],
|
||||
n = k-1;
|
||||
const p = points,
|
||||
k = p.length,
|
||||
data = [],
|
||||
n = k-1;
|
||||
|
||||
if (k <= 3) return;
|
||||
if (k <= 3) return;
|
||||
|
||||
// build M, which will be (k) rows by (k-1) columns
|
||||
for(let i=0; i<k; i++) {
|
||||
data[i] = (new Array(k - 1)).fill(0);
|
||||
if(i===0) { data[i][0] = 1; }
|
||||
else if(i===n) { data[i][i-1] = 1; }
|
||||
else {
|
||||
data[i][i-1] = i / k;
|
||||
data[i][i] = 1 - data[i][i-1];
|
||||
}
|
||||
// build M, which will be (k) rows by (k-1) columns
|
||||
for(let i=0; i<k; i++) {
|
||||
data[i] = (new Array(k - 1)).fill(0);
|
||||
if(i===0) { data[i][0] = 1; }
|
||||
else if(i===n) { data[i][i-1] = 1; }
|
||||
else {
|
||||
data[i][i-1] = i / k;
|
||||
data[i][i] = 1 - data[i][i-1];
|
||||
}
|
||||
}
|
||||
|
||||
// Apply our matrix operations:
|
||||
const M = new Matrix(data);
|
||||
const Mt = M.transpose(M);
|
||||
const Mc = Mt.multiply(M);
|
||||
const Mi = Mc.invert();
|
||||
// Apply our matrix operations:
|
||||
const M = new Matrix(data);
|
||||
const Mt = M.transpose(M);
|
||||
const Mc = Mt.multiply(M);
|
||||
const Mi = Mc.invert();
|
||||
|
||||
if (!Mi) {
|
||||
return console.error('MtM has no inverse?');
|
||||
}
|
||||
if (!Mi) {
|
||||
return console.error('MtM has no inverse?');
|
||||
}
|
||||
|
||||
// And then we map our k-order list of coordinates
|
||||
// to an n-order list of coordinates, instead:
|
||||
const V = Mi.multiply(Mt);
|
||||
const x = new Matrix(points.map(p => [p.x]));
|
||||
const nx = V.multiply(x);
|
||||
const y = new Matrix(points.map(p => [p.y]));
|
||||
const ny = V.multiply(y);
|
||||
// And then we map our k-order list of coordinates
|
||||
// to an n-order list of coordinates, instead:
|
||||
const V = Mi.multiply(Mt);
|
||||
const x = new Matrix(points.map(p => [p.x]));
|
||||
const nx = V.multiply(x);
|
||||
const y = new Matrix(points.map(p => [p.y]));
|
||||
const ny = V.multiply(y);
|
||||
|
||||
points = nx.data.map((x,i) => ({
|
||||
x: x[0],
|
||||
y: ny.data[i][0]
|
||||
}));
|
||||
points = nx.data.map((x,i) => ({
|
||||
x: x[0],
|
||||
y: ny.data[i][0]
|
||||
}));
|
||||
|
||||
resetMovable(points);
|
||||
redraw();
|
||||
resetMovable(points);
|
||||
redraw();
|
||||
}
|
||||
|
Reference in New Issue
Block a user