mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 08:25:19 +01:00
78 lines
No EOL
2.4 KiB
JavaScript
78 lines
No EOL
2.4 KiB
JavaScript
import {NUMERICAL_SOLVE_TOL, TOLERANCE, TOLERANCE_01, TOLERANCE_SQ} from '../tolerance';
|
||
import {curveDomain, curvePoint, meshesIntersect, surfaceMaxDegree} from '../impl/nurbs-ext';
|
||
import {IntersectionCurve} from '../curves/intersectionCurve';
|
||
import * as vec from 'math/vec';
|
||
|
||
export function surfaceIntersect(surfaceA, surfaceB) {
|
||
const tessA = verb.eval.Tess.rationalSurfaceAdaptive(surfaceA);
|
||
const tessB = verb.eval.Tess.rationalSurfaceAdaptive(surfaceB);
|
||
|
||
function fixTessNaNPoitns(s, tess) {
|
||
for (let i = 0; i < tess.points.length; i++) {
|
||
let pt = tess.points[i];
|
||
if (Number.isNaN(pt[0]) || Number.isNaN(pt[1]) || Number.isNaN(pt[2])) {
|
||
let [u, v] = tess.uvs[i];
|
||
tess.points[i] = verb.eval.Eval.rationalSurfacePoint(s, u, v);
|
||
}
|
||
}
|
||
}
|
||
|
||
fixTessNaNPoitns(surfaceA, tessA);
|
||
fixTessNaNPoitns(surfaceB, tessB);
|
||
|
||
const resApprox = meshesIntersect(tessA, tessB, TOLERANCE, TOLERANCE_SQ, TOLERANCE_01);
|
||
const exactPls = resApprox.map(pl => pl.map(inter =>
|
||
verb.eval.Intersect.surfacesAtPointWithEstimate(surfaceA, surfaceB, inter.uv0, inter.uv1, NUMERICAL_SOLVE_TOL)
|
||
));
|
||
|
||
let curves = [];
|
||
for (let pl of exactPls) {
|
||
let points = pl.map(ip => ip.point);
|
||
|
||
points = removeSuperfluousPoints(points, 30*30); //5*5
|
||
// points.forEach(__DEBUG__.AddPoint3);
|
||
curves.push(new IntersectionCurve(points, surfaceA, surfaceB))
|
||
}
|
||
return curves;
|
||
}
|
||
|
||
//it's Douglas–Peucker and it's not well suited here
|
||
function removeSuperfluousPoints(points, tolSq) {
|
||
|
||
let out = [];
|
||
let stack = [[0, points.length - 1]];
|
||
out.push(points[0]);
|
||
while (stack.length !== 0) {
|
||
let stackItem = stack.pop();
|
||
if (!Array.isArray(stackItem)) {
|
||
out.push(points[stackItem]);
|
||
continue;
|
||
}
|
||
let [from, to] = stackItem;
|
||
let maxDistSq = tolSq;
|
||
let hero = -1;
|
||
let v = vec._normalize(vec.sub(points[to], points[from]));
|
||
|
||
for (let i = from + 1; i < to; i ++) {
|
||
let proj = vec.dot(v, vec.sub(points[i], points[from]));
|
||
let vA = vec.add(points[from], vec.mul(v, proj));
|
||
let vX = vec.sub(points[i], vA);
|
||
let perpDistSq = vec.lengthSq(vX);
|
||
if (perpDistSq > maxDistSq) {
|
||
hero = i;
|
||
maxDistSq = perpDistSq;
|
||
}
|
||
}
|
||
if (hero !== -1) {
|
||
if (to - hero > 1) {
|
||
stack.push([hero, to]);
|
||
}
|
||
stack.push(hero);
|
||
if (hero - from > 1) {
|
||
stack.push([from, hero]);
|
||
}
|
||
}
|
||
}
|
||
out.push(points[points.length - 1]);
|
||
return out;
|
||
} |