Repository navigation
Conversation
…pendent of the walk order Every path edge with a removed face walks its hole loop in parallel, unless its thread already found that loop good or already set its face. A walk meeting e0.sym() or a new edge twice sets the old face of its own path edge; new edges met twice are found by per-thread 16-bit walk numbers. Before, one serial walk per loop, skipped when the other side of the path edge was walked, found a loop bad only if it came back along the reverse of its start edge: a loop running another edge both ways was missed when walked from an edge whose two sides are in different loops. The selfBoolean of four test inputs now reports more faces with nested intersections; all boolean results are the same. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
getBadFacesAfterCutfinds the faces of the cut whose holes are not valid loops, for example where contours cross inside a face. It walks the hole loop on the left of every path edge whose face was removed: of the path edge, or of its sym if the face was only on its right.tbb::parallel_forover all path edges, grain 256). Before, one serial walk per loop, skipped when the other side of the path edge had been walked.e0.sym(), or a new edge (contour piece, chord) met twice. Before, onlye0.sym()counted. A loop that ran another edge both ways was missed when the walk started from an edge whose two sides are in different loops. For example, two contours whose chords cross in a face, where one chord crosses two others, gave one bad face out of two. Only new edges can bound one face's hole on both sides in valid loops. This also affects plain cuts: such faces are reported as bad instead of being filled with overlapping triangles.tbb::enumerable_thread_specific):FaceBitSetof the faces it set, made at its first one: its path edges with such a face need no walk. The sets are merged at the end, so nothing is written from two threads.The same check exists in its serial form in #7231; whichever of the two merges second takes this version.
Tests
dental|self.ab4 → 5. All boolean rows, plain and forced, are bit-identical.cutMeshcall of the regression set (5435) was checked against a plain reference, where every path edge walks its whole loop with no skips: the same faces in 3 runs each. So did a build with the walk numbers cut to 8 bits, which wrap every 255 walks.Benchmark
Alternating rounds against master 29f1678. Every MRTest was opted out of Windows power throttling, and no run was dropped as disturbed.
Plain boolean, 5 rounds:
Forced boolean (
forceCut), 3 rounds:The function alone: inputs captured from real cuts, median of 30 rounds, time over master's
getBadFacesAfterCut:getBadFacesAfterCutat 0.096-0.102 s on master and 0.103-0.110 s here; on the big cases, 0.023-0.025 s vs 0.020-0.024 s.Generated with Claude Code