Skip to content

Commit

Permalink
The source of the bad points can be traced back to this change
Browse files Browse the repository at this point in the history
  • Loading branch information
madhephaestus committed Nov 11, 2024
1 parent c8dd04d commit b0de6e1
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 85 deletions.
24 changes: 13 additions & 11 deletions src/main/java/eu/mihosoft/vrl/v3d/CSG.java
Original file line number Diff line number Diff line change
Expand Up @@ -1556,17 +1556,19 @@ private CSG updatePolygons(ArrayList<Polygon> toAdd, ArrayList<Polygon> degenera
toAdd.add(poly);
}
} catch (Throwable ex) {
Debug3dProvider.setProvider(providerOf3d);
ex.printStackTrace();
Debug3dProvider.clearScreen();
Debug3dProvider.addObject(p);
try {
List<Polygon> triangles = PolygonUtil.concaveToConvex(p);
toAdd.addAll(triangles);
}catch(java.lang.IllegalStateException ise) {
ise.printStackTrace();
}
Debug3dProvider.setProvider(null);
System.err.println("Pruning bad polygon CSG::updatePolygons");

// Debug3dProvider.setProvider(providerOf3d);
// //ex.printStackTrace();
// Debug3dProvider.clearScreen();
// Debug3dProvider.addObject(p);
// try {
// List<Polygon> triangles = PolygonUtil.concaveToConvex(p);
// toAdd.addAll(triangles);
// }catch(java.lang.IllegalStateException ise) {
// ise.printStackTrace();
// }
// Debug3dProvider.setProvider(null);
}

}
Expand Down
63 changes: 38 additions & 25 deletions src/main/java/eu/mihosoft/vrl/v3d/Plane.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,39 +110,52 @@ public static Vector3d computeNormal(List<Vertex> vertices) {
// First attempt: Newell's method
Vector3d normal = new Vector3d(0, 0, 0);
int n = vertices.size();

for (int i = 0; i < n; i++) {
Vector3d current = vertices.get(i).pos;
Vector3d next = vertices.get((i + 1) % n).pos;

normal.x += (current.y - next.y) * (current.z + next.z);
normal.y += (current.z - next.z) * (current.x + next.x);
normal.z += (current.x - next.x) * (current.y + next.y);
}
double d = current.z + next.z;
double e = current.z - next.z;
double e2 = current.y - next.y;
double f = current.x + next.x;
double f2 = current.x - next.x;
double g = current.y + next.y;

if (isValidNormal(normal, EPSILON)) {
return normal.normalized();
normal.x += e2 * d;
normal.y += e * f;
normal.z += f2 * g;
}
Vector3d normalized = normal.normalized();

// Second attempt: Find three non-colinear points
normal = findNormalFromNonColinearPoints(vertices);
if (normal != null) {
return normal;
if (isValidNormal(normalized, EPSILON)) {
return normalized;
}

// Third attempt: Find principal direction
normal = findPrincipalDirection(vertices);
if (normal != null) {
return normal;
}

// Final fallback: Use statistical approach
return determineStatisticalNormal(vertices);
throw new RuntimeException("Mesh has problems, can not work around it");
// // Second attempt: Find three non-colinear points
//
// normal = findNormalFromNonColinearPoints(vertices);
// if (normal != null) {
// System.err.println("findNormalFromNonColinearPoints ");
// return normal;
// }
// // Third attempt: Find principal direction
// normal = findPrincipalDirection(vertices);
// if (normal != null) {
// System.err.println("findPrincipalDirection ");
//
// return normal;
// }
// System.err.println("determineStatisticalNormal ");
// // Final fallback: Use statistical approach
// return determineStatisticalNormal(vertices);
}

private static boolean isValidNormal(Vector3d normal, double epsilon) {
double lengthSquared = normal.lengthSquared();
return lengthSquared >= epsilon * epsilon;
if(Double.isFinite(normal.x)&&Double.isFinite(normal.y)&&Double.isFinite(normal.z)) {
double lengthSquared = Math.abs(normal.length());
return lengthSquared >= epsilon;
}
return false;
}

private static Vector3d findNormalFromNonColinearPoints(List<Vertex> vertices) {
Expand Down Expand Up @@ -408,9 +421,9 @@ else if (somePointsInBack) {
if (b.size() >= 3) {
try {
back.add(new Polygon(b, polygon.getStorage()).setColor(polygon.getColor()));
} catch (NumberFormatException ex) {
//ex.printStackTrace();
// skip adding broken polygon here
} catch (Exception ex) {
// ex.printStackTrace();
System.err.println("Pruning bad polygon Plane::splitPolygon");
}
} else {
//com.neuronrobotics.sdk.common.Log.error("Back Clip Fault!");
Expand Down
99 changes: 51 additions & 48 deletions src/main/java/eu/mihosoft/vrl/v3d/thumbnail/ThumbnailImage.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package eu.mihosoft.vrl.v3d.thumbnail;



import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
Expand Down Expand Up @@ -37,9 +35,9 @@ public static Bounds getSellectedBounds(List<CSG> incoming) {
Vector3d min = null;
Vector3d max = null;
for (CSG c : incoming) {
if(c.isHide())
if (c.isHide())
continue;
if(c.isInGroup())
if (c.isInGroup())
continue;
Vector3d min2 = c.getBounds().getMin().clone();
Vector3d max2 = c.getBounds().getMax().clone();
Expand All @@ -60,19 +58,19 @@ public static Bounds getSellectedBounds(List<CSG> incoming) {
if (max.z < max2.z)
max.z = max2.z;
}
if(max==null)
max=new Vector3d(0,0,0);
if(min==null)
min=new Vector3d(0,0,0);
if (max == null)
max = new Vector3d(0, 0, 0);
if (min == null)
min = new Vector3d(0, 0, 0);
return new Bounds(min, max);
}

public static WritableImage get(List<CSG> c) {
ArrayList<CSG> csgList=new ArrayList<CSG>() ;
for(CSG cs:c) {
if(cs.getManipulator()!=null) {
ArrayList<CSG> csgList = new ArrayList<CSG>();
for (CSG cs : c) {
if (cs.getManipulator() != null) {
csgList.add(cs.transformed(TransformConverter.fromAffine(cs.getManipulator())).syncProperties(cs));
}else
} else
csgList.add(cs);
}
// Create a group to hold all the meshes
Expand All @@ -81,13 +79,13 @@ public static WritableImage get(List<CSG> c) {
// Add all meshes to the group
Bounds b = getSellectedBounds(csgList);

double yOffset = (b.getMax().y-b.getMin().y)/2;
double xOffset =(b.getMax().x -b.getMin().x)/2;
double zCenter = (b.getMax().z -b.getMin().z)/2;
double yOffset = (b.getMax().y - b.getMin().y) / 2;
double xOffset = (b.getMax().x - b.getMin().x) / 2;
double zCenter = (b.getMax().z - b.getMin().z) / 2;
for (CSG csg : csgList) {
if(csg.isHide())
if (csg.isHide())
continue;
if(csg.isInGroup())
if (csg.isInGroup())
continue;
MeshView meshView = csg.movez(-zCenter).getMesh();
if (csg.isHole()) {
Expand All @@ -111,7 +109,7 @@ public static WritableImage get(List<CSG> c) {

// Calculate camera position to fit all objects in view
double maxDimension = Math.max(totalx, Math.max(totaly, totalz));
double cameraDistance = (maxDimension / Math.tan(Math.toRadians(camera.getFieldOfView() / 2)))*0.8 ;
double cameraDistance = (maxDimension / Math.tan(Math.toRadians(camera.getFieldOfView() / 2))) * 0.8;

// TransformNR camoffset = new TransformNR(xOffset, yOffset, 0);
// TransformNR camDist = new TransformNR(0, 0, -cameraDistance);
Expand All @@ -120,18 +118,17 @@ public static WritableImage get(List<CSG> c) {
// Affine af = TransformFactory.nrToAffine(camoffset.times(rot.times(camDist)));
Affine camDist = new Affine();
camDist.setTz(-cameraDistance);
Rotate rot1 =new Rotate(45, Rotate.Z_AXIS);
Rotate rot2 =new Rotate(-150, Rotate.Y_AXIS);
Rotate rot1 = new Rotate(45, Rotate.Z_AXIS);
Rotate rot2 = new Rotate(-150, Rotate.Y_AXIS);
Affine camoffset = new Affine();
camoffset.setTx(xOffset);
camoffset.setTy(yOffset);
camera.getTransforms().add(camoffset );
camera.getTransforms().add(rot2 );
camera.getTransforms().add(rot1 );
camera.getTransforms().add(camDist );
camera.getTransforms().add(camoffset);
camera.getTransforms().add(rot2);
camera.getTransforms().add(rot1);
camera.getTransforms().add(camDist);
//



// Position the camera
// camera.setTranslateX();
// camera.setTranslateY();
Expand All @@ -154,9 +151,8 @@ public static WritableImage get(List<CSG> c) {
params.setDepthBuffer(true);
params.setTransform(Transform.scale(1, 1));
// Set the near and far clip
camera.setNearClip(0.1); // Set the near clip plane
camera.setFarClip(9000.0); // Set the far clip plane

camera.setNearClip(0.1); // Set the near clip plane
camera.setFarClip(9000.0); // Set the far clip plane

// Create the WritableImage first
WritableImage snapshot = new WritableImage(i, i);
Expand All @@ -165,30 +161,37 @@ public static WritableImage get(List<CSG> c) {

return snapshot;
}


public static Thread writeImage(CSG incoming, File toPNG) {
ArrayList<CSG> bits = new ArrayList<CSG>();
bits.add(incoming);
return writeImage(bits, toPNG);
}

public static Thread writeImage(ArrayList<CSG> incoming, File toPNG) {
Thread t= new Thread(new Runnable() {
WritableImage img=null;
Thread t = new Thread(new Runnable() {
WritableImage img = null;

@Override
public void run() {
File image = toPNG;
javafx.application.Platform.runLater(() -> img=ThumbnailImage.get(incoming));
while (img == null)
try {
Thread.sleep(16);
// com.neuronrobotics.sdk.common.Log.error("Waiting for image to write");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(img, null);

File image = toPNG;
javafx.application.Platform.runLater(() -> img = ThumbnailImage.get(incoming));
while (img == null)
try {
ImageIO.write(bufferedImage, "png", image);
} catch (IOException e) {
throw new RuntimeException(e);
Thread.sleep(16);
// com.neuronrobotics.sdk.common.Log.error("Waiting for image to write");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
break;
}
BufferedImage bufferedImage = SwingFXUtils.fromFXImage(img, null);

try {
ImageIO.write(bufferedImage, "png", image);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
});
t.setUncaughtExceptionHandler((thread, throwable) -> {
Expand Down
32 changes: 32 additions & 0 deletions src/test/java/eu/mihosoft/vrl/v3d/StlExportTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package eu.mihosoft.vrl.v3d;

import static org.junit.Assert.*;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

import org.junit.Test;

public class StlExportTest {

@Test
public void makeBadSTL() throws IOException {
CSG badExport2 = CSG.text(" A QUICK BROWN FOX JUMPS OVER THE LAZY DOG", 10).movey(30);
CSG badExport = CSG.text("THis is some text a quick brown fox jumps over the lazy dog.", 10);
// badExport2=new Cube(20).toCSG().movey(30);
// badExport=new Cube(20).toCSG();

badExport=badExport.union(badExport2);
String filename ="TextStl.stl";
FileUtil.write(Paths.get(filename),
badExport.toStlString());
System.out.println("Load saved stl");
File file = new File(filename);
CSG loaded = STL.file(file.toPath());
badExport=loaded.union(badExport2);
FileUtil.write(Paths.get(filename),
badExport.toStlString());
}

}
13 changes: 12 additions & 1 deletion src/test/java/eu/mihosoft/vrl/v3d/StlLoadTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,23 @@

import org.junit.Test;

import eu.mihosoft.vrl.v3d.thumbnail.ThumbnailImage;
import javafx.scene.shape.CullFace;

public class StlLoadTest {

@Test
public void test() throws IOException {
String filename = "brokenSTL.STL";
CSG loaded = STL.file(new File(filename).toPath());
File file = new File(filename);
CSG loaded = STL.file(file.toPath());
try {
ThumbnailImage.setCullFaceValue(CullFace.NONE);
ThumbnailImage.writeImage(loaded,new File(file.getAbsolutePath()+".png")).join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

0 comments on commit b0de6e1

Please sign in to comment.