fix: marching triangles isovalue degeneracies#251
Open
liamnwhite1 wants to merge 2 commits into
Open
Conversation
Classify scalar samples as below, equal, or above the isovalue before collecting contour hits. Deduplicate hits so an exact isovalue vertex shared by two incident edges does not produce a three-hit face and get skipped. Also skip ambiguous degenerate cases explicitly when a face has anything other than two unique contour hits.
Add regression coverage for a contour passing through an exact isovalue vertex, ensuring the face still emits a segment. Also cover fully iso-valued faces, which should be skipped because the one-dimensional contour is ambiguous.
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.
Summary
This PR fixes
marchingTriangles()so contours that pass exactly through mesh vertices are emitted instead of being dropped as degenerate faces.The implementation now classifies scalar samples as below, equal to, above, or invalid relative to the requested isovalue, deduplicates contour hits per face, and keeps strict edge crossings in canonical edge coordinates so adjacent faces stitch into the same contour curve.
Problem Addressed
Originally,
marchingTriangles()detected contour intersections by checking each face edge independently. When the isovalue landed exactly on a vertex, both incident edges in the same triangle reported that same vertex as a crossing.That meant a valid contour segment could produce three hits on one face:
The existing code only emitted faces with exactly two hits, so these valid contour segments were skipped.
There was also a subtle stitching risk while fixing this: shared-edge crossings must be represented in canonical
Edgecoordinates. If neighboring faces compute the same crossing from opposite halfedge orientations, tiny floating-point differences can make exactSurfacePointequality fail, fragmenting one contour into separate components.What Changed
Added explicit isovalue classification for vertex samples:
BelowEqualAboveInvalidAdded per-face hit deduplication so repeated exact vertex hits collapse to one
SurfacePoint(Vertex).Handles exact contour cases directly:
Preserves contour stitching by storing strict crossings as
SurfacePoint(e, t)in canonicalEdgeorientation, rather than face-local halfedge orientation.Keeps ambiguous degenerate cases explicit:
Why This Fix Works
A valid contour segment through a triangle should be emitted whenever there are exactly two unique contour hits on that face.
By classifying exact isovalue vertices before interpolation and deduplicating hits, a face with an exact isovalue vertex plus an opposite-edge crossing now produces the expected two unique hits instead of three raw edge hits.
For ordinary crossings, using canonical edge coordinates ensures both faces adjacent to an edge produce exactly the same
SurfacePoint, sogetCurveComponents()can stitch the segments into a single curve.Tests
Added focused regression coverage for: