mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-08 01:13:27 +01:00
BREP boolean operations / debug info
This commit is contained in:
parent
c4ee5ba7c6
commit
edad41be1e
7 changed files with 85 additions and 31 deletions
|
|
@ -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 = {
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
|
|
@ -1,6 +0,0 @@
|
||||||
|
|
||||||
export function transform(shell, matrix) {
|
|
||||||
for (let vertex of shell.vertices) {
|
|
||||||
matrix._apply(vertex.point);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue