mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-24 01:15:25 +01:00
choose between coincident edges with same direction while face overlap merge
Closes #47 Union 2 shells: side faces are in same plane, resulted a null shell
This commit is contained in:
parent
5dfc499162
commit
3173626ea2
2 changed files with 61 additions and 27 deletions
|
|
@ -79,7 +79,9 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
|||
type = TYPE.INTERSECT;
|
||||
}
|
||||
|
||||
let workingFaces = [];
|
||||
let workingFaces = collectFaces(shellA, shellB);
|
||||
|
||||
initOperationData(workingFaces);
|
||||
|
||||
mergeVertices(shellA, shellB);
|
||||
initVertexFactory(shellA, shellB);
|
||||
|
|
@ -87,9 +89,6 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
|
|||
intersectEdges(shellA, shellB);
|
||||
let mergedFaces = mergeOverlappingFaces(shellA, shellB, type);
|
||||
|
||||
initOperationData(shellA, workingFaces);
|
||||
initOperationData(shellB, workingFaces);
|
||||
|
||||
intersectFaces(shellA, shellB, type);
|
||||
|
||||
replaceMergedFaces(workingFaces, mergedFaces);
|
||||
|
|
@ -239,7 +238,7 @@ function detectLoops(surface, graph) {
|
|||
}
|
||||
|
||||
|
||||
function findOverlappingFaces(shell1, shell2) {
|
||||
function findOverlappingFaces(shellA, shellB) {
|
||||
|
||||
function overlapsImpl(face1, face2) {
|
||||
function pointOnFace(face, pt) {
|
||||
|
|
@ -264,21 +263,23 @@ function findOverlappingFaces(shell1, shell2) {
|
|||
|
||||
let overlapGroups = [];
|
||||
|
||||
for (let face1 of shell1.faces) {
|
||||
for (let face2 of shell2.faces) {
|
||||
for (let faceA of shellA.faces) {
|
||||
for (let faceB of shellB.faces) {
|
||||
if (DEBUG.FACE_MERGE) {
|
||||
__DEBUG__.Clear();
|
||||
__DEBUG__.AddFace(face1, 0x0000ff);
|
||||
__DEBUG__.AddFace(face2);
|
||||
__DEBUG__.AddFace(faceA, 0x0000ff);
|
||||
__DEBUG__.AddFace(faceB);
|
||||
}
|
||||
if (overlaps(face1, face2) ) {
|
||||
let group = overlapGroups.find(g => g[0].has(face1) || g[1].has(face2));
|
||||
if (overlaps(faceA, faceB) ) {
|
||||
let group = overlapGroups.find(g => g[0].has(faceA) || g[1].has(faceB));
|
||||
if (!group) {
|
||||
group = [new Set(), new Set()];
|
||||
overlapGroups.push(group);
|
||||
}
|
||||
group[0].add(face1);
|
||||
group[1].add(face2);
|
||||
group[A].add(faceA);
|
||||
group[B].add(faceB);
|
||||
faceA.op.overlaps = group[B];
|
||||
faceB.op.overlaps = group[A];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -341,12 +342,18 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
if (edgeA.vertexA === edgeB.vertexA) {
|
||||
// chooseBetweenEqualEdges();
|
||||
// canEdgeBeTransferred(edge, face, opType)
|
||||
throw new CadError({
|
||||
kind: CadError.KIND.UNSUPPORTED_CASE,
|
||||
code: 'edge collision on face merge',
|
||||
relatedTopoObjects: [edgeA, edgeB],
|
||||
userMessage: "edges can't be coincident for this operation"
|
||||
});
|
||||
let faceAAdjacent = edgeA.twin().loop.face;
|
||||
let faceBAdjacent = edgeB.twin().loop.face;
|
||||
if (faceAAdjacent.op.overlaps && faceAAdjacent.op.overlaps.has(faceBAdjacent)) {
|
||||
invalid.add(edgeB);
|
||||
} else {
|
||||
throw new CadError({
|
||||
kind: CadError.KIND.UNSUPPORTED_CASE,
|
||||
code: 'edge collision on face merge',
|
||||
relatedTopoObjects: [edgeA, edgeB],
|
||||
userMessage: "edges can't be coincident for this operation"
|
||||
});
|
||||
}
|
||||
} else if (edgeA.vertexA === edgeB.vertexB) {
|
||||
|
||||
invalid.add(edgeA);
|
||||
|
|
@ -369,12 +376,12 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
}
|
||||
}
|
||||
|
||||
function invalidateEdges(faceA, faceB) {
|
||||
for (let edgeA of faceA.edges) {
|
||||
if (coincidentEdges.has(edgeA)) {
|
||||
function invalidateEdges(faceX, faceY) {
|
||||
for (let edgeX of faceX.edges) {
|
||||
if (coincidentEdges.has(edgeX)) {
|
||||
continue;
|
||||
}
|
||||
invalidateEdge(faceB, edgeA);
|
||||
invalidateEdge(faceY, edgeX);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -391,7 +398,6 @@ function mergeFaces(facesA, facesB, opType) {
|
|||
for (let faceA of facesA) {
|
||||
for (let faceB of facesB) {
|
||||
invalidate(faceA, faceB);
|
||||
invalidate(faceB, faceA);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -522,10 +528,21 @@ export function loopsToFaces(originFace, loops, out) {
|
|||
}
|
||||
}
|
||||
|
||||
function initOperationData(shell, faceCollector) {
|
||||
for (let face of shell.faces) {
|
||||
function collectFaces(shellA, shellB) {
|
||||
function collect(shell, out) {
|
||||
for (let face of shell.faces) {
|
||||
out.push(face);
|
||||
}
|
||||
}
|
||||
let out = [];
|
||||
collect(shellA, out);
|
||||
collect(shellB, out);
|
||||
return out;
|
||||
}
|
||||
|
||||
function initOperationData(faces) {
|
||||
for (let face of faces) {
|
||||
initOperationDataForFace(face);
|
||||
faceCollector.push(face);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1160,6 +1177,7 @@ class FaceOperationData extends EdgeGraph {
|
|||
this.face = face;
|
||||
this.newEdges = [];
|
||||
this.collidedEdges = [];
|
||||
this.overlaps = null;
|
||||
}
|
||||
|
||||
markTransferredFrom(edge) {
|
||||
|
|
|
|||
|
|
@ -261,6 +261,22 @@ export default defineTests([
|
|||
'vertices': [[-250, -250, -250], [-250, -250, -163], [-250, -250, 157], [-250, -250, 250], [-250, 250, -250], [-250, 250, -163], [-250, 250, 157], [-250, 250, 250], [250, -250, -250], [250, -250, -163], [250, -250, 157], [250, -250, 250], [250, 250, -250], [250, 250, -163], [250, 250, 157], [250, 250, 250]],
|
||||
'faces': [[[7, 3, 11, 15]], [[8, 0, 4, 12]], [[5, 1, 9, 13]], [[2, 6, 14, 10]], [[2, 10, 11, 3]], [[9, 1, 0, 8]], [[13, 9, 8, 12]], [[10, 14, 15, 11]], [[5, 13, 12, 4]], [[14, 6, 7, 15]], [[6, 2, 3, 7]], [[1, 5, 4, 0]]]
|
||||
}
|
||||
},
|
||||
|
||||
{
|
||||
'name': '4AdjacentFacesUnion_BUG_47',
|
||||
'state': {
|
||||
'sketches': {'0:3': {'Segment': [[[-379, 250], [157, 250]], [[157, 250], [157, -250]], [[157, -250], [-379, -250]], [[-379, -250], [-379, 250]]]}},
|
||||
'operations': [{'type': 'BOX', 'params': {'width': 500, 'height': 500, 'depth': 500}}, {
|
||||
'type': 'EXTRUDE',
|
||||
'params': {'value': -500, 'prism': 1, 'angle': 0, 'rotation': 0, 'face': '0:3'}
|
||||
}]
|
||||
},
|
||||
'expected': {
|
||||
'format': 'LOOPS',
|
||||
'vertices': [[-250, -250, -379], [-250, -250, -250], [-250, -250, 157], [-250, -250, 250], [-250, 250, -379], [-250, 250, -250], [-250, 250, 157], [-250, 250, 250], [250, -250, -379], [250, -250, -250], [250, -250, 157], [250, -250, 250], [250, 250, -379], [250, 250, -250], [250, 250, 157], [250, 250, 250]],
|
||||
'faces': [[[7, 3, 11, 15]], [[8, 0, 4, 12]], [[0, 8, 9, 10, 11, 3, 2, 1]], [[9, 8, 12, 13, 14, 15, 11, 10]], [[13, 12, 4, 5, 6, 7, 15, 14]], [[6, 5, 4, 0, 1, 2, 3, 7]]]
|
||||
}
|
||||
}
|
||||
|
||||
]);
|
||||
|
|
|
|||
Loading…
Reference in a new issue