mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-15 21:05:22 +01:00
BREP boolean algorithm / simple topology
This commit is contained in:
parent
edad41be1e
commit
15300e225a
5 changed files with 223 additions and 94 deletions
|
|
@ -11,16 +11,34 @@ export function AddDebugSupport(app) {
|
|||
}
|
||||
|
||||
function addGlobalDebugActions(app) {
|
||||
const debugGroup = new THREE.Object3D();
|
||||
app.viewer.workGroup.add(debugGroup);
|
||||
window.__DEBUG__ = {
|
||||
AddLine: (a, b) => {
|
||||
app.viewer.workGroup.add(createLine(a, b));
|
||||
debugGroup.add(createLine(a, b));
|
||||
app.viewer.render();
|
||||
},
|
||||
AddPoint: (coordinates, or, vector) => {
|
||||
app.viewer.workGroup.add(createPoint(coordinates, or, vector));
|
||||
AddSegment: (a, b) => {
|
||||
debugGroup.add(createLine(a, b));
|
||||
debugGroup.add(createPoint(a, 0x000088));
|
||||
debugGroup.add(createPoint(b, 0x880000));
|
||||
app.viewer.render();
|
||||
},
|
||||
AddPoint: (coordinates, or, vector, andColorAtTheEnd) => {
|
||||
debugGroup.add(createPoint(coordinates, or, vector, andColorAtTheEnd));
|
||||
app.viewer.render();
|
||||
},
|
||||
AddVertex: (v) => {
|
||||
window.__DEBUG__.AddPoint(v.point);
|
||||
},
|
||||
AddHalfEdge: (he) => {
|
||||
window.__DEBUG__.AddSegment(he.vertexA.point, he.vertexB.point);
|
||||
},
|
||||
Clear: () => {
|
||||
while (debugGroup.children.length) debugGroup.remove(debugGroup.children[0]);
|
||||
app.viewer.render();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function createLine(a, b) {
|
||||
|
|
@ -31,14 +49,16 @@ function createLine(a, b) {
|
|||
return new THREE.Line(lg, debugLineMaterial);
|
||||
}
|
||||
|
||||
function createPoint(x, y, z) {
|
||||
if (!y) {
|
||||
function createPoint(x, y, z, color) {
|
||||
if (!z) {
|
||||
color = y;
|
||||
y = x.y;
|
||||
z = x.z;
|
||||
x = x.x;
|
||||
}
|
||||
color = color || 0x00ff00;
|
||||
var geometry = new THREE.SphereGeometry( 5, 16, 16 );
|
||||
var material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
|
||||
var material = new THREE.MeshBasicMaterial( {color} );
|
||||
var sphere = new THREE.Mesh(geometry, material);
|
||||
sphere.position.x = x;
|
||||
sphere.position.y = y;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,10 @@ function App() {
|
|||
}
|
||||
|
||||
App.prototype.BREPTest = function() {
|
||||
setTimeout(() => this.BREPTestImpl());
|
||||
};
|
||||
|
||||
App.prototype.BREPTestImpl = function() {
|
||||
const addToScene = (shell) => {
|
||||
const sceneSolid = new SceneSolid(shell);
|
||||
this.viewer.workGroup.add(sceneSolid.cadGroup);
|
||||
|
|
@ -78,11 +82,14 @@ App.prototype.BREPTest = function() {
|
|||
const box1 = BREPPrimitives.box(500, 500, 500);
|
||||
const box2 = BREPPrimitives.box(500, 500, 500, new Matrix3().translate(250, 250, 250));
|
||||
|
||||
addToScene(box1);
|
||||
addToScene(box2);
|
||||
//box1.faces = [box1.faces[2]];
|
||||
//box2.faces = [box2.faces[5]];
|
||||
|
||||
//addToScene(box1);
|
||||
//addToScene(box2);
|
||||
|
||||
const result = BREPBool.union(box1, box2);
|
||||
//addToScene(result);
|
||||
addToScene(result);
|
||||
|
||||
this.viewer.render()
|
||||
|
||||
|
|
|
|||
|
|
@ -16,33 +16,41 @@ export function createPrism(basePoints, height) {
|
|||
|
||||
const lidNormal = normal.multiply(-1);
|
||||
const offVector = lidNormal.multiply(height);
|
||||
const lidPoints = basePoints.map(p => p.plus(offVector));
|
||||
const lidLoop = createPlaneLoop(lidPoints.map(p => new Vertex(p)));
|
||||
const lidFace = createPlaneFace(lidNormal, lidLoop);
|
||||
|
||||
const lidSegments = [];
|
||||
iterateSegments(basePoints.map(p => p.plus(offVector)), (a, b) => lidSegments.push({a, b}));
|
||||
const lidLoop = new Loop();
|
||||
|
||||
const shell = new Shell();
|
||||
|
||||
for (let i = 0; i < baseLoop.halfEdges.length; i++) {
|
||||
const baseHalfEdge = baseLoop.halfEdges[i];
|
||||
const lidHalfEdge = lidLoop.halfEdges[i];
|
||||
const wallLoop = createPlaneLoop([baseHalfEdge.vertexA, baseHalfEdge.vertexB, lidHalfEdge.vertexB, lidHalfEdge.vertexA]);
|
||||
|
||||
const baseEdge = new Edge(new Line());
|
||||
const n = baseLoop.halfEdges.length;
|
||||
for (let i = 0; i < n; i++) {
|
||||
const baseHalfEdge = baseLoop.halfEdges[i];
|
||||
const lidSegment = lidSegments[i];
|
||||
const lidHalfEdge = createHalfEdge(lidLoop, new Vertex(lidSegment.b), new Vertex(lidSegment.a));
|
||||
|
||||
const wallPolygon = [baseHalfEdge.vertexB, baseHalfEdge.vertexA, lidHalfEdge.vertexB, lidHalfEdge.vertexA];
|
||||
const wallLoop = createPlaneLoop(wallPolygon);
|
||||
|
||||
const baseEdge = new Edge(Line.fromSegment(baseHalfEdge.vertexA.point, baseHalfEdge.vertexB.point));
|
||||
linkHalfEdges(baseEdge, baseHalfEdge, wallLoop.halfEdges[0]);
|
||||
|
||||
const lidEdge = new Edge(new Line());
|
||||
const lidEdge = new Edge(Line.fromSegment(lidHalfEdge.vertexA.point, lidHalfEdge.vertexB.point));
|
||||
linkHalfEdges(lidEdge, lidHalfEdge, wallLoop.halfEdges[2]);
|
||||
|
||||
const wallNormal = cad_utils.normalOfCCWSeq([baseHalfEdge.vertexA.point, baseHalfEdge.vertexB.point, lidHalfEdge.vertexB.point]);
|
||||
const wallNormal = cad_utils.normalOfCCWSeq(wallPolygon.map(v => v.point));
|
||||
|
||||
const wallFace = createPlaneFace(wallNormal, wallLoop);
|
||||
wallFace.debugName = 'wall_' + i;
|
||||
|
||||
shell.faces.push(wallFace);
|
||||
}
|
||||
|
||||
const lidFace = createPlaneFace(lidNormal, lidLoop);
|
||||
iterateSegments(shell.faces, (a, b) => {
|
||||
linkHalfEdges(new Edge(new Line()), a.outerLoop.halfEdges[1], b.outerLoop.halfEdges[3]);
|
||||
const halfEdgeA = a.outerLoop.halfEdges[3];
|
||||
const halfEdgeB = b.outerLoop.halfEdges[1];
|
||||
const curve = Line.fromSegment(halfEdgeA.vertexA.point, halfEdgeA.vertexB.point);
|
||||
linkHalfEdges(new Edge(curve), halfEdgeA, halfEdgeB);
|
||||
});
|
||||
|
||||
baseFace.debugName = 'base';
|
||||
|
|
@ -67,8 +75,6 @@ export function linkHalfEdges(edge, halfEdge1, halfEdge2) {
|
|||
halfEdge2.edge = edge;
|
||||
edge.halfEdge1 = halfEdge1;
|
||||
edge.halfEdge2 = halfEdge2;
|
||||
halfEdge1.vertexA.edges.push(edge);
|
||||
halfEdge1.vertexB.edges.push(edge);
|
||||
}
|
||||
|
||||
export function createPlaneLoop(vertices) {
|
||||
|
|
@ -76,17 +82,22 @@ export function createPlaneLoop(vertices) {
|
|||
const loop = new Loop();
|
||||
|
||||
iterateSegments(vertices, (a, b) => {
|
||||
const halfEdge = new HalfEdge();
|
||||
halfEdge.loop = loop;
|
||||
halfEdge.vertexA = a;
|
||||
halfEdge.vertexB = b;
|
||||
loop.halfEdges.push(halfEdge);
|
||||
createHalfEdge(loop, a, b)
|
||||
});
|
||||
|
||||
linkSegments(loop.halfEdges);
|
||||
return loop;
|
||||
}
|
||||
|
||||
export function createHalfEdge(loop, a, b) {
|
||||
const halfEdge = new HalfEdge();
|
||||
halfEdge.loop = loop;
|
||||
halfEdge.vertexA = a;
|
||||
halfEdge.vertexB = b;
|
||||
loop.halfEdges.push(halfEdge);
|
||||
return halfEdge;
|
||||
}
|
||||
|
||||
export function linkSegments(halfEdges) {
|
||||
iterateSegments(halfEdges, (prev, next) => {
|
||||
prev.next = next;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,10 @@ import {Shell} from '../topo/shell';
|
|||
import {Vertex} from '../topo/vertex';
|
||||
import {Line} from '../geom/impl/line';
|
||||
import Vector from '../../math/vector';
|
||||
import * as math from '../../math/math';
|
||||
import {Matrix3} from '../../math/l3space';
|
||||
|
||||
export const TOLERANCE = 1e-8;
|
||||
|
||||
export function union( shell1, shell2 ) {
|
||||
|
||||
|
|
@ -17,16 +21,17 @@ export function union( shell1, shell2 ) {
|
|||
intersectFaces(shell1, shell2);
|
||||
|
||||
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 (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));
|
||||
//if (shell2.faces.indexOf(face) != -1) {
|
||||
// continue;
|
||||
//}
|
||||
const edges = face.outerLoop.halfEdges.concat(faceData.newEdges);
|
||||
//edges.forEach(e => __DEBUG__.AddLine(e.vertexA.point, e.vertexB.point));
|
||||
while (true) {
|
||||
let edge = edges.pop();
|
||||
if (!edge) {
|
||||
|
|
@ -37,6 +42,8 @@ export function union( shell1, shell2 ) {
|
|||
}
|
||||
const loop = new Loop();
|
||||
while (edge) {
|
||||
//__DEBUG__.AddHalfEdge(edge);
|
||||
|
||||
loop.halfEdges.push(edge);
|
||||
seen.add(edge);
|
||||
let candidates = faceData.vertexToEdge.get(edge.vertexB);
|
||||
|
|
@ -49,11 +56,13 @@ export function union( shell1, shell2 ) {
|
|||
}
|
||||
}
|
||||
|
||||
BREPBuilder.linkSegments(loop.halfEdges);
|
||||
const newFace = new Face(face.surface);
|
||||
newFace.outerLoop = loop;
|
||||
newFace.outerLoop.face = newFace;
|
||||
result.faces.push(newFace);
|
||||
if (loop.halfEdges[0].vertexA == loop.halfEdges[loop.halfEdges.length - 1].vertexB) {
|
||||
BREPBuilder.linkSegments(loop.halfEdges);
|
||||
const newFace = new Face(face.surface);
|
||||
newFace.outerLoop = loop;
|
||||
newFace.outerLoop.face = newFace;
|
||||
result.faces.push(newFace);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
|
@ -97,31 +106,31 @@ function intersectFaces(shell1, shell2) {
|
|||
const face1 = shell1.faces[i];
|
||||
const face2 = shell2.faces[j];
|
||||
|
||||
if (face1.debugName == 'base' && face2.debugName == 'wall_3') {
|
||||
console.log('there');
|
||||
}
|
||||
|
||||
const curve = face1.surface.intersect(face2.surface);
|
||||
|
||||
const nodes = [];
|
||||
collectNodesOfIntersection(face2, face1.outerLoop, nodes);
|
||||
collectNodesOfIntersection(face1, face2.outerLoop, nodes);
|
||||
|
||||
const newEdges = [];
|
||||
const direction = face1.surface.normal.cross(face2.surface.normal);
|
||||
split(face2, face1.outerLoop, newEdges, curve, direction);
|
||||
split(face1, face2.outerLoop, newEdges, curve, direction);
|
||||
split(nodes, newEdges, curve, direction);
|
||||
|
||||
newEdges.forEach(e => {
|
||||
//__DEBUG__.AddHalfEdge(e.halfEdge1);
|
||||
console.log("new edge");
|
||||
face1.__faceSolveData.newEdges.push(e.halfEdge1);
|
||||
addToListInMap(face1.__faceSolveData.vertexToEdge, e.halfEdge1.vertexA, e.halfEdge1);
|
||||
});
|
||||
newEdges.forEach(e => {
|
||||
face2.__faceSolveData.newEdges.push(e.halfEdge2);
|
||||
|
||||
addToListInMap(face1.__faceSolveData.vertexToEdge, e.halfEdge1.vertexA, e.halfEdge1);
|
||||
addToListInMap(face2.__faceSolveData.vertexToEdge, e.halfEdge2.vertexA, e.halfEdge2);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function split(face, loop, result, onCurve, direction) {
|
||||
const nodes = [];
|
||||
function collectNodesOfIntersection(face, loop, nodes) {
|
||||
const verticesCases = new Set();
|
||||
for (let edge of loop.halfEdges) {
|
||||
const edgeSolveData = EdgeSolveData.get(edge);
|
||||
if (edgeSolveData.skipFace.has(face)) {
|
||||
|
|
@ -129,27 +138,40 @@ function split(face, loop, result, onCurve, direction) {
|
|||
}
|
||||
const preExistVertex = edgeSolveData.splitByFace.get(face);
|
||||
if (preExistVertex) {
|
||||
nodes.push(new Node(preExistVertex, edgeNormal(edge), edge));
|
||||
__DEBUG__.AddVertex(preExistVertex);
|
||||
nodes.push(new Node(preExistVertex, edgeNormal(edge), edge, face));
|
||||
continue
|
||||
}
|
||||
intersectSurfaceWithEdge(face.surface, edge, nodes);
|
||||
intersectFaceWithEdge(face, edge, nodes, verticesCases);
|
||||
}
|
||||
}
|
||||
|
||||
function split(nodes, result, onCurve, direction) {
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let inNode = nodes[i];
|
||||
//if (i == 0) __DEBUG__.AddPoint(inNode.vertex.point);
|
||||
|
||||
if (inNode == null) continue;
|
||||
nodes[i] = null;
|
||||
let closestIdx = findCloserProjection(nodes, inNode.point);
|
||||
let closestIdx = findCloserProjection(nodes, inNode);
|
||||
if (closestIdx == -1) {
|
||||
continue;
|
||||
}
|
||||
let outNode = nodes[closestIdx];
|
||||
|
||||
//if (i == 1) __DEBUG__.AddPoint(outNode.vertex.point);
|
||||
//if (i == 1) __DEBUG__.AddSegment(inNode.point, inNode.point.plus(inNode.normal.multiply(1000)));
|
||||
//__DEBUG__.AddSegment(new Vector(), outNode.normal.multiply(100));
|
||||
|
||||
if (outNode.normal.dot(inNode.normal) > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nodes[closestIdx] = null;
|
||||
|
||||
|
||||
//__DEBUG__.AddPoint(inNode.vertex.point);
|
||||
//__DEBUG__.AddPoint(outNode.vertex.point);
|
||||
|
||||
|
||||
const halfEdge1 = new HalfEdge();
|
||||
halfEdge1.vertexA = inNode.vertex;
|
||||
halfEdge1.vertexB = outNode.vertex;
|
||||
|
|
@ -158,8 +180,12 @@ function split(face, loop, result, onCurve, direction) {
|
|||
halfEdge2.vertexB = halfEdge1.vertexA;
|
||||
halfEdge2.vertexA = halfEdge1.vertexB;
|
||||
|
||||
splitEdgeByVertex(inNode.edge, halfEdge1.vertexA);
|
||||
splitEdgeByVertex(outNode.edge, halfEdge1.vertexB);
|
||||
//__DEBUG__.AddHalfEdge(halfEdge1);
|
||||
//__DEBUG__.AddSegment(new Vector(), direction.multiply(100));
|
||||
|
||||
|
||||
splitEdgeByVertex(inNode.edge, halfEdge1.vertexA, inNode.splittingFace);
|
||||
splitEdgeByVertex(outNode.edge, halfEdge1.vertexB, outNode.splittingFace);
|
||||
|
||||
const sameDirection = direction.dot(outNode.point.minus(inNode.point)) > 0;
|
||||
|
||||
|
|
@ -175,48 +201,52 @@ function split(face, loop, result, onCurve, direction) {
|
|||
}
|
||||
}
|
||||
|
||||
function splitEdgeByVertex(originHalfEdge, vertex) {
|
||||
function splitEdgeByVertex(originHalfEdge, vertex, splittingFace) {
|
||||
|
||||
function splitHalfEdge(h) {
|
||||
const newEdge = new HalfEdge();
|
||||
newEdge.vertexA = vertex;
|
||||
newEdge.vertexB = h.vertexB;
|
||||
h.vertexB = newEdge.vertexA;
|
||||
addToListInMap(h.loop.face.__faceSolveData.vertexToEdge, vertex, newEdge);
|
||||
return newEdge;
|
||||
}
|
||||
|
||||
const orig = originHalfEdge;
|
||||
|
||||
const halfEdge1 = new HalfEdge();
|
||||
halfEdge1.vertexA = vertex;
|
||||
halfEdge1.vertexB = orig.vertexB;
|
||||
|
||||
const halfEdge2 = new HalfEdge();
|
||||
halfEdge2.vertexA = halfEdge1.vertexB;
|
||||
halfEdge2.vertexB = halfEdge1.vertexA;
|
||||
|
||||
const newEdge = new Edge(orig.edge);
|
||||
BREPBuilder.linkHalfEdges(newEdge, halfEdge1, halfEdge2);
|
||||
|
||||
const twin = orig.twin();
|
||||
orig.vertexB = vertex;
|
||||
twin.vertexA = vertex;
|
||||
|
||||
if (orig.vertexA == vertex || orig.vertexB == vertex) {
|
||||
return;
|
||||
}
|
||||
|
||||
orig.loop.halfEdges.push(halfEdge1);
|
||||
twin.loop.halfEdges.push(halfEdge2);
|
||||
const newOrig = splitHalfEdge(orig);
|
||||
const newTwin = splitHalfEdge(twin);
|
||||
|
||||
halfEdge1.loop = orig.loop;
|
||||
halfEdge2.loop = twin.loop;
|
||||
|
||||
EdgeSolveData.transfer(orig, halfEdge1);
|
||||
EdgeSolveData.transfer(twin, halfEdge2);
|
||||
BREPBuilder.linkHalfEdges(orig.edge, orig, newTwin);
|
||||
BREPBuilder.linkHalfEdges(new Edge(orig.edge.curve), twin, newOrig);
|
||||
|
||||
orig.loop.halfEdges.splice(orig.loop.halfEdges.indexOf(orig) + 1, 0, newOrig);
|
||||
twin.loop.halfEdges.splice(twin.loop.halfEdges.indexOf(twin) + 1, 0, newTwin);
|
||||
|
||||
EdgeSolveData.createIfEmpty(twin).splitByFace.set(orig.loop.face, vertex);
|
||||
EdgeSolveData.createIfEmpty(halfEdge2).skipFace.add(orig.loop.face);
|
||||
newOrig.loop = orig.loop;
|
||||
newTwin.loop = twin.loop;
|
||||
|
||||
EdgeSolveData.transfer(orig, newOrig);
|
||||
EdgeSolveData.transfer(twin, newTwin);
|
||||
|
||||
addToListInMap(orig.loop.face.__faceSolveData.vertexToEdge, vertex, halfEdge1);
|
||||
addToListInMap(twin.loop.face.__faceSolveData.vertexToEdge, vertex, halfEdge2);
|
||||
EdgeSolveData.createIfEmpty(twin).splitByFace.set(splittingFace, vertex);
|
||||
EdgeSolveData.createIfEmpty(newTwin).skipFace.add(splittingFace);
|
||||
}
|
||||
|
||||
function findCloserProjection(nodes, point) {
|
||||
function findCloserProjection(nodes, toNode) {
|
||||
let hero = -1;
|
||||
let heroDistance = Number.MAX_VALUE;
|
||||
for (let i = 0; i < nodes.length; i++) {
|
||||
let node = nodes[i];
|
||||
if (node == null) continue;
|
||||
let projectionDistance = node.normal.dot(node.point.minus(point));
|
||||
if (hero == -1 || (projectionDistance > 0 && projectionDistance < heroDistance)) {
|
||||
let projectionDistance = toNode.normal.dot(node.point.minus(toNode.point));
|
||||
if (projectionDistance > 0 && projectionDistance < heroDistance) {
|
||||
hero = i;
|
||||
heroDistance = projectionDistance;
|
||||
}
|
||||
|
|
@ -224,20 +254,57 @@ function findCloserProjection(nodes, point) {
|
|||
return hero;
|
||||
}
|
||||
|
||||
function intersectSurfaceWithEdge(surface, edge, result) {
|
||||
function intersectFaceWithEdge(face, edge, result, vertecies) {
|
||||
|
||||
if (vertecies.has(edge.vertexA) || vertecies.has(edge.vertexB)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const p0 = edge.vertexA.point;
|
||||
const ab = edge.vertexB.point.minus(p0);
|
||||
const length = ab.length();
|
||||
const v = ab._multiply(1 / length);
|
||||
const edgeLine = new Line(p0, v);
|
||||
const t = edgeLine.intersectSurface(surface);
|
||||
const t = edgeLine.intersectSurface(face.surface);
|
||||
if (t >= 0 && t <= length) {
|
||||
const pointOfIntersection = edgeLine.parametricEquation(t);
|
||||
const edgeNormal = edge.loop.face.surface.normal.cross(v)._normalize() ;
|
||||
result.push(new Node(new Vertex(pointOfIntersection), edgeNormal, edge));
|
||||
//TODO: should check if point on an edge then exclude that edge from further intersection test cuz it would produce two identical Nodes
|
||||
//TODO: should check if point on a vertex then exclude two edges of the vertex from further intersection test cuz it would produce three identical Nodes
|
||||
if (pointBelongsToFace(pointOfIntersection, face)) {
|
||||
let vertexOfIntersection;
|
||||
if (math.areVectorsEqual(edge.vertexA.point, pointOfIntersection, TOLERANCE)) {
|
||||
vertecies.add(edge.vertexA);
|
||||
vertexOfIntersection = edge.vertexA;
|
||||
//console.log("point A on surface");
|
||||
} if (math.areVectorsEqual(edge.vertexB.point, pointOfIntersection, TOLERANCE)) {
|
||||
vertecies.add(edge.vertexB);
|
||||
vertexOfIntersection = edge.vertexB;
|
||||
//console.log("point B on surface");
|
||||
} else {
|
||||
vertexOfIntersection = new Vertex(pointOfIntersection);
|
||||
duplicatePointTest(pointOfIntersection);
|
||||
}
|
||||
|
||||
const edgeNormal = edge.loop.face.surface.normal.cross(v)._normalize() ;
|
||||
result.push(new Node(vertexOfIntersection, edgeNormal, edge));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function pointBelongsToFace(point, face) {
|
||||
//TODO: holes case
|
||||
const tr = new Matrix3().setBasis(face.surface.calculateBasis());
|
||||
const polygon = face.outerLoop.asPolygon().map(p => tr.apply(p));
|
||||
const point2d = tr.apply(point);
|
||||
return pointInsidePolygon(point2d, polygon);
|
||||
}
|
||||
|
||||
function pointInsidePolygon(point, polygon) {
|
||||
//TODO: absolutely unacceptable way. should be done honoring intersecting edges and vertices. see TODOs above
|
||||
return math.isPointInsidePolygon(point, polygon);
|
||||
}
|
||||
|
||||
function edgeNormal(edge) {
|
||||
return edge.loop.face.surface.normal.cross( edge.vertexB.point.minus(edge.vertexA.point) )._normalize();
|
||||
}
|
||||
|
|
@ -285,14 +352,36 @@ EdgeSolveData.transfer = function(from, to) {
|
|||
to.__edgeSolveData = from.__edgeSolveData;
|
||||
};
|
||||
|
||||
function Node(vertex, normal, splitsEdge) {
|
||||
function Node(vertex, normal, splitsEdge, splittingFace) {
|
||||
this.vertex = vertex;
|
||||
this.normal = normal;
|
||||
this.point = vertex.point;
|
||||
this.edge = splitsEdge;
|
||||
this.splittingFace = splittingFace;
|
||||
__DEBUG__.AddPoint(this.point);
|
||||
}
|
||||
|
||||
|
||||
let __DEBUG_POINT_DUPS = [];
|
||||
function duplicatePointTest(point, data) {
|
||||
data = data || {};
|
||||
let res = false;
|
||||
for (let entry of __DEBUG_POINT_DUPS) {
|
||||
let other = entry[0];
|
||||
if (math.areVectorsEqual(point, other, TOLERANCE)) {
|
||||
res = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
__DEBUG_POINT_DUPS.push([point, data]);
|
||||
if (res) {
|
||||
__DEBUG__.Clear();
|
||||
__DEBUG__.AddPoint(point);
|
||||
console.error('DUPLICATE DETECTED: ' + point)
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
class SolveData {
|
||||
constructor() {
|
||||
this.faceData = [];
|
||||
|
|
@ -315,3 +404,5 @@ function addToListInMap(map, key, value) {
|
|||
}
|
||||
list.push(value);
|
||||
}
|
||||
|
||||
let xxx = 0;
|
||||
|
|
|
|||
|
|
@ -69,10 +69,10 @@ export class SceneSolid {
|
|||
const visited = new Set();
|
||||
for (let face of this.shell.faces) {
|
||||
for (let halfEdge of face.outerLoop.halfEdges) {
|
||||
if (!visited.has(halfEdge.edge)) {
|
||||
//if (!visited.has(halfEdge.edge)) {
|
||||
visited.add(halfEdge.edge);
|
||||
this.addLineToScene(halfEdge.vertexA.point, halfEdge.vertexB.point, halfEdge.edge);
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -134,7 +134,7 @@ function createSolidMaterial() {
|
|||
polygonOffset : true,
|
||||
polygonOffsetFactor : 1,
|
||||
polygonOffsetUnits : 2,
|
||||
side : THREE.DoubleSide
|
||||
//side : THREE.DoubleSide
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue