tetwild: extend 4-4 and 5-6 edge swaps to the tracked surface - #954
Open
danielepanozzo wants to merge 1 commit into
Open
tetwild: extend 4-4 and 5-6 edge swaps to the tracked surface#954danielepanozzo wants to merge 1 commit into
danielepanozzo wants to merge 1 commit into
Conversation
danielepanozzo
force-pushed
the
adding-remaining-surface-swaps
branch
from
July 23, 2026 02:13
77d0dd3 to
2df6071
Compare
Previously only the 3->2 edge swap could flip a surface edge (a surface diagonal flip); 4-4 and 5-6 rejected surface edges outright, so slivers touching the surface that need those flips could not be improved. The surface change is always the same 2D Pachner 2-2 move of the two incident surface faces (a,b,c),(a,b,d) -> (a,c,d),(b,c,d). What differs per swap is the volumetric retetrahedralization that realizes edge (c,d): - Core TetMesh: add two default-true virtual predicates swap_edge_44_accept_case(new_edge) / swap_edge_56_accept_case(new_face) that filter candidate cases before the min-energy selection. Default true leaves interior edges and other meshes (e.g. SimWild) unchanged; tetwild overrides them to force the case that creates the surface diagonal (c,d). The 5-6 predicate keys on the fan apex, not "contains edge (c,d)", so a pre-existing link edge cannot spuriously match. - tetwild: generalize prepare_surface_flip to any ring size (it finds the two surface apexes c,d and runs the manifold guards: open-boundary reject, exactly two incident surface faces, (c,d) link condition via a direct incident-surface-face count, new faces not already surface). 4-4/5-6 _before route surface edges through it; _after envelope-checks the two new surface faces, retags them, and bumps per-type counters. - Routing hardening: new edge_incident_surface_face_count (face-based, so it ignores possibly-stale m_is_on_surface vertex flags) decides surface-vs- interior in all three swaps, so a genuine surface edge is never silently torn by the interior path. It runs only after the incident-tet-count gate. - The 2->3 face swap stays surface-forbidden (removing a surface triangle tears the surface; not topology-preserving) -- covered by a test. - swap_all_edges_44/56 now also wrapped in the check_surface_topology signature net; per-type counters cnt_surface_swap_32/_44/_56 added/logged. Tests: test_surface_swap.cpp gains 4-4/5-6 accept, adjacent-apex reject, apex-vs-link-edge guard, non-manifold reject, disabled-param, stale-flag routing, interior-unchanged, and face-swap-excluded cases. Interior 4-4/5-6 behavior is unchanged (core [tuple_operation] suite still green). Validated on sphere/100071_sf/37989_sf/Octocat/bunny with surface swaps and the surface-topology check on: all three swap types fire on the surface and the surface topology signature is unchanged across every swap pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
danielepanozzo
force-pushed
the
adding-remaining-surface-swaps
branch
from
July 23, 2026 02:34
2df6071 to
3a01dfa
Compare
There was a problem hiding this comment.
Pull request overview
This PR extends TetWild’s tracked-surface support from only 3→2 swaps to also allow 4-4 and 5-6 edge swaps to perform the same surface 2-2 diagonal flip, while keeping core wmtk::TetMesh behavior unchanged by default via new opt-in predicates.
Changes:
- Added two new
TetMeshvirtual predicates (swap_edge_44_accept_case,swap_edge_56_accept_case) to allow derived meshes (TetWild) to veto/force candidate swap orientations before energy selection. - Implemented surface-aware routing/guarding for 4-4 and 5-6 in TetWild (ring-size agnostic surface-flip prep, envelope checks, retagging, per-type counters, topology-signature checks).
- Expanded
test_surface_swap.cppwith new correctness/rejection/routing tests for surface 4-4 and 5-6 swaps, and updated parameter/spec documentation.
Reviewed changes
Copilot reviewed 8 out of 8 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| src/wmtk/TetMeshSwapMeshConnectivity.cpp | Calls new accept-case predicates during 4-4 / 5-6 candidate-case selection. |
| src/wmtk/TetMesh.h | Introduces new virtual predicates for filtering 4-4 and 5-6 candidate cases. |
| components/tetwild/wmtk/components/tetwild/TetWildMesh.h | Declares TetWild overrides for accept-case predicates, generalizes surface-flip prep API, adds routing helper + counters. |
| components/tetwild/wmtk/components/tetwild/TetWildMesh.cpp | Adds face-based surface-edge detection helper (edge_incident_surface_face_count). |
| components/tetwild/wmtk/components/tetwild/EdgeSwapping.cpp | Implements generalized prepare_surface_flip, routes 3-2/4-4/5-6 surface edges through it, enforces envelope + retagging for 4-4/5-6, adds topology-signature checks. |
| components/tetwild/wmtk/components/tetwild/Parameters.h | Updates allow_surface_swap documentation to cover 3-2/4-4/5-6. |
| components/tetwild/wmtk/components/tetwild/tetwild_spec.json | Updates parameter docstring to reflect extended surface swap coverage. |
| components/tetwild/wmtk/components/tetwild/tests/test_surface_swap.cpp | Adds comprehensive tests for surface 4-4 and 5-6 swaps and routing hardening. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+811
to
+812
| * @param new_edge The unordered pair of vertices of the candidate's new edge. | ||
| * @return true if this candidate case is allowed. |
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
Previously only the 3→2 edge swap could flip a surface edge (a surface diagonal flip); the 4-4 and 5-6 swaps rejected surface edges outright, so slivers touching the surface that need those flips could not be improved. This PR extends all edge swaps to operate on the surface.
The surface change is always the same 2D Pachner 2-2 move of the two incident surface faces
(a,b,c),(a,b,d) → (a,c,d),(b,c,d). What differs per swap is the volumetric retetrahedralization that realizes the new edge(c,d).Design
wmtk::TetMesh— two default-truevirtual predicatesswap_edge_44_accept_case(new_edge)/swap_edge_56_accept_case(new_face)that filter candidate cases before the min-energy selection. Default-true leaves interior edges and other meshes (e.g. SimWild) unchanged; tetwild overrides them to force the case that creates the surface diagonal(c,d). The 5-6 predicate keys on the fan apex (not "face contains edge(c,d)"), so a pre-existing link edge can't spuriously match.prepare_surface_flip(ring-size agnostic: finds the two surface apexesc,dand runs the manifold guards — open-boundary reject, exactly two incident surface faces,(c,d)link condition via a direct incident-surface-face count, new faces not already surface). 4-4/5-6_beforeroute surface edges through it;_afterenvelope-checks the two new surface faces, retags them, and bumps per-type counters.edge_incident_surface_face_count(face-based, ignores possibly-stalem_is_on_surfacevertex flags) decides surface-vs-interior in all three swaps, so a genuine surface edge is never silently torn by the interior path.swap_all_edges_44/56now also wrapped in thecheck_surface_topologysignature net; per-type counterscnt_surface_swap_32/_44/_56added and logged.Tests
test_surface_swap.cppgains 4-4/5-6 accept, adjacent-apex reject, apex-vs-link-edge guard, non-manifold reject, disabled-param, stale-flag routing, interior-unchanged, and face-swap-excluded cases. Interior 4-4/5-6 behavior is unchanged (core[tuple_operation]suite still green).[surface_swap]: 10 cases / 149 assertions ✓[tuple_operation]: 11 cases / 166 ✓Integration validation
Ran tetwild with
allow_surface_swapandcheck_surface_topologyon. All three swap types fire on the surface, and the surface-topology signature (components, V/E/F, Euler, boundary loops) is unchanged across every swap pass:🤖 Generated with Claude Code