diff --git a/src/org/nschmidt/csg/CSG.java b/src/org/nschmidt/csg/CSG.java index d5b45110..51a2c791 100644 --- a/src/org/nschmidt/csg/CSG.java +++ b/src/org/nschmidt/csg/CSG.java @@ -215,15 +215,18 @@ public CSG union(CSG csg) { }); CompletableFuture f1 = CompletableFuture.supplyAsync(() -> new Node(thisPolys)); - CompletableFuture f2 = CompletableFuture.supplyAsync(() -> new Node(otherPolys)); - CompletableFuture.allOf(f1, f2).join(); + CompletableFuture f2 = CompletableFuture.supplyAsync(() -> new Node(this.createClone().polygons)); + CompletableFuture f3 = CompletableFuture.supplyAsync(() -> new Node(otherPolys)); + CompletableFuture.allOf(f1, f2, f3).join(); - final Node a; + final Node a1; + final Node a2; final Node b; try { - a = f1.get(); - b = f2.get(); + a1 = f1.get(); + a2 = f2.get(); + b = f3.get(); } catch (ExecutionException e) { // Exceptions should (tm) already be thrown by the "join()" call. throw new LDPartEditorException(e); @@ -232,15 +235,12 @@ public CSG union(CSG csg) { throw new LDPartEditorException(e); } - a.clipTo(b); - b.clipTo(a); - b.invert(); - b.clipTo(a); - b.invert(); + a1.clipTo(b); + b.clipTo(a2); final List nodes = new ArrayList<>(); final Deque st = new LinkedList<>(); - st.push(new NodePolygon(a, b.allPolygons(new ArrayList<>()))); + st.push(new NodePolygon(a1, b.allPolygons(new ArrayList<>()))); while (!st.isEmpty()) { NodePolygon np = st.pop(); Node n = np.node(); @@ -251,7 +251,7 @@ public CSG union(CSG csg) { } } - final List resultPolys = a.allPolygons(nonIntersectingPolys); + final List resultPolys = a1.allPolygons(nonIntersectingPolys); return CSG.fromPolygons(resultPolys); } diff --git a/src/org/nschmidt/csg/Node.java b/src/org/nschmidt/csg/Node.java index 1e21e8e7..eefb1184 100644 --- a/src/org/nschmidt/csg/Node.java +++ b/src/org/nschmidt/csg/Node.java @@ -91,6 +91,10 @@ public Node(List polygons) { st.push(np2); } } + + if (it == 10000) { + NLogger.debug(getClass(), "CSG limit exceeded."); //$NON-NLS-1$ + } } } diff --git a/src/org/nschmidt/csg/Plane.java b/src/org/nschmidt/csg/Plane.java index 42e7dba8..39e9e5ef 100644 --- a/src/org/nschmidt/csg/Plane.java +++ b/src/org/nschmidt/csg/Plane.java @@ -114,12 +114,29 @@ int[] getTypes(final Polygon polygon) { final int size = polygon.vertices.size(); final int[] types = new int[size + 1]; int polygonType = 0; + int coplanarityHits = 0; + boolean noCoplanar = false; for (int i = 0; i < size; i++) { double t = this.normal.dot(polygon.vertices.get(i)) - this.dist; int type = t < -Plane.epsilon ? BACK : t > Plane.epsilon ? FRONT : COPLANAR; + if (type == COPLANAR) { + coplanarityHits += 1; + if (coplanarityHits > 2 && noCoplanar) break; + } else { + noCoplanar = true; + } polygonType |= type; types[i] = type; } + + // When three or more points are co-planar, then the whole polygon is co-planar! + if (coplanarityHits > 2 && noCoplanar) { + polygonType = COPLANAR; + for (int i = 0; i < size; i++) { + types[i] = COPLANAR; + } + } + types[size] = polygonType; return types; }