1
0
mirror of https://github.com/Pomax/BezierInfo-2.git synced 2025-08-17 06:04:31 +02:00
Files
2020-09-05 22:50:12 -07:00

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