8000 boolean debugging by pca006132 · Pull Request #1104 · elalish/manifold · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

boolean debugging #1104

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll 8000 occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Dec 11, 2024
Merged

boolean debugging #1104

merged 16 commits into from
Dec 11, 2024

Conversation

pca006132
Copy link
Collaborator
  1. Dump problematic boolean operands when we perform boolean operations.
  2. Check for self-intersections after boolean operations.

I don't think this can be merged now, because the self-intersection check causes quite a few failures. Some are probably fine (epsilon-valid because they are just touching), but some are probably not. Use the verbose option to print the information, because it can be quite long.

@elalish maybe you should have a look and play with this.

@pca006132 pca006132 requested a review from elalish December 8, 2024 12:23
src/csg_tree.cpp Outdated
#ifdef MANIFOLD_DEBUG
if (impl.IsSelfIntersecting()) {
dump_lock.lock();
std::cout << "self-intersection detected" << std::endl;
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably clean up these error messages later.

src/impl.cpp Outdated
< 8000 td class="blob-code blob-code-addition">
#endif
#ifdef MANIFOLD_EXPORT
MeshGL64 ImportMeshGL64(std::istream& stream) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function imports the .obj file. Note that this is a quick-and-dirty implementation that doesn't really support the actual specification, but good enough that it can parse our outputs. I do not plan to make it spec compliant, nor make the format stable, so this will probably keep internal to us.

@@ -1016,4 +1020,26 @@ TEST(BooleanComplex, SimpleOffset) {
EXPECT_EQ(c.Status(), Manifold::Error::NoError);
}

TEST(BooleanComplex, UnionDifferenceSelfIntersect) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a simple failure case, and a test case to exercise the parser as well.

Copy link
Owner
@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the big question: does this successfully spit out the Boolean that leads to the first self-intersection in our problem Minkowski cases? If so, this will be super helpful. If not, we probably need to rethink it.

@pca006132
Copy link
Collaborator Author

So the big question: does this successfully spit out the Boolean that leads to the first self-intersection in our problem Minkowski cases? If so, this will be super helpful. If not, we probably need to rethink it.

This seems to work for the BooleanComplex.SimpleOffset case, but you need to disable the status check for it to output a pair of smaller operands.

Copy link
codecov bot commented Dec 9, 2024

Codecov Report

Attention: Patch coverage is 29.72973% with 26 lines in your changes missing coverage. Please review.

Project coverage is 91.46%. Comparing base (ec0bbca) to head (5baa367).
Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/properties.cpp 0.00% 26 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1104      +/-   ##
==========================================
- Coverage   91.87%   91.46%   -0.41%     
==========================================
  Files          30       30              
  Lines        5885     5908      +23     
==========================================
- Hits         5407     5404       -3     
- Misses        478      504      +26     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@pca006132
Copy link
Collaborator Author

Here are the failures we have when intermediate checks are enabled (via a new -c flag)

[ RUN      ] BooleanComplex.SelfIntersect
self intersections detected
LHS self-intersecting: 1
RHS self-intersecting: 1
unknown file: Failure
C++ exception with description "self intersection detected" thrown in the test body.

[  FAILED  ] BooleanComplex.SelfIntersect (39 ms)
[ RUN      ] BooleanComplex.GenericTwinBooleanTest7081
self intersections detected
LHS self-intersecting: 1
RHS self-intersecting: 0
unknown file: Failure
C++ exception with description "self intersection detected" thrown in the test body.

[  FAILED  ] BooleanComplex.GenericTwinBooleanTest7081 (6798 ms)
[ RUN      ] BooleanComplex.GenericTwinBooleanTest7863
self intersections detected
LHS self-intersecting: 0
RHS self-intersecting: 1
unknown file: Failure
C++ exception with description "self intersection detected" thrown in the test body.

[  FAILED  ] BooleanComplex.GenericTwinBooleanTest7863 (8 ms)
[ RUN      ] BooleanComplex.Havocglass8Bool
[       OK ] BooleanComplex.Havocglass8Bool (2 ms)
[ RUN      ] BooleanComplex.CraycloudBool
[       OK ] BooleanComplex.CraycloudBool (1 ms)
[ RUN      ] BooleanComplex.HullMask
self intersections detected
LHS self-intersecting: 0
RHS self-intersecting: 0
unknown file: Failure
C++ exception with description "self intersection detected" thrown in the test body.

[  FAILED  ] BooleanComplex.HullMask (29 ms)
[ RUN      ] BooleanComplex.SimpleOffset
self intersections detected
LHS self-intersecting: 0
RHS self-intersecting: 0
unknown file: Failure
C++ exception with description "self intersection detected" thrown in the test body.

[  FAILED  ] BooleanComplex.SimpleOffset (1330 ms)
[ RUN      ] BooleanComplex.OffsetTriangulationFailure
-----------------------------------
Triangulation failed! Precision = 2.01711e-08
Error in file: /home/pca006132/code/manifold/src/polygon.cpp (118): 'std::all_of(triangles.begin(), triangles.end(), [&vertPos, epsilon](const ivec3 &tri) { return CCW(vertPos[tri[0]], vertPos[tri[1]], vertPos[tri[2]], epsilon) >= 0; })' is false: triangulation is not entirely CCW!
Polygon 0 2.01711e-08 2
11
5001.56 -19653.4
5002.53 -19653.5
5001.56 -19653.4
5001.56 -19653.4
5001.56 -19653.4
5001.56 -19653.4
5001.56 -19653.4
5001.56 -19653.4
5002.53 -19653.5
5002.53 -19653.5
5001.56 -19653.4
12
5003.5 -19653.6
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5039.82 -19373.5
5001.56 -19653.4
5002.53 -19653.5
# ... 
show(array([
  [5001.56, -19653.4],
  [5002.53, -19653.5],
  [5001.56, -19653.4],
  [5001.56, -19653.4],
  [5001.56, -19653.4],
  [5001.56, -19653.4],
  [5001.56, -19653.4],
  [5001.56, -19653.4],
  [5002.53, -19653.5],
  [5002.53, -19653.5],
  [5001.56, -19653.4],
]))
show(array([
  [5003.5, -19653.6],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5039.82, -19373.5],
  [5001.56, -19653.4],
  [5002.53, -19653.5],
]))
produced this triangulation:
4661, 2943, 2993
3003, 4666, 4658
4658, 4659, 2172
2993, 2995, 2999
2999, 3001, 3003
2999, 3003, 4658
2172, 4661, 2993
2172, 2993, 2999
2172, 2999, 4658
2989, 4657, 5071
2987, 2989, 5071
2985, 2987, 5071
2983, 2985, 5071
2991, 2983, 5071
5070, 2173, 2453
2991, 5071, 5070
2453, 5767, 3084
5070, 2453, 3084
2991, 5070, 3084
LHS self-intersecting: 0
RHS self-intersecting: 0
unknown file: Failure
C++ exception with description "Error in file: /home/pca006132/code/manifold/src/polygon.cpp (118): 'std::all_of(triangles.begin(), triangles.end(), [&vertPos, epsilon](const ivec3 &tri) { return CCW(vertPos[tri[0]], vertPos[tri[1]], vertPos[tri[2]], epsilon) >= 0; })' is false: triangulation is not entirely CCW!" thrown in the test body.

[  FAILED  ] BooleanComplex.OffsetTriangulationFailure (15 ms)

It now checks if the two operands are self-intersecting up to epsilon.

@pca006132
Copy link
Collaborator Author

The main issue is that the operands causing these issues are typically quite large, may require some randomized algorithm to reduce their sizes.

@pca006132
Copy link
Collaborator Author

Managed to obtain a smaller self-intersecting result case with openscad. The two operands are fine, but the result is not.

Btw, I found that the problem with verbose output is that we also print running time and algorithm statistics with verbose enabled, and things are unreadable when run in multiple threads... Wonder if we should split that into some debug flag, as users should never use that verbose output (except during debugging).

@pca006132
Copy link
Collaborator Author

It seems that the offending pairs look like this by peforming decomposition:

diff --git a/test/boolean_complex_test.cpp b/test/boolean_complex_test.cpp
index 2cef5f6..a16bd67 100644
--- a/test/boolean_complex_test.cpp
+++ b/test/boolean_complex_test.cpp
@@ -1045,7 +1045,7 @@ TEST(BooleanComplex, DISABLED_OffsetTriangulationFailure) {
   ManifoldParams().intermediateChecks = intermediateChecks;
 }
 
-TEST(BooleanComplex, DISABLED_OffsetSelfIntersect) {
+TEST(BooleanComplex, OffsetSelfIntersect) {
   const bool intermediateChecks = ManifoldParams().intermediateChecks;
   ManifoldParams().intermediateChecks = true;
   std::string file = __FILE__;
@@ -1063,10 +1063,17 @@ TEST(BooleanComplex, DISABLED_OffsetSelfIntersect) {
     std::cout << err.what() << std::endl;
     FAIL();
   }
-  Manifold x(a);
-  Manifold y(b);
-  Manifold result = x + y;
-  EXPECT_EQ(result.Status(), Manifold::Error::NoError);
+
+  auto xs = Manifold(a).Decompose();
+  auto ys = Manifold(b).Decompose();
+
+  for (const auto &x : xs) {
+    for (const auto &y : ys) {
+      Manifold result = x + y;
+      EXPECT_EQ(result.Status(), Manifold::Error::NoError);
+    }
+  }
+
   ManifoldParams().intermediateChecks = intermediateChecks;
 }
 

image

But for some reason after extracting the mesh, I cannot reproduce the issue. Perhaps this is related to rounding error or face normals?

@pca006132
Copy link
Collaborator Author

It can now be reproduced after allowing setting epsilon.

Copy link
Owner
@elalish elalish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thanks!

for (int i : {0, 1, 2}) tmp_y[i] = tri_y[i] + epsilon_ * faceNormal_[x];
if (DistanceTriangleTriangleSquared(tri_x, tmp_y) > 0.0) return true;
for (int i : {0, 1, 2}) tmp_y[i] = tri_y[i] - epsilon_ * faceNormal_[x];
if (DistanceTriangleTriangleSquared(tri_x, tmp_y) > 0.0) return true;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

@pca006132 pca006132 merged commit 926d2e7 into master Dec 11, 2024
25 checks passed
@pca006132 pca006132 deleted the csg-tree-debug branch December 11, 2024 04:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants
0