support nurbs / adopt nurbs api for boolean

This commit is contained in:
Val Erastov 2017-09-19 18:50:42 -07:00
parent 43b27d18c5
commit e3859bdebc
6 changed files with 76 additions and 79 deletions

View file

@ -122,6 +122,11 @@ function addGlobalDebugActions(app) {
__DEBUG__.AddPoint(nurbs.point(1, 1), 0x0000ff);
__DEBUG__.AddPoint(nurbs.point(0, 1), 0x00ffff);
},
AddNormal: (atPoint, normal, color, scale) => {
scale = scale || 100;
__DEBUG__.AddSegment(atPoint, atPoint.plus(normal.multiply(scale)), color);
},
HideSolids: () => {
app.findAllSolidsOnScene().forEach(s => s.cadGroup.traverse(o => o.visible = false));
app.viewer.render();

View file

@ -84,14 +84,16 @@ App.prototype.addShellOnScene = function(shell, skin) {
};
App.prototype.scratchCode = function() {
let box = createBox(500, 500, 500);
let sphere = createSphere([0, 200, 0], 300);
let clylinder = createCylinder(150, 500);
this.viewer.workGroup.add(box.toThreeMesh());
// this.viewer.workGroup.add(sphere.toThreeMesh());
this.viewer.workGroup.add(clylinder.toThreeMesh());
this.viewer.render();
const app = this;
const box1 = app.TPI.brep.primitives.box(500, 500, 500);
const box2 = app.TPI.brep.primitives.box(250, 250, 750, new Matrix3().translate(25, 25, 0));
const box3 = app.TPI.brep.primitives.box(150, 600, 350, new Matrix3().translate(25, 25, -250));
let result = app.TPI.brep.bool.union(box1, box2);
// let result = app.TPI.brep.bool.subtract(box1, box2);
// result = app.TPI.brep.bool.subtract(result, box3);
app.addShellOnScene(box1);
app.addShellOnScene(box2);
app.viewer.render();
};

View file

@ -357,16 +357,6 @@ export function iterateSegments(items, callback) {
}
}
export function invertLoop(loop) {
for (let halfEdge of loop.halfEdges) {
const t = halfEdge.vertexA;
halfEdge.vertexA = halfEdge.vertexB;
halfEdge.vertexB = t;
}
loop.halfEdges.reverse();
linkSegments(loop.halfEdges);
}
export function createPlaneLoop(vertices, curves) {
const loop = new Loop();

View file

@ -51,11 +51,11 @@ export class NurbsCurve extends Curve {
}
tangentAtPoint(point) {
return new Point().set3(this.verb.tangent(this.verb.closestParam(point.data())));
return new Point().set3(this.verb.tangent(this.verb.closestParam(point.data())))._normalize();
}
tangentAtParam(param) {
return new Point().set3(this.verb.tangent(param ));
return new Point().set3(this.verb.tangent(param ))._normalize();
}
closestDistanceToPoint(point) {
@ -67,10 +67,6 @@ export class NurbsCurve extends Curve {
return this.verb.split(this.verb.closestParam(point.data)).map(v => new NurbsCurve(v));
}
intersect(other, tolerance) {
return verb.geom.Intersect.curves(this.verb, other.verb, tolerance);
}
invert() {
return new NurbsCurve(this.verb.reverse());
}
@ -78,7 +74,16 @@ export class NurbsCurve extends Curve {
point(u) {
return new Point().set3(this.verb.point(u));
}
intersectCurve(other, tol) {
return verb.geom.Intersect.curves(this.verb, other.verb, tol).map( i => ({
u0: i.u0,
u1: i.u1,
p0: new Vector().set3(i.point0),
p1: new Vector().set3(i.point1)
}));
}
static createByPoints(points, degeree) {
points = points.map(p => p.data());
return new NurbsCurve(new verb.geom.NurbsCurve.byPoints(points, degeree));
@ -111,6 +116,7 @@ export class NurbsSurface extends Surface {
if (this.inverted) {
normal._negate();
}
normal._normalize();
return normal;
}
@ -119,22 +125,19 @@ export class NurbsSurface extends Surface {
if (this.inverted) {
normal._negate();
}
normal._normalize();
return normal;
}
normalInMiddle(point) {
let normal = new Vector().set3(this.verb.normal(0.5, 0.5));
if (this.inverted) {
normal._negate();
}
return normal;
normalInMiddle() {
return this.normalUV(0.5, 0.5);
}
point(u, v) {
return new Point().set3(this.verb.point(u, v));
}
intersectForSameClass(other, tol) {
intersectSurfaceForSameClass(other, tol) {
const curves = verb.geom.Intersect.surfaces(this.verb, other.verb, tol);
let inverted = this.inverted !== other.inverted;
return curves.map(curve => new NurbsCurve(inverted ? curve.reverse() : curve));

View file

@ -7,15 +7,15 @@ export class Surface {
//--------------------------------------------------------------------------------------------------------------------
intersectForSameClass() {
intersectSurfaceForSameClass() {
throw 'not implemented';
}
intersect(other, tol) {
intersectSurface(other, tol) {
if (this.isSameClass(other)) {
return this.intersectForSameClass(other, tol)
return this.intersectSurfaceForSameClass(other, tol)
}
return this.toNurbs().intersectForSameClass(other.toNurbs(), tol);
return this.toNurbs().intersectSurfaceForSameClass(other.toNurbs(), tol);
};
//--------------------------------------------------------------------------------------------------------------------

View file

@ -46,20 +46,20 @@ export function subtract( shell1, shell2 ) {
export function invert( shell ) {
for (let face of shell.faces) {
face.surface = face.surface.invert();
for (let loop of face.loops) {
invertLoop(loop);
}
for (let edge of shell.edges) {
edge.invert();
}
for (let loop of face.loops) {
for (let i = 0; i < loop.halfEdges.length; i++) {
loop.halfEdges[i] = loop.halfEdges[i].twin();
}
loop.halfEdges.reverse();
loop.link();
}
}
BREPValidator.validateToConsole(shell);
}
function invertLoop(loop) {
BREPBuilder.invertLoop(loop);
}
export function BooleanAlgorithm( shell1, shell2, type ) {
POINT_TO_VERT.clear();
@ -297,11 +297,16 @@ function leftTurningMeasure(v1, v2, normal) {
}
function intersectEdges(shell1, shell2) {
const tuples1 = [];
const tuples2 = [];
function collectTuples(shell) {
const tuples = [];
for (let edge of shell.edges) {
tuples.push([edge]);
}
return tuples;
}
shell1.edges.forEach(e => tuples1.push([e]));
shell2.edges.forEach(e => tuples2.push([e]));
const tuples1 = collectTuples(shell1);
const tuples2 = collectTuples(shell2);
for (let i = 0; i < tuples1.length; i++) {
const edges1 = tuples1[i];
@ -311,7 +316,7 @@ function intersectEdges(shell1, shell2) {
const e1 = edges1[k];
for (let l = edges2.length - 1; l >= 0 ; l--) {
const e2 = edges2[l];
let points = e1.curve.intersect(e2.curve, TOLERANCE);
let points = e1.curve.intersectCurve(e2.curve, TOLERANCE);
for (let point of points) {
const {u0, u1} = point;
@ -344,26 +349,23 @@ function intersectEdges(shell1, shell2) {
}
}
//TODO: extract to a unit test
function curveDirectionValidityTest(curve, surface1, surface2, operationType) {
function fixCurveDirection(curve, surface1, surface2, operationType) {
let point = curve.point(0.5);
let tangent = curve.tangentAtPoint(point);
assert('tangent should be normalized', eq(tangent.length, 1));
let normal1 = surface1.normal(point);
assert('normal should be normalized', eq(normal1.length, 1));
let normal2 = surface2.normal(point);
assert('normal should be normalized', eq(normal2.length, 1));
let expectedDirection = normal1.cross(normal2);
if (operationType === TYPE.UNION) {
expectedDirection._negate();
}
let sameAsExpected = expectedDirection.dot(tangent) > 0;
assert('wrong intersection curve direction', sameAsExpected);
if (sameAsExpected) {
curve = curve.invert();
}
return curve;
}
//TODO: extract to a unit test
@ -392,13 +394,10 @@ function intersectFaces(shell1, shell2, operationType) {
}
}
let curves = face1.surface.intersect(face2.surface, TOLERANCE);
let curves = face1.surface.intersectSurface(face2.surface, TOLERANCE);
for (let curve of curves) {
if (invert) {
curve = curve.invert();
}
curveDirectionValidityTest(curve, face1.surface, face2.surface, invert);
curve = fixCurveDirection(curve, face1.surface, face2.surface, operationType);
const nodes = [];
collectNodesOfIntersectionOfFace(curve, face1, nodes);
collectNodesOfIntersectionOfFace(curve, face2, nodes);
@ -409,7 +408,7 @@ function intersectFaces(shell1, shell2, operationType) {
split(nodes, curve, newEdges);
newEdges.forEach(e => {
newEdgeDirectionValidityTest(e, curve)
newEdgeDirectionValidityTest(e, curve);
addNewEdge(face1, e.halfEdge1);
addNewEdge(face2, e.halfEdge2);
});
@ -465,33 +464,31 @@ function collectNodesOfIntersectionOfFace(curve, face, nodes) {
function collectNodesOfIntersection(curve, loop, nodes) {
for (let edge of loop.halfEdges) {
intersectCurveWithEdge(curves, edge, nodes);
intersectCurveWithEdge(curve, edge, nodes);
}
}
function intersectCurveWithEdge(curve, edge, result) {
for (let i = 0; i < curves.length; ++i) {
const points = edge.edge.curve.intersectCurve(curve);
for (let point of points) {
const {u0, u1} = point;
const points = edge.edge.curve.intersectCurve(curve, TOLERANCE);
for (let point of points) {
const {u0, u1} = point;
let vertex;
if (equal(u0, 0)) {
vertex = edge.edge.halfEdge1.vertexA;
} else if (equal(u0, 1)) {
vertex = edge.edge.halfEdge1.vertexB;
} else {
vertex = new Vertex(edge.edge.curve.point(u0));
}
result.push(new Node(vertex, edge, curve, u1));
let vertex;
if (equal(u0, 0)) {
vertex = edge.edge.halfEdge1.vertexA;
} else if (equal(u0, 1)) {
vertex = edge.edge.halfEdge1.vertexB;
} else {
vertex = new Vertex(edge.edge.curve.point(u0));
}
result.push(new Node(vertex, edge, curve, u1));
}
}
function split(nodes, curve, result) {
nodes.sort((n1, n2) => n1.u - n2.u);
nodes = nodes.filter(n => n !== null);
nodes.sort((n1, n2) => n1.u - n2.u);
for (let i = 0; i < nodes.length - 1; i++) {
let inNode = nodes[i];
let outNode = nodes[i + 1];