Skip to content

tetwild: extend 4-4 and 5-6 edge swaps to the tracked surface - #954

Open
danielepanozzo wants to merge 1 commit into
danielepanozzo/sort-total-orderfrom
adding-remaining-surface-swaps
Open

tetwild: extend 4-4 and 5-6 edge swaps to the tracked surface#954
danielepanozzo wants to merge 1 commit into
danielepanozzo/sort-total-orderfrom
adding-remaining-surface-swaps

Conversation

@danielepanozzo

Copy link
Copy Markdown
Contributor

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

  • Core wmtk::TetMesh — 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 "face contains edge (c,d)"), so a pre-existing link edge can't spuriously match.
  • tetwild — generalized prepare_surface_flip (ring-size agnostic: 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, 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.
  • 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 and 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).

  • [surface_swap]: 10 cases / 149 assertions ✓
  • full tetwild suite: 18 cases / 813 ✓
  • core [tuple_operation]: 11 cases / 166 ✓

Integration validation

Ran tetwild with allow_surface_swap and check_surface_topology on. 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:

model 3-2 4-4 5-6 topology changed
sphere 11 132 6 0
100071_sf 62 2148 561 0
37989_sf 41 1687 511 0
Octocat 124 1390 255 0
bunny (open surface, 228 boundary loops) 305 2495 452 0

🤖 Generated with Claude Code

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>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 TetMesh virtual 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.cpp with 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 thread src/wmtk/TetMesh.h
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.
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