Skip to content

Commit 01bf1f7

Browse files
committed
Attempting to narrow down the STL loading error
1 parent 3ed53dd commit 01bf1f7

File tree

4 files changed

+101
-141
lines changed

4 files changed

+101
-141
lines changed

src/main/java/eu/mihosoft/vrl/v3d/Bounds.java

+5
Original file line numberDiff line numberDiff line change
@@ -328,5 +328,10 @@ public double getTotalY() {
328328
public double getTotalZ() {
329329
return (-this.getMinZ() + this.getMaxZ());
330330
}
331+
public boolean isBoundsTouching(Bounds incoming) {
332+
return this.getMaxX() > incoming.getMinX() && this.getMinX() < incoming.getMaxX()
333+
&& this.getMaxY() > incoming.getMinY() && this.getMinY() < incoming.getMaxY()
334+
&& this.getMaxZ() > incoming.getMinZ() && this.getMinZ() < incoming.getMaxZ();
335+
}
331336

332337
}

src/main/java/eu/mihosoft/vrl/v3d/CSG.java

+32-126
Original file line numberDiff line numberDiff line change
@@ -1498,14 +1498,11 @@ public CSG triangulate(boolean fix) {
14981498
if (triangulated)
14991499
return this;
15001500

1501-
//// com.neuronrobotics.sdk.common.Log.error("CSG triangulating for " +
1502-
//// name+"..");
1503-
ArrayList<Polygon> toAdd = new ArrayList<Polygon>();
1504-
ArrayList<Polygon> degenerates = new ArrayList<Polygon>();
15051501
if (providerOf3d == null && Debug3dProvider.provider != null)
15061502
providerOf3d = Debug3dProvider.provider;
15071503
IDebug3dProvider start = Debug3dProvider.provider;
15081504
Debug3dProvider.setProvider(null);
1505+
//performTriangulation();
15091506
if (preventNonManifoldTriangles) {
15101507
for (int i = 0; i < 2; i++)
15111508
if (isUseGPU()) {
@@ -1514,49 +1511,24 @@ public CSG triangulate(boolean fix) {
15141511
runCPUMakeManifold();
15151512
}
15161513
}
1517-
try {
1518-
Stream<Polygon> polygonStream;
1519-
polygonStream = polygons.stream();
1520-
// TODO this should work in paralell but throws immpossible NPE's instead.
1521-
// if (getPolygons().size() > 200) {
1522-
// polygonStream = polygons.parallelStream();
1523-
// }
1524-
polygonStream.forEach(p -> updatePolygons(toAdd, degenerates, p));
1525-
// for (int i = 0; i < polygons.size(); i++) {
1526-
// Polygon p = polygons.get(i);
1527-
// updatePolygons(toAdd, degenerates, p);
1528-
// }
1529-
1530-
if (degenerates.size() > 0) {
1531-
//
1532-
// Debug3dProvider.setProvider(providerOf3d);
1533-
1534-
if (fix) {
1535-
Debug3dProvider.clearScreen();
1536-
Stream<Polygon> degenStreeam;
1537-
degenStreeam = polygons.stream(); // this operation is read-modify-write and can not be done in
1538-
// parallel
1539-
// com.neuronrobotics.sdk.common.Log.error("Found "+degenerates.size()+"
1540-
// degenerate triangles, Attempting to fix");
1541-
degenStreeam.forEach(p -> fixDegenerates(toAdd, p));
1542-
} else {
1543-
needsDegeneratesPruned = true;
1544-
toAdd.addAll(degenerates);
1545-
}
1546-
}
1547-
if (toAdd.size() > 0) {
1548-
setPolygons(toAdd);
1549-
}
1550-
// now all polygons are definantly triangles
1551-
triangulated = true;
1552-
} catch (Throwable t) {
1553-
t.printStackTrace();
1554-
1555-
}
1514+
performTriangulation();
1515+
// now all polygons are definantly triangles
1516+
triangulated = true;
15561517
Debug3dProvider.setProvider(start);
15571518
return this;
15581519
}
15591520

1521+
private void performTriangulation() {
1522+
ArrayList<Polygon> toAdd = new ArrayList<Polygon>();
1523+
1524+
Stream<Polygon> polygonStream;
1525+
polygonStream = polygons.stream();
1526+
polygonStream.forEach(p -> updatePolygons(toAdd, p));
1527+
if (toAdd.size() > 0) {
1528+
setPolygons(toAdd);
1529+
}
1530+
}
1531+
15601532
private void runCPUMakeManifold() {
15611533
long start = System.currentTimeMillis();
15621534
System.err.println("Cleaning up the mesh by adding coincident points to the polygons they touch");
@@ -1706,99 +1678,28 @@ public void run() {
17061678
System.out.println("Data processed!");
17071679
}
17081680

1709-
private CSG fixDegenerates(ArrayList<Polygon> toAdd, Polygon p) {
1710-
Debug3dProvider.clearScreen();
1711-
Debug3dProvider.addObject(p);
1712-
ArrayList<Vertex> degen = p.getDegeneratePoints();
1713-
Edge longEdge = p.getLongEdge();
1714-
ArrayList<Polygon> polygonsSharing = new ArrayList<Polygon>();
1715-
ArrayList<Polygon> polygonsSharingFixed = new ArrayList<Polygon>();
1716-
1717-
for (Polygon ptoA : toAdd) {
1718-
ArrayList<Edge> edges = ptoA.edges();
1719-
for (Edge e : edges) {
1720-
if (e.equals(longEdge)) {
1721-
//// com.neuronrobotics.sdk.common.Log.error("Degenerate Mate Found!");
1722-
polygonsSharing.add(ptoA);
1723-
Debug3dProvider.addObject(ptoA);
1724-
// TODO inject the points into the found edge
1725-
// upstream reparirs to mesh generation made this code effectivly unreachable
1726-
// in case that turns out to be false, pick up here
1727-
// the points in degen need to be inserted into the matching polygons
1728-
// both list of points should be right hand, but since they are other polygons,
1729-
// that may not be the case, so sorting needs to take place
1730-
ArrayList<Vertex> newpoints = new ArrayList<Vertex>();
1731-
for (Vertex v : ptoA.getVertices()) {
1732-
newpoints.add(v);
1733-
if (e.isThisPointOneOfMine(v, Plane.EPSILON_Point)) {
1734-
for (Vertex v2 : degen)
1735-
newpoints.add(v2);
1736-
}
1737-
}
1738-
Polygon e2 = new Polygon(newpoints, ptoA.getStorage());
1739-
try {
1740-
List<Polygon> t = PolygonUtil.concaveToConvex(e2);
1741-
for (Polygon poly : t) {
1742-
if (!poly.isDegenerate()) {
1743-
polygonsSharingFixed.add(poly);
1744-
}
1745-
1746-
}
1747-
} catch (Exception ex) {
1748-
ex.printStackTrace();
1749-
// retriangulation failed, ok, whatever man, moving on...
1750-
}
1751-
}
1752-
}
1753-
}
1754-
if (polygonsSharing.size() == 0) {
1755-
//// com.neuronrobotics.sdk.common.Log.error("Error! Degenerate triangle does
1756-
//// not share edge with any triangle");
1757-
}
1758-
if (polygonsSharingFixed.size() > 0) {
1759-
toAdd.removeAll(polygonsSharing);
1760-
toAdd.addAll(polygonsSharingFixed);
1761-
}
1762-
return this;
1763-
}
1764-
1765-
private CSG updatePolygons(ArrayList<Polygon> toAdd, ArrayList<Polygon> degenerates, Polygon p) {
1766-
// p=PolygonUtil.pruneDuplicatePoints(p);
1681+
private CSG updatePolygons(ArrayList<Polygon> toAdd, Polygon p) {
17671682
if (p == null)
17681683
return this;
1769-
// if(p.isDegenerate()) {
1770-
// degenerates.add(p);
1771-
// return;
1772-
// }
1684+
17731685

17741686
if (p.getVertices().size() == 3) {
17751687
toAdd.add(p);
17761688
} else {
1777-
// //com.neuronrobotics.sdk.common.Log.error("Fixing error in STL " + name + "
1778-
// polygon# " + i + "
1779-
// number of vertices " + p.vertices.size());
1689+
17801690
try {
1781-
List<Polygon> triangles = PolygonUtil.concaveToConvex(p);
1782-
for (Polygon poly : triangles) {
1783-
toAdd.add(poly);
1691+
if(!p.areAllPointsCollinear()) {
1692+
List<Polygon> triangles = PolygonUtil.concaveToConvex(p);
1693+
for (Polygon poly : triangles) {
1694+
toAdd.add(poly);
1695+
}
1696+
}else {
1697+
System.err.println("Polygon is colinear, removing "+p);
17841698
}
17851699
} catch (Throwable ex) {
1786-
//ex.printStackTrace();
1700+
System.err.println("Failed to triangulate "+p);
1701+
ex.printStackTrace();
17871702
progressMoniter.progressUpdate(1, 1, "Pruning bad polygon CSG::updatePolygons " + p, null);
1788-
// try {PolygonUtil.concaveToConvex(p);} catch (Throwable ex2) {
1789-
// ex2.printStackTrace();
1790-
// }
1791-
// Debug3dProvider.setProvider(providerOf3d);
1792-
// //ex.printStackTrace();
1793-
// Debug3dProvider.clearScreen();
1794-
// Debug3dProvider.addObject(p);
1795-
// try {
1796-
// List<Polygon> triangles = PolygonUtil.concaveToConvex(p);
1797-
// toAdd.addAll(triangles);
1798-
// }catch(java.lang.IllegalStateException ise) {
1799-
// ise.printStackTrace();
1800-
// }
1801-
// Debug3dProvider.setProvider(null);
18021703
}
18031704

18041705
}
@@ -3439,4 +3340,9 @@ public static boolean isUseGPU() {
34393340
public static void setUseGPU(boolean useGPU) {
34403341
CSG.useGPU = useGPU;
34413342
}
3343+
3344+
public boolean isBoundsTouching(CSG incoming) {
3345+
return getBounds().isBoundsTouching(incoming.getBounds());
3346+
}
3347+
34423348
}

src/main/java/eu/mihosoft/vrl/v3d/Polygon.java

+49
Original file line numberDiff line numberDiff line change
@@ -772,4 +772,53 @@ public Polygon add(int index, Vertex v) {
772772
return this;
773773
}
774774

775+
public boolean areAllPointsCollinear() {
776+
// If we have 2 or fewer points, they're always collinear
777+
if (vertices.size() <= 2) {
778+
return true;
779+
}
780+
781+
// Get first two points to establish a direction vector
782+
Vertex p1 = vertices.get(0);
783+
Vertex p2 = vertices.get(1);
784+
785+
// Calculate the direction vector between first two points
786+
double[] directionVector = { p2.getX() - p1.getX(), p2.getY() - p1.getY(), p2.getZ() - p1.getZ() };
787+
788+
// Normalize the direction vector
789+
double length = Math.sqrt(directionVector[0] * directionVector[0] + directionVector[1] * directionVector[1]
790+
+ directionVector[2] * directionVector[2]);
791+
double ep = Plane.getEPSILON();
792+
if (length < ep) { // If points are effectively identical
793+
return false;
794+
}
795+
796+
directionVector[0] /= length;
797+
directionVector[1] /= length;
798+
directionVector[2] /= length;
799+
800+
// Check each subsequent point
801+
for (int i = 2; i < vertices.size(); i++) {
802+
Vertex p = vertices.get(i);
803+
804+
// Vector from first point to current point
805+
double[] currentVector = { p.getX() - p1.getX(), p.getY() - p1.getY(), p.getZ() - p1.getZ() };
806+
807+
// Calculate cross product
808+
double[] crossProduct = { directionVector[1] * currentVector[2] - directionVector[2] * currentVector[1],
809+
directionVector[2] * currentVector[0] - directionVector[0] * currentVector[2],
810+
directionVector[0] * currentVector[1] - directionVector[1] * currentVector[0] };
811+
812+
// Calculate magnitude of cross product
813+
double magnitude = Math.sqrt(crossProduct[0] * crossProduct[0] + crossProduct[1] * crossProduct[1]
814+
+ crossProduct[2] * crossProduct[2]);
815+
816+
// If magnitude is not close to zero, points are not collinear
817+
if (magnitude > ep) {
818+
return false;
819+
}
820+
}
821+
822+
return true;
823+
}
775824
}

src/main/java/eu/mihosoft/vrl/v3d/TextExtrude.java

+15-15
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ private TextExtrude(String text, Font font, double dir) {
159159
for (int i = 0; i < sections.size(); i++) {
160160
for (CSG h : holes) {
161161
try {
162-
if (sections.get(i).touching(h)) {
162+
if (sections.get(i).isBoundsTouching(h)) {
163163
// println "Hole found "
164164
CSG nl = sections.get(i).difference(h);
165165

@@ -200,8 +200,8 @@ public List<Vector3d> getOffset() {
200200
}
201201

202202
// Below is AI slop
203-
private static final double CURVE_SEGMENTS = 3; // Number of segments to approximate curves
204-
private static final double POINT_EPSILON = 0.0001; // Distance threshold for considering points equal
203+
private static final double CURVE_SEGMENTS = 2; // Number of segments to approximate curves
204+
//private static final double POINT_EPSILON = 0.0001; // Distance threshold for considering points equal
205205

206206
/**
207207
* Converts a JavaFX Text object into a list of cleaned vector lists
@@ -276,18 +276,18 @@ private static List<Vector3d> cleanOutline(List<Vector3d> outline) {
276276
return outline;
277277

278278
List<Vector3d> cleaned = new ArrayList<>();
279-
Vector3d prevPoint = null;
280-
281-
// Process all points
282-
for (Vector3d point : outline) {
283-
if (prevPoint == null || !isNearlyEqual(prevPoint, point)) {
284-
// Only add point if it's significantly different from the previous point
285-
cleaned.add(point);
286-
prevPoint = point;
279+
for (int i = 0; i < outline.size(); i++) {
280+
Vector3d point = outline.get(i);
281+
boolean touching=false;
282+
for(Vector3d v:cleaned) {
283+
if(v.test(point, Plane.getEPSILON()*100))
284+
touching=true;
287285
}
286+
if(!touching)
287+
cleaned.add(point);
288288
}
289289
// Remove redundant points that form zero-area triangles
290-
return removeRedundantPoints(cleaned);
290+
return cleaned;
291291
}
292292

293293
/**
@@ -308,9 +308,9 @@ private static List<Vector3d> removeRedundantPoints(List<Vector3d> points) {
308308
return result;
309309
}
310310

311-
private static boolean isNearlyEqual(Vector3d v1, Vector3d v2) {
312-
return v1.minus(v2).length() < POINT_EPSILON;
313-
}
311+
// private static boolean isNearlyEqual(Vector3d v1, Vector3d v2) {
312+
// return v1.minus(v2).length() < POINT_EPSILON;
313+
// }
314314

315315
// Bezier curve methods remain the same
316316
private static List<Vector3d> approximateCubicCurve(Vector3d start, Vector3d control1, Vector3d control2,

0 commit comments

Comments
 (0)