@davepagurek/flo-mat
Version:
Medial / Scale Axis Transform (MAT/SAT) Library.
76 lines (62 loc) • 1.98 kB
text/typescript
import { ddDeflate, allRootsCertified, RootInterval } from 'flo-poly';
import { evalDeCasteljauDd, getFootpointPolyDd } from 'flo-bezier3';
import { Curve } from "../curve/curve.js";
/**
* @internal
* @param curve The curve
* @param p The point from which to check
* @param tRange The allowed t range
* @param touchedCurve The bezier on which p is located
* @param t The t value of the bezier that locates p
*/
function closestPointsOnCurvePrecise(
curve: Curve,
p: number[],
[tS,tE]: number[] = [0,1],
touchedCurve: Curve,
t: number): {
p: number[];
t: number;
}[] {
const _poly = getFootpointPolyDd(curve.ps, p);
const poly = curve === touchedCurve
? ddDeflate(_poly, t)
: _poly;
const roots: Omit<RootInterval,'multiplicity'>[] =
allRootsCertified(poly, tS, tE);
// Also test the endpoints
const dontPush0 = (
(t === 1 && curve === touchedCurve.next) ||
(t === 0 && curve === touchedCurve)
);
const dontPush1 = (
(t === 0 && curve === touchedCurve.prev) ||
(t === 1 && curve === touchedCurve)
);
if (tS === 0) {
if (!dontPush0) { roots.push({ tS: 0, tE: 0 }); }
} else if (tS === 1) {
if (!dontPush1) { roots.push({ tS: 1, tE: 1 }); }
} else {
roots.push({ tS: tS, tE: tS });
}
if (tE === 0) {
if (!dontPush0) { roots.push({ tS: 0, tE: 0 }); }
} else if (tE === 1) {
if (!dontPush1) { roots.push({ tS: 1, tE: 1 }); }
} else {
roots.push({ tS: tE, tE: tE });
}
const ps = roots.map(
root => {
const tS = root.tS;
const tE = root.tE;
const t = tS < 0
? 0
: tE > 1 ? 1 : (tS + tE)/2;
return { p: evalDeCasteljauDd(curve.ps,[0,t]).map(v => v[1]), t }
}
);
return ps;
}
export { closestPointsOnCurvePrecise }