BREP / union / intersect / subtract

This commit is contained in:
Val Erastov 2017-01-12 02:25:40 -08:00
parent 19181e6135
commit e66f7f7126
6 changed files with 68 additions and 6 deletions

View file

@ -91,7 +91,7 @@ App.prototype.BREPTestImpl = function() {
//addToScene(box1);
//addToScene(box2);
const result = BREPBool.union(box1, box2);
const result = BREPBool.subtract(box1, box2);
addToScene(result);
this.viewer.render()

View file

@ -59,6 +59,7 @@ export function createPrism(basePoints, height) {
lidFace.debugName = 'lid';
shell.faces.push(baseFace, lidFace);
shell.faces.forEach(f => f.shell = shell);
return shell;
}

View file

@ -9,6 +9,9 @@ export class BREPValidator {
validateShell(shell) {
for (let face of shell.faces) {
if (face.shell !== shell) {
this.addError(new FaceRefersToWrongShell(face, shell))
}
this.validateFace(face);
}
}
@ -77,6 +80,17 @@ BREPValidator.validateToConsole = function(shell) {
}
};
class FaceRefersToWrongShell {
constructor(face, shell) {
this.face = face;
this.shell = shell;
}
message() {
return "face refers to a shell it doesn't belong to";
}
}
class VerticesOfHalfEdgeArentConnected {
constructor(loop, halfEdge1, halfEdge2) {
this.loop = loop;

View file

@ -30,4 +30,7 @@ export class Plane extends Surface {
return super.intersect();
}
invert() {
return new Plane(this.normal.multiply(-1), - this.w);
}
}

View file

@ -12,22 +12,62 @@ import {Matrix3} from '../../math/l3space';
export const TOLERANCE = 1e-8;
const TYPE = {
UNION: 0,
INTERSECT: 1,
SUBTRACT: 2
};
export function union( shell1, shell2 ) {
return BooleanAlgorithm(shell1, shell2, TYPE.UNION);
}
export function intersect( shell1, shell2 ) {
return BooleanAlgorithm(shell1, shell2, TYPE.INTERSECT);
}
export function subtract( shell1, shell2 ) {
invert(shell2);
return BooleanAlgorithm(shell1, shell2, TYPE.SUBTRACT);
}
export function invert( shell ) {
for (let face of shell.faces) {
face.surface = face.surface.invert();
invertLoop(face.outerLoop);
}
BREPValidator.validateToConsole(shell);
}
function invertLoop(loop) {
for (let halfEdge of loop.halfEdges) {
const t = halfEdge.vertexA;
halfEdge.vertexA = halfEdge.vertexB;
halfEdge.vertexB = t;
}
loop.halfEdges.reverse();
BREPBuilder.linkSegments(loop.halfEdges);
}
export function BooleanAlgorithm( shell1, shell2, type ) {
const facesData = [];
initSolveData(shell1, facesData);
initSolveData(shell2, facesData);
intersectFaces(shell1, shell2);
intersectFaces(shell1, shell2, type !== TYPE.UNION);
const result = new Shell();
//__DEBUG__.AddSegment(shell2.faces[0].outerLoop.halfEdges[0].vertexA.point, shell2.faces[0].outerLoop.halfEdges[0].vertexB.point)
for (let faceData of facesData) {
const seen = new Set();
const face = faceData.face;
if (faceData.newEdges.length == 0) {
if (type === TYPE.INTERSECT) continue;
if (type === TYPE.SUBTRACT && face.shell == shell2) continue;
}
const seen = new Set();
const edges = face.outerLoop.halfEdges.concat(faceData.newEdges);
while (true) {
let edge = edges.pop();
@ -61,6 +101,7 @@ export function union( shell1, shell2 ) {
const newFace = new Face(face.surface);
newFace.outerLoop = loop;
newFace.outerLoop.face = newFace;
newFace.shell = result;
result.faces.push(newFace);
}
}
@ -101,7 +142,7 @@ function findMaxTurningLeft(edge, edges) {
return edges[0];
}
function intersectFaces(shell1, shell2) {
function intersectFaces(shell1, shell2, inverseCrossEdgeDirection) {
for (let i = 0; i < shell1.faces.length; i++) {
for (let j = 0; j < shell2.faces.length; j++) {
const face1 = shell1.faces[i];
@ -115,11 +156,13 @@ function intersectFaces(shell1, shell2) {
const newEdges = [];
const direction = face1.surface.normal.cross(face2.surface.normal);
if (inverseCrossEdgeDirection) {
direction._multiply(-1);
}
split(nodes, newEdges, curve, direction);
newEdges.forEach(e => {
//__DEBUG__.AddHalfEdge(e.halfEdge1);
console.log("new edge");
face1.__faceSolveData.newEdges.push(e.halfEdge1);
face2.__faceSolveData.newEdges.push(e.halfEdge2);

View file

@ -3,6 +3,7 @@ export class Face {
constructor(surface) {
this.surface = surface;
this.shell = null;
this.outerLoop = null;
this.innerLoops = [];
}