BREP boolean operations / debug info

This commit is contained in:
Val Erastov 2017-01-09 21:28:06 -08:00
parent c4ee5ba7c6
commit edad41be1e
7 changed files with 85 additions and 31 deletions

View file

@ -1,12 +1,49 @@
import {checkForSelectedFaces} from './actions/action-helpers' import {checkForSelectedFaces} from './actions/action-helpers'
export const DEBUG = false; export const DEBUG = true;
export function AddDebugSupport(app) { export function AddDebugSupport(app) {
if (!DEBUG) return; if (!DEBUG) return;
app.actionManager.registerActions(DebugActions); app.actionManager.registerActions(DebugActions);
app.ui.registerMenuActions(DebugMenuConfig); app.ui.registerMenuActions(DebugMenuConfig);
app.controlBar.add('menu.debug', true); app.controlBar.add('menu.debug', true);
addGlobalDebugActions(app);
}
function addGlobalDebugActions(app) {
window.__DEBUG__ = {
AddLine: (a, b) => {
app.viewer.workGroup.add(createLine(a, b));
app.viewer.render();
},
AddPoint: (coordinates, or, vector) => {
app.viewer.workGroup.add(createPoint(coordinates, or, vector));
app.viewer.render();
}
};
}
function createLine(a, b) {
const debugLineMaterial = new THREE.LineBasicMaterial({color: 0xFA8072, linewidth: 3});
const lg = new THREE.Geometry();
lg.vertices.push(a.three());
lg.vertices.push(b.three());
return new THREE.Line(lg, debugLineMaterial);
}
function createPoint(x, y, z) {
if (!y) {
y = x.y;
z = x.z;
x = x.x;
}
var geometry = new THREE.SphereGeometry( 5, 16, 16 );
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
var sphere = new THREE.Mesh(geometry, material);
sphere.position.x = x;
sphere.position.y = y;
sphere.position.z = z;
return sphere;
} }
const DebugMenuConfig = { const DebugMenuConfig = {

View file

@ -17,7 +17,6 @@ import {init as initSample} from './sample'
import '../../css/app3d.less' import '../../css/app3d.less'
import * as BREPPrimitives from '../brep/brep-primitives' import * as BREPPrimitives from '../brep/brep-primitives'
import * as BREPAffine from '../brep/operations/affine'
import * as BREPBool from '../brep/operations/boolean' import * as BREPBool from '../brep/operations/boolean'
import {SceneSolid} from '../brep/viz/scene-solid' import {SceneSolid} from '../brep/viz/scene-solid'
@ -77,15 +76,13 @@ App.prototype.BREPTest = function() {
this.viewer.workGroup.add(sceneSolid.cadGroup); this.viewer.workGroup.add(sceneSolid.cadGroup);
}; };
const box1 = BREPPrimitives.box(500, 500, 500); const box1 = BREPPrimitives.box(500, 500, 500);
const box2 = BREPPrimitives.box(500, 500, 500); const box2 = BREPPrimitives.box(500, 500, 500, new Matrix3().translate(250, 250, 250));
BREPAffine.transform(box2, new Matrix3().translate(250, 250, 250)); addToScene(box1);
addToScene(box2);
//addToScene(box1);
//addToScene(box2);
const result = BREPBool.union(box1, box2); const result = BREPBool.union(box1, box2);
addToScene(result); //addToScene(result);
this.viewer.render() this.viewer.render()

View file

@ -46,7 +46,7 @@ export function createPrism(basePoints, height) {
}); });
baseFace.debugName = 'base'; baseFace.debugName = 'base';
baseFace.debugName = 'lid'; lidFace.debugName = 'lid';
shell.faces.push(baseFace, lidFace); shell.faces.push(baseFace, lidFace);
return shell; return shell;

View file

@ -1,13 +1,19 @@
import * as BREPBuilder from './brep-builder' import * as BREPBuilder from './brep-builder'
import {Matrix3} from '../math/l3space'
export function box(w, h, d) { export function box(w, h, d, tr) {
const wh = w * 0.5; const wh = w * 0.5;
const hh = h * 0.5; const hh = h * 0.5;
const dh = d * 0.5; const dh = d * 0.5;
if (!tr) {
tr = IDENTITY;
}
return BREPBuilder.createPrism([ return BREPBuilder.createPrism([
BREPBuilder.point(-wh, -hh, dh), tr._apply(BREPBuilder.point(-wh, -hh, dh)),
BREPBuilder.point( wh, -hh, dh), tr._apply(BREPBuilder.point( wh, -hh, dh)),
BREPBuilder.point( wh, hh, dh), tr._apply(BREPBuilder.point( wh, hh, dh)),
BREPBuilder.point(-wh, hh, dh) tr._apply(BREPBuilder.point(-wh, hh, dh))
], d); ], d);
} }
const IDENTITY = new Matrix3();

View file

@ -1,6 +0,0 @@
export function transform(shell, matrix) {
for (let vertex of shell.vertices) {
matrix._apply(vertex.point);
}
}

View file

@ -22,8 +22,11 @@ export function union( shell1, shell2 ) {
const seen = new Set(); const seen = new Set();
const face = faceData.face; const face = faceData.face;
const edges = faceData.newEdges.concat(face.outerLoop); if (shell2.faces.indexOf(face) != -1) {
continue;
}
const edges = faceData.newEdges.concat(face.outerLoop.halfEdges);
edges.forEach(e => __DEBUG__.AddLine(e.vertexA.point, e.vertexB.point));
while (true) { while (true) {
let edge = edges.pop(); let edge = edges.pop();
if (!edge) { if (!edge) {
@ -37,7 +40,10 @@ export function union( shell1, shell2 ) {
loop.halfEdges.push(edge); loop.halfEdges.push(edge);
seen.add(edge); seen.add(edge);
let candidates = faceData.vertexToEdge.get(edge.vertexB); let candidates = faceData.vertexToEdge.get(edge.vertexB);
edge = findMaxTurningLeft(candidates, face); if (!candidates) {
break;
}
edge = findMaxTurningLeft(edge, candidates);
if (seen.has(edge)) { if (seen.has(edge)) {
break; break;
} }
@ -47,9 +53,10 @@ export function union( shell1, shell2 ) {
const newFace = new Face(face.surface); const newFace = new Face(face.surface);
newFace.outerLoop = loop; newFace.outerLoop = loop;
newFace.outerLoop.face = newFace; newFace.outerLoop.face = newFace;
result.push(newFace); result.faces.push(newFace);
} }
} }
return result;
} }
function initSolveData(shell, facesData) { function initSolveData(shell, facesData) {
@ -64,7 +71,7 @@ function initSolveData(shell, facesData) {
} }
} }
function findMaxTurningLeft(edge, edges, face) { function findMaxTurningLeft(edge, edges) {
edges = edges.slice(); edges = edges.slice();
function edgeVector(edge) { function edgeVector(edge) {
return edge.vertexB.point.minus(edge.vertexA.point)._normalize(); return edge.vertexB.point.minus(edge.vertexA.point)._normalize();
@ -90,6 +97,10 @@ function intersectFaces(shell1, shell2) {
const face1 = shell1.faces[i]; const face1 = shell1.faces[i];
const face2 = shell2.faces[j]; const face2 = shell2.faces[j];
if (face1.debugName == 'base' && face2.debugName == 'wall_3') {
console.log('there');
}
const curve = face1.surface.intersect(face2.surface); const curve = face1.surface.intersect(face2.surface);
const newEdges = []; const newEdges = [];
@ -125,10 +136,11 @@ function split(face, loop, result, onCurve, direction) {
} }
for (let i = 0; i < nodes.length; i++) { for (let i = 0; i < nodes.length; i++) {
let inNode = nodes[i]; let inNode = nodes[i];
if (inNode == null) continue;
nodes[i] = null; nodes[i] = null;
let closestIdx = findCloserProjection(nodes, inNode.point); let closestIdx = findCloserProjection(nodes, inNode.point);
if (closestIdx == -1) { if (closestIdx == -1) {
throw 'consider me'; continue;
} }
let outNode = nodes[closestIdx]; let outNode = nodes[closestIdx];
@ -181,8 +193,8 @@ function splitEdgeByVertex(originHalfEdge, vertex) {
orig.vertexB = vertex; orig.vertexB = vertex;
twin.vertexA = vertex; twin.vertexA = vertex;
orig.loop.push(halfEdge1); orig.loop.halfEdges.push(halfEdge1);
twin.loop.push(halfEdge2); twin.loop.halfEdges.push(halfEdge2);
halfEdge1.loop = orig.loop; halfEdge1.loop = orig.loop;
halfEdge2.loop = twin.loop; halfEdge2.loop = twin.loop;
@ -277,6 +289,8 @@ function Node(vertex, normal, splitsEdge) {
this.vertex = vertex; this.vertex = vertex;
this.normal = normal; this.normal = normal;
this.point = vertex.point; this.point = vertex.point;
this.edge = splitsEdge;
__DEBUG__.AddPoint(this.point);
} }
class SolveData { class SolveData {
@ -299,5 +313,5 @@ function addToListInMap(map, key, value) {
list = []; list = [];
map.set(key, list); map.set(key, list);
} }
list.add(value); list.push(value);
} }

View file

@ -50,7 +50,13 @@ export class SceneSolid {
face.normal = normal; face.normal = normal;
face.materialIndex = gIdx ++; face.materialIndex = gIdx ++;
geom.faces.push(face); geom.faces.push(face);
//face.color.set(new THREE.Color().setRGB( Math.random(), Math.random(), Math.random())); if (brepFace.debugName == 'base') {
face.color.set(new THREE.Color().setHex( 0x000077 ));
}
if (brepFace.debugName == 'wall_3') {
face.color.set(new THREE.Color().setHex( 0x007700 ));
}
} }
//view.setFaceColor(polyFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null); //view.setFaceColor(polyFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null);
off = geom.vertices.length; off = geom.vertices.length;