UNPKG

@thi.ng/geom-splines

Version:

nD cubic & quadratic curve analysis, conversion, interpolation, splitting

45 lines (44 loc) 1.42 kB
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 };