mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-09 09:52:34 +01:00
re-implement face merge
This commit is contained in:
parent
15bec39f66
commit
ecc48b47c2
2 changed files with 62 additions and 112 deletions
|
|
@ -249,7 +249,10 @@ export class NurbsCurve { //TODO: rename to BrepCurve
|
|||
}
|
||||
|
||||
middlePoint() {
|
||||
return this.point(0.5);
|
||||
if (!this.__middlePoint) {
|
||||
this.__middlePoint = this.point(0.5);
|
||||
}
|
||||
return this.__middlePoint;
|
||||
}
|
||||
|
||||
passesThrough(point) {
|
||||
|
|
|
|||
|
|
@ -300,9 +300,7 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
let allPoints = [];
|
||||
|
||||
for (let face of originFaces) {
|
||||
face.__mergeGraph = new Map();
|
||||
for (let e of face.edges) {
|
||||
addToListInMap(face.__mergeGraph, e.vertexA, e);
|
||||
allPoints.push(e.vertexA.point);
|
||||
}
|
||||
}
|
||||
|
|
@ -331,80 +329,58 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
}
|
||||
}
|
||||
|
||||
function invalidate(face, other) {
|
||||
let edgesIndex = other.__mergeGraph;
|
||||
for (let edge of face.edges) {
|
||||
markEdgeTransferred(edge.edge);
|
||||
let testForReversedDir = edgesIndex.get(edge.vertexB);
|
||||
if (!testForReversedDir) {
|
||||
continue;
|
||||
}
|
||||
for (let testee of testForReversedDir) {
|
||||
if (invalid.has(testee)) {
|
||||
//been annihilated already
|
||||
continue;
|
||||
}
|
||||
if (isSameEdge(testee, edge)) {
|
||||
//annihilation here
|
||||
markEdgeToReplace(testee, edge.twin());
|
||||
invalid.add(testee);
|
||||
invalid.add(edge);
|
||||
}
|
||||
}
|
||||
let testForSameDir = edgesIndex.get(edge.vertexA);
|
||||
if (!testForSameDir) {
|
||||
continue;
|
||||
}
|
||||
for (let testee of testForSameDir) {
|
||||
if (isSameEdge(testee, edge)) {
|
||||
throw new CadError('BOOLEAN_INVALID_RESULT', edgeCollisionError(testee, edge));
|
||||
function invalidate(faceA, faceB) {
|
||||
|
||||
let coincidentEdges = new Set();
|
||||
|
||||
function checkCoincidentEdges(edgeA, edgeB) {
|
||||
if (isSameEdge(edgeA, edgeB)) {
|
||||
coincidentEdges.add(edgeA);
|
||||
coincidentEdges.add(edgeB);
|
||||
markEdgeTransferred(edgeA.edge);
|
||||
markEdgeTransferred(edgeB.edge);
|
||||
BREP_DEBUG.markEdge('same edge', edgeA);
|
||||
if (edgeA.vertexA === edgeB.vertexA) {
|
||||
throw new CadError('BOOLEAN_INVALID_RESULT', edgeCollisionError(edgeA, edgeB));
|
||||
} else if (edgeA.vertexA === edgeB.vertexB) {
|
||||
|
||||
invalid.add(edgeA);
|
||||
invalid.add(edgeA);
|
||||
// markEdgeToReplace(testee, edge.twin());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function invalidateEdge(face, edge) {
|
||||
let pt = edge.edge.curve.middlePoint();
|
||||
if (face.rayCast(pt).inside) {
|
||||
markEdgeTransferred(edge.edge);
|
||||
if (canEdgeBeTransferred(edge, face, opType)) {
|
||||
EdgeSolveData.setPriority(edge, 10);
|
||||
} else {
|
||||
invalid.push(edge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let loop of face.loops) {
|
||||
for (let [inEdge, outEdge, v] of loop.encloses) {
|
||||
if (DEBUG.FACE_MERGE) {
|
||||
__DEBUG__.Clear();
|
||||
__DEBUG__.AddFace(face);
|
||||
__DEBUG__.AddHalfEdge(inEdge, 0x0000ff);
|
||||
__DEBUG__.AddHalfEdge(outEdge, 0xffff00);
|
||||
}
|
||||
let edgesToTest = edgesIndex.get(v);
|
||||
if (!edgesToTest) {
|
||||
function invalidateEdges(faceA, faceB) {
|
||||
for (let edgeA of faceA.edges) {
|
||||
if (coincidentEdges.has(edgeA)) {
|
||||
continue;
|
||||
}
|
||||
for (let testee of edgesToTest) {
|
||||
if (DEBUG.FACE_MERGE) {
|
||||
__DEBUG__.AddHalfEdge(testee, 0xffffff);
|
||||
}
|
||||
|
||||
if (invalid.has(testee)) {
|
||||
//been annihilated already
|
||||
continue;
|
||||
}
|
||||
|
||||
let inside = isInsideEnclose(originFace.surface.normal(v.point),
|
||||
testee.tangentAtStart(), inEdge.tangentAtEnd(), outEdge.tangentAtStart(), true);
|
||||
|
||||
classify(inside, testee);
|
||||
}
|
||||
invalidateEdge(faceB, edgeA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function invalidateByRayCast(face, other) {
|
||||
for (let testee of other.edges) {
|
||||
if (!invalid.has(testee) && !valid.has(testee)) {
|
||||
let pt = testee.edge.curve.middlePoint();
|
||||
let inside = face.rayCast(pt, referenceSurface).inside;
|
||||
let isValid = classify(inside, testee);
|
||||
let classificationSet = isValid ? valid : invalid;
|
||||
for (let e of testee.loop.halfEdges) {
|
||||
classificationSet.add(e);
|
||||
}
|
||||
|
||||
for (let edgeA of faceA.edges) {
|
||||
for (let edgeB of faceB.edges) {
|
||||
checkCoincidentEdges(edgeA, edgeB);
|
||||
}
|
||||
}
|
||||
|
||||
invalidateEdges(faceA, faceB);
|
||||
invalidateEdges(faceB, faceA);
|
||||
}
|
||||
|
||||
for (let faceA of facesA) {
|
||||
|
|
@ -414,39 +390,6 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
}
|
||||
}
|
||||
|
||||
for (let face of originFaces) {
|
||||
for (let loop of face.loops) {
|
||||
loop.link();
|
||||
}
|
||||
}
|
||||
|
||||
for (let edge of valid) {
|
||||
EdgeSolveData.setPriority(edge, 10);
|
||||
}
|
||||
|
||||
for (let edge of invalid) {
|
||||
edge = edge.next;
|
||||
while (!valid.has(edge) && !invalid.has(edge)) {
|
||||
invalid.add(edge);
|
||||
edge = edge.next;
|
||||
}
|
||||
}
|
||||
|
||||
for (let edge of valid) {
|
||||
edge = edge.next;
|
||||
while (!valid.has(edge) && !invalid.has(edge)) {
|
||||
valid.add(edge);
|
||||
edge = edge.next;
|
||||
}
|
||||
}
|
||||
|
||||
for (let faceA of facesA) {
|
||||
for (let faceB of facesB) {
|
||||
invalidateByRayCast(faceA, faceB);
|
||||
invalidateByRayCast(faceB, faceA);
|
||||
}
|
||||
}
|
||||
|
||||
let graph = new EdgeGraph();
|
||||
let discardedEdges = new Set();
|
||||
for (let face of originFaces) {
|
||||
|
|
@ -459,12 +402,12 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
}
|
||||
|
||||
let detectedLoops = detectLoops(originFace.surface, graph);
|
||||
for (let loop of detectedLoops) {
|
||||
for (let edge of loop.halfEdges) {
|
||||
EdgeSolveData.setPriority(edge, 1);
|
||||
discardedEdges.delete(edge);
|
||||
}
|
||||
}
|
||||
// for (let loop of detectedLoops) {
|
||||
// for (let edge of loop.halfEdges) {
|
||||
// // EdgeSolveData.setPriority(edge, 1);
|
||||
// discardedEdges.delete(edge);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
return {
|
||||
|
|
@ -720,14 +663,18 @@ function intersectFaces(shellA, shellB, operationType) {
|
|||
}
|
||||
}
|
||||
|
||||
export function chooseValidEdge(edge, face, operationType) {
|
||||
let pt = edge.edge.curve.middlePoint();
|
||||
let edgeTangent = edge.tangent(pt);
|
||||
let edgeFaceNormal = edge.loop.face.surface.normal(pt);
|
||||
function canEdgeBeTransferred(edge, face, operationType) {
|
||||
let testPoint = edge.edge.curve.middlePoint();
|
||||
let edgeTangent = edge.tangent(testPoint);
|
||||
let edgeFaceNormal = edge.loop.face.surface.normal(testPoint);
|
||||
let edgeFaceDir = edgeTangent.cross(edgeFaceNormal);
|
||||
let faceNormal = face.surface.normal(pt);
|
||||
let faceNormal = face.surface.normal(testPoint);
|
||||
let outside = edgeFaceDir.dot(faceNormal);
|
||||
return (operationType === TYPE.INTERSECT) === outside ? edge.twin() : edge;
|
||||
return (operationType === TYPE.INTERSECT) !== outside;
|
||||
}
|
||||
|
||||
export function chooseValidEdge(edge, face, operationType) {
|
||||
return canEdgeBeTransferred(edge, face, operationType) ? edge : edge.twin();
|
||||
}
|
||||
|
||||
function transferEdges(faceSource, faceDest, operationType) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue