jsketcher/modules/geom/impl/curve/curve-tess.js
2023-03-12 16:17:32 -07:00

58 lines
No EOL
1.3 KiB
JavaScript

import * as vec from "math/vec";
export default function curveTess(curve, min, max, tessTol, scale) {
return curveTessParams(curve, min, max, tessTol, scale).map(u => curve.point(u));
}
export function curveTessParams(curve, min, max, tessTol, scale) {
const out = [];
const knots = curve.knots();
const splits = [min];
for (const split of knots) {
if (split > min && split < max) {
splits.push(split);
}
}
splits.push(max);
function refine(u1, u2, step) {
const uDist = u2 - u1;
if (uDist < 1e-3) {
return
}
if (step < uDist) {
const mid = u1 + uDist * 0.5;
refine(u1, mid, step);
out.push(mid);
refine(mid, u2, curveStep(curve, mid, tessTol, scale));
}
}
for (let i = 1; i < splits.length; ++i) {
const u1 = splits[i - 1];
out.push(u1);
refine(u1, splits[i], curveStep(curve, u1, tessTol, scale));
}
out.push(max);
return out;
}
export function curveStep(curve, u, tessTol, scale) {
tessTol = tessTol || 1;
scale = scale || 1;
const ders = curve.eval(u, 2);
const r1 = ders[1];
const r2 = ders[2];
const r1lsq = vec.lengthSq(r1);
const r1l = Math.sqrt(r1lsq);
const r = r1lsq * r1l / vec.length(vec.cross(r1, r2));
const tol = tessTol / scale;
const step = 2 * Math.sqrt(tol*(2*r - tol)) / r1l;
return step;
}