@thi.ng/geom-splines
Version:
nD cubic & quadratic curve analysis, conversion, interpolation, splitting
45 lines (44 loc) • 1.42 kB
JavaScript
import { pointAtTheta } from "@thi.ng/geom-arc/point-at";
import { sincos } from "@thi.ng/math/angle";
import { EPS, HALF_PI, PI } from "@thi.ng/math/api";
import { roundEps } from "@thi.ng/math/prec";
import { magSq2 } from "@thi.ng/vectors/magsq";
import { cubicFromLine } from "./cubic-line.js";
const cubicFromArc = (pos, r, axis, start, end) => {
const p = pointAtTheta(pos, r, axis, start);
const q = pointAtTheta(pos, r, axis, end);
const delta = end - start;
const [rx, ry] = r;
const [s, c] = sincos(axis);
const dx = c * (p[0] - q[0]) / 2 + s * (p[1] - q[1]) / 2;
const dy = -s * (p[0] - q[0]) / 2 + c * (p[1] - q[1]) / 2;
if (Math.abs(delta) < PI && dx === 0 && dy === 0 || magSq2(r) < EPS) {
return [cubicFromLine(p, q)];
}
const mapP = (x, y) => {
x *= rx;
y *= ry;
return [c * x - s * y + pos[0], s * x + c * y + pos[1]];
};
const res = [];
const n = Math.ceil(roundEps(Math.abs(delta) / HALF_PI, 1e-3));
const d = delta / n;
const t = 8 / 6 * Math.tan(0.25 * d);
if (!isFinite(t)) {
return [cubicFromLine(p, q)];
}
for (let i = n, theta = start, sc = sincos(theta); i > 0; i--, theta += d) {
const [s1, c1] = sc;
const [s2, c2] = sc = sincos(theta + d);
res.push([
mapP(c1, s1),
mapP(c1 - s1 * t, s1 + c1 * t),
mapP(c2 + s2 * t, s2 - c2 * t),
mapP(c2, s2)
]);
}
return res;
};
export {
cubicFromArc
};