mirror of
https://github.com/Pomax/BezierInfo-2.git
synced 2025-08-17 06:04:31 +02:00
102 lines
2.7 KiB
JavaScript
102 lines
2.7 KiB
JavaScript
// setup={this.setupCubic} draw={this.drawSingleArc} onKeyDown={this.props.onKeyDown}
|
|
|
|
let curve, utils = Bezier.getUtils();
|
|
|
|
setup() {
|
|
curve = Bezier.defaultCubic(this);
|
|
setMovable(curve.points);
|
|
setSlider(`.slide-control`, `error`, 0.5);
|
|
}
|
|
|
|
draw() {
|
|
clear();
|
|
|
|
curve.drawSkeleton();
|
|
curve.drawCurve();
|
|
|
|
setColor(`#FF000040`);
|
|
let a = this.getArc(curve);
|
|
arc(
|
|
a.x, a.y, a.r, a.s, a.e,
|
|
// draw a wedge, not just the arc
|
|
a.x, a.y
|
|
);
|
|
|
|
setColor("black");
|
|
text(`Arc approximation with total error ${this.error}`, this.width/2, 15, CENTER);
|
|
curve.drawPoints();
|
|
}
|
|
|
|
getArc(curve) {
|
|
let ts = 0,
|
|
te = 1,
|
|
tm = te,
|
|
safety = 0,
|
|
np1 = curve.get(ts), np2, np3,
|
|
arc,
|
|
currGood = false,
|
|
prevGood = false,
|
|
done,
|
|
prev_e = 1,
|
|
step = 0;
|
|
|
|
// Find where the good/bad boundary is
|
|
te = 1;
|
|
|
|
// step 2: find the best possible arc
|
|
do {
|
|
prevGood = currGood;
|
|
tm = (ts + te) / 2;
|
|
step++;
|
|
|
|
np2 = curve.get(tm);
|
|
np3 = curve.get(te);
|
|
|
|
arc = utils.getccenter(np1, np2, np3);
|
|
arc.interval = { start: ts, end: te, };
|
|
|
|
let error = this.computeError(arc, np1, ts, te);
|
|
currGood = (error <= this.error);
|
|
|
|
done = prevGood && !currGood;
|
|
if (!done) prev_e = te;
|
|
|
|
// this arc is fine: try a wider arc
|
|
if (currGood) {
|
|
// if e is already at max, then we're done for this arc.
|
|
if (te >= 1) {
|
|
// make sure we cap at t=1
|
|
arc.interval.end = prev_e = 1;
|
|
// if we capped the arc segment to t=1 we also need to make sure that
|
|
// the arc's end angle is correct with respect to the bezier end point.
|
|
if (te > 1) {
|
|
let d = {
|
|
x: arc.x + arc.r * cos(arc.e),
|
|
y: arc.y + arc.r * sin(arc.e),
|
|
};
|
|
arc.e += utils.angle({ x: arc.x, y: arc.y }, d, curve.points[3]);
|
|
}
|
|
done = true;
|
|
break;
|
|
}
|
|
// if not, move it up by half the iteration distance
|
|
te = te + (te - ts) / 2;
|
|
}
|
|
|
|
// This is a bad arc: we need to move 'e' down to find a good arc
|
|
else { te = tm; }
|
|
} while (!done && safety++ < 100);
|
|
|
|
return arc;
|
|
}
|
|
|
|
computeError(pc, np1, s, e) {
|
|
const q = (e - s) / 4,
|
|
c1 = curve.get(s + q),
|
|
c2 = curve.get(e - q),
|
|
ref = dist(pc.x, pc.y, np1.x, np1.y),
|
|
d1 = dist(pc.x, pc.y, c1.x, c1.y),
|
|
d2 = dist(pc.x, pc.y, c2.x, c2.y);
|
|
return abs(d1 - ref) + abs(d2 - ref);
|
|
}
|