mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-05 00:07:58 +02:00
242 lines
7.0 KiB
JavaScript
242 lines
7.0 KiB
JavaScript
var atan2 = Math.atan2, sqrt = Math.sqrt, sin = Math.sin, cos = Math.cos;
|
|
|
|
module.exports = {
|
|
setupQuadratic: function(api) {
|
|
var w = api.getPanelWidth(),
|
|
h = api.getPanelHeight(),
|
|
cx = w/2, cy = h/2, pad = 40,
|
|
pts = [
|
|
// first curve:
|
|
{x:cx,y:pad}, {x:w-pad,y:pad}, {x:w-pad,y:cy},
|
|
// subsequent curve
|
|
{x:w-pad,y:h-pad}, {x:cx,y:h-pad},
|
|
// subsequent curve
|
|
{x:pad,y:h-pad}, {x:pad,y:cy},
|
|
// final curve control point
|
|
{x:pad,y:pad}
|
|
];
|
|
api.lpts = pts;
|
|
},
|
|
|
|
setupCubic: function(api) {
|
|
var w = api.getPanelWidth(),
|
|
h = api.getPanelHeight(),
|
|
cx = w/2, cy = h/2, pad = 40,
|
|
r = (w - 2*pad)/2,
|
|
k = 0.55228,
|
|
kr = k*r,
|
|
pts = [
|
|
// first curve:
|
|
{x:cx,y:pad}, {x:cx+kr,y:pad}, {x:w-pad,y:cy-kr}, {x:w-pad,y:cy},
|
|
// subsequent curve
|
|
{x:w-pad,y:cy+kr}, {x:cx+kr,y:h-pad}, {x:cx,y:h-pad},
|
|
// subsequent curve
|
|
{x:cx-kr,y:h-pad}, {x:pad,y:cy+kr}, {x:pad,y:cy},
|
|
// final curve control point
|
|
{x:pad,y:cy-kr}, {x:cx-kr,y:pad}
|
|
];
|
|
api.lpts = pts;
|
|
},
|
|
|
|
movePointsQuadraticLD: function(api, i) {
|
|
// ...we need to move _everything_
|
|
var anchor, fixed, toMove;
|
|
for(var p=1; p<4; p++) {
|
|
anchor = i + (2*p - 2) + api.lpts.length;
|
|
anchor = api.lpts[anchor % api.lpts.length];
|
|
fixed = i + (2*p - 1);
|
|
fixed = api.lpts[fixed % api.lpts.length];
|
|
toMove = i + 2*p;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
|
|
toMove.x = fixed.x + (fixed.x - anchor.x);
|
|
toMove.y = fixed.y + (fixed.y - anchor.y);
|
|
}
|
|
// then, the furthest point cannot be computed properly!
|
|
toMove = i + 6;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
api.problem = toMove;
|
|
},
|
|
|
|
movePointsCubicLD: function(api, i) {
|
|
var toMove, fixed;
|
|
if (i%3 === 1) {
|
|
fixed = i-1;
|
|
fixed += (fixed < 0) ? api.lpts.length : 0;
|
|
toMove = i-2;
|
|
toMove += (toMove < 0) ? api.lpts.length : 0;
|
|
} else {
|
|
fixed = (i+1) % api.lpts.length;
|
|
toMove = (i+2) % api.lpts.length;
|
|
}
|
|
fixed = api.lpts[fixed];
|
|
toMove = api.lpts[toMove];
|
|
toMove.x = fixed.x + (fixed.x - api.mp.x);
|
|
toMove.y = fixed.y + (fixed.y - api.mp.y);
|
|
},
|
|
|
|
linkDerivatives: function(evt, api) {
|
|
if (api.mp) {
|
|
var quad = api.lpts.length === 8;
|
|
var i = api.mp_idx;
|
|
if (quad) {
|
|
if (i%2 !== 0) { this.movePointsQuadraticLD(api, i); }
|
|
} else {
|
|
if(i%3 !== 0) { this.movePointsCubicLD(api, i); }
|
|
}
|
|
}
|
|
},
|
|
|
|
movePointsQuadraticDirOnly: function(api, i) {
|
|
// ...we need to move _everything_ ...again
|
|
var anchor, fixed, toMove;
|
|
|
|
// move left and right
|
|
[-1,1].forEach(v => {
|
|
anchor = api.mp;
|
|
fixed = i + v + api.lpts.length;
|
|
fixed = api.lpts[fixed % api.lpts.length];
|
|
toMove = i + 2*v + api.lpts.length;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
var a = atan2(fixed.y - anchor.y, fixed.x - anchor.x),
|
|
dx = toMove.x - fixed.x,
|
|
dy = toMove.y - fixed.y,
|
|
d = sqrt(dx*dx + dy*dy);
|
|
toMove.x = fixed.x + d*cos(a);
|
|
toMove.y = fixed.y + d*sin(a);
|
|
});
|
|
|
|
// then, the furthest point cannot be computed properly!
|
|
toMove = i + 4;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
api.problem = toMove;
|
|
},
|
|
|
|
movePointsCubicDirOnly: function(api, i) {
|
|
var toMove, fixed;
|
|
if (i%3 === 1) {
|
|
fixed = i-1;
|
|
fixed += (fixed < 0) ? api.lpts.length : 0;
|
|
toMove = i-2;
|
|
toMove += (toMove < 0) ? api.lpts.length : 0;
|
|
} else {
|
|
fixed = (i+1) % api.lpts.length;
|
|
toMove = (i+2) % api.lpts.length;
|
|
}
|
|
fixed = api.lpts[fixed];
|
|
toMove = api.lpts[toMove];
|
|
var a = atan2(fixed.y - api.mp.y, fixed.x - api.mp.x),
|
|
dx = toMove.x - fixed.x,
|
|
dy = toMove.y - fixed.y,
|
|
d = sqrt(dx*dx + dy*dy);
|
|
toMove.x = fixed.x + d*cos(a);
|
|
toMove.y = fixed.y + d*sin(a);
|
|
},
|
|
|
|
linkDirection: function(evt, api) {
|
|
if (api.mp) {
|
|
var quad = api.lpts.length === 8;
|
|
var i = api.mp_idx;
|
|
if (quad) {
|
|
if(i%2 !== 0) { this.movePointsQuadraticDirOnly(api, i); }
|
|
} else {
|
|
if(i%3 !== 0) { this.movePointsCubicDirOnly(api, i); }
|
|
}
|
|
}
|
|
},
|
|
|
|
bufferPoints: function(evt, api) {
|
|
api.bpts = JSON.parse(JSON.stringify(api.lpts));
|
|
},
|
|
|
|
moveQuadraticPoint: function(api, i) {
|
|
this.moveCubicPoint(api,i);
|
|
|
|
// then move the other control points
|
|
[-1,1].forEach(v => {
|
|
var anchor = i - v + api.lpts.length;
|
|
anchor = api.lpts[anchor % api.lpts.length];
|
|
var fixed = i - 2*v + api.lpts.length;
|
|
fixed = api.lpts[fixed % api.lpts.length];
|
|
var toMove = i - 3*v + api.lpts.length;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
var a = atan2(fixed.y - anchor.y, fixed.x - anchor.x),
|
|
dx = toMove.x - fixed.x,
|
|
dy = toMove.y - fixed.y,
|
|
d = sqrt(dx*dx + dy*dy);
|
|
toMove.x = fixed.x + d*cos(a);
|
|
toMove.y = fixed.y + d*sin(a);
|
|
});
|
|
|
|
// then signal a problem
|
|
var toMove = i + 4;
|
|
toMove = api.lpts[toMove % api.lpts.length];
|
|
api.problem = toMove;
|
|
},
|
|
|
|
moveCubicPoint: function(api, i) {
|
|
var op = api.bpts[i],
|
|
np = api.lpts[i],
|
|
dx = np.x - op.x,
|
|
dy = np.y - op.y,
|
|
len = api.lpts.length,
|
|
l = i-1+len,
|
|
r = i+1,
|
|
// original left and right
|
|
ol = api.bpts[l % len],
|
|
or = api.bpts[r % len],
|
|
// current left and right
|
|
nl = api.lpts[l % len],
|
|
nr = api.lpts[r % len];
|
|
// update current left
|
|
nl.x = ol.x + dx;
|
|
nl.y = ol.y + dy;
|
|
// update current right
|
|
nr.x = or.x + dx;
|
|
nr.y = or.y + dy;
|
|
return {x:dx, y:dy};
|
|
},
|
|
|
|
modelCurve: function(evt, api) {
|
|
if (api.mp) {
|
|
var quad = api.lpts.length === 8;
|
|
var i = api.mp_idx;
|
|
if (quad) {
|
|
if (i%2 !== 0) { this.movePointsQuadraticDirOnly(api, i); }
|
|
else { this.moveQuadraticPoint(api, i); }
|
|
}
|
|
else {
|
|
if(i%3 !== 0) { this.movePointsCubicDirOnly(api, i); }
|
|
else { this.moveCubicPoint(api, i); }
|
|
}
|
|
}
|
|
},
|
|
|
|
draw: function(api, curves) {
|
|
api.reset();
|
|
var pts = api.lpts;
|
|
var quad = pts.length === 8;
|
|
|
|
var c1 = quad ? new api.Bezier(pts[0],pts[1],pts[2]) : new api.Bezier(pts[0],pts[1],pts[2],pts[3]);
|
|
api.drawSkeleton(c1, false, true);
|
|
api.drawCurve(c1);
|
|
|
|
var c2 = quad ? new api.Bezier(pts[2],pts[3],pts[4]) : new api.Bezier(pts[3],pts[4],pts[5],pts[6]);
|
|
api.drawSkeleton(c2, false, true);
|
|
api.drawCurve(c2);
|
|
|
|
var c3 = quad ? new api.Bezier(pts[4],pts[5],pts[6]) : new api.Bezier(pts[6],pts[7],pts[8],pts[9]);
|
|
api.drawSkeleton(c3, false, true);
|
|
api.drawCurve(c3);
|
|
|
|
var c4 = quad ? new api.Bezier(pts[6],pts[7],pts[0]) : new api.Bezier(pts[9],pts[10],pts[11],pts[0]);
|
|
api.drawSkeleton(c4, false, true);
|
|
api.drawCurve(c4);
|
|
|
|
if (api.problem) {
|
|
api.setColor("red");
|
|
api.drawCircle(api.problem,5);
|
|
}
|
|
}
|
|
};
|