jsketcher/web/app/cad/sketch/sketchBoundaries.js
2020-07-18 22:18:03 -07:00

117 lines
No EOL
3.2 KiB
JavaScript

import {areEqual, circleFromPoints, distanceAB, radiusOfCurvature, TOLERANCE} from '../../../../modules/math/commons';
import * as vec from 'math/vec';
import {iteratePath} from '../cad-utils';
import NurbsCurve from '../../brep/geom/curves/nurbsCurve';
import {veqXYZ} from '../../brep/geom/tolerance';
import curveTess, {curveTessParams} from '../../brep/geom/impl/curve/curve-tess';
export function getSketchBoundaries(sceneFace) {
const boundary = {lines: [], arcs: [], circles: [], nurbses: []};
let w2sTr = sceneFace.worldToSketchTransformation;
let _w2sTrArr = null;
let w2sTrArr = () => _w2sTrArr || (_w2sTrArr = w2sTr.toArray());
if (!sceneFace.brepFace) {
return boundary;
}
for (let he of sceneFace.brepFace.edges) {
const edge = sceneFace.shell.brepRegistry.get(he.edge);
if (!edge) {
continue;
}
const id = edge.id;
const curve = he.edge.curve.impl;
if (curve.constructor.name === 'NurbsCurve' && curve.degree() !== 1) {
let curve2d = curve.transform(w2sTrArr());
let arcRadius = findArcRadius(curve2d);
if (arcRadius !== null){
let [from, to] = curve2d.domain();
let [A, DA, DDA] = curve2d.eval(from, 2);
let [B, DB] = curve2d.eval(to, 1);
let mA = vec.normalize(DA);
let mmA = vec.normalize(DDA);
let orient = mA[0] * mmA[1] - mA[1] * mmA[0];
if (orient < 0) {
let t;
t = B;
B = A;
A = t;
t = DB;
DB = DA;
DA = t;
mA = vec.normalize(DA);
}
if (veqXYZ(A[0], A[1], 0, B[0], B[1], 0)) {
let centripetal = perpXY(vec.mul(mA, arcRadius));
let c = vec._add(centripetal, A);
boundary.circles.push({
id,
c: {x: c[0], y: c[1]},
r: arcRadius
});
continue;
}
let centripetalB = vec.normalize(DB);
perpXY(centripetalB);
let proj = vec.dot(mA, vec.sub(A, B));
let u = proj / vec.dot(mA, centripetalB);
let C = vec._add(vec._mul(centripetalB, u), B);
boundary.arcs.push({
id,
a: {x: A[0], y: A[1]},
b: {x: B[0], y: B[1]},
c: {x: C[0], y: C[1]}
});
} else {
const data = curve.transform(w2sTrArr()).serialize();
data.id = id;
boundary.nurbses.push(data);
}
} else {
const addSegment = (id, a, b) => {
boundary.lines.push({
id,
a: {x: a.x, y: a.y},
b: {x: b.x, y: b.y}
});
};
addSegment(id, w2sTr.apply(he.vertexA.point), w2sTr.apply(he.vertexB.point));
}
}
return boundary;
}
function findArcRadius(curve) {
if (curve.degree() !== 2) {
return null;
}
let [uMin, uMax] = curve.domain();
let knots = curveTessParams(curve, uMin, uMax);
let prevRadCur = null;
for (let knot of knots) {
let [P, D, DD] = curve.eval(knot, 2);
let radCur = radiusOfCurvature(D, DD);
if (prevRadCur !== null && !areEqual(radCur, prevRadCur, 0.1)) {
return null;
}
prevRadCur = radCur;
}
return prevRadCur;
}
function perpXY(v) {
let [x, y] = v;
v[0] = - y;
v[1] = x;
return v;
}