-
Notifications
You must be signed in to change notification settings - Fork 4
Fix tetrahedron orientation in FlexiCubes output #63
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 occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
mkofler96
wants to merge
6
commits into
main
Choose a base branch
from
claude/sweet-goodall-k198uk
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
+138
−0
Open
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
426205b
Fix inverted tetrahedra in FlexiCubes volume mesh output
claude 9160c55
Remove degenerate zero-volume tets from FlexiCubes output
claude efe750d
Drop caplog assertion from degenerate-tet test
claude 53a04b0
style: format code with Black
deepsource-autofix[bot] ae28745
Address review: explicit grid bounds in test, no_grad in _orient_tets
claude 56a5ae0
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
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
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,88 @@ | ||
| """Regression tests for tetrahedron orientation in FlexiCubes output. | ||
|
|
||
| FlexiCubes' ``_tetrahedralize`` builds tets from two sub-procedures (surface | ||
| pyramids and interior edges) whose vertex orderings do not share a consistent | ||
| winding, so a large fraction of the elements used to come out inverted | ||
| (negative signed volume). That breaks FEA solvers, which require a positive | ||
| signed volume / Jacobian on every element. The interior sub-procedure can | ||
| additionally emit degenerate (exactly coplanar, zero-volume) tets, which are | ||
| removed during extraction. These tests pin both fixes: every tet returned by | ||
| FlexiCubes must have a strictly positive signed volume. | ||
| """ | ||
|
|
||
| import torch | ||
|
|
||
| from DeepSDFStruct.flexicubes.flexicubes import FlexiCubes | ||
| from DeepSDFStruct.optimization import tet_signed_vol | ||
|
|
||
|
|
||
| def _sphere_volume_mesh(res=16, radius=0.7, center=(0.0, 0.0, 0.0)): | ||
| fc = FlexiCubes(device="cpu") | ||
| x_nx3, cube_fx8 = fc.construct_voxel_grid( | ||
| res, bounds=[[-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]] | ||
| ) | ||
| c = torch.tensor(center, dtype=x_nx3.dtype) | ||
| s_n = torch.linalg.norm(x_nx3 - c, dim=1) - radius | ||
| verts, tets, _ = fc(x_nx3, s_n, cube_fx8, res, output_tetmesh=True) | ||
| return verts, tets | ||
|
|
||
|
|
||
| def test_orient_tets_flips_inverted_element(): | ||
| """A single inverted tet is flipped to positive signed volume.""" | ||
| verts = torch.tensor( | ||
| [[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]] | ||
| ) | ||
| # [0, 1, 2, 3] is positively oriented; [0, 1, 3, 2] is its inversion. | ||
| tets = torch.tensor([[0, 1, 2, 3], [0, 1, 3, 2]]) | ||
|
|
||
| assert ( | ||
| tet_signed_vol(verts, tets) < 0 | ||
| ).any(), "fixture should contain an inversion" | ||
|
|
||
| oriented = FlexiCubes._orient_tets(verts, tets) | ||
| vols = tet_signed_vol(verts, oriented) | ||
| assert (vols > 0).all(), f"expected all positive volumes, got {vols.tolist()}" | ||
| # Orientation is fixed by reordering indices only: |volume| is preserved. | ||
| assert torch.allclose(vols.abs(), tet_signed_vol(verts, tets).abs()) | ||
|
|
||
|
|
||
| def test_orient_tets_handles_empty(): | ||
| verts = torch.zeros((0, 3)) | ||
| tets = torch.zeros((0, 4), dtype=torch.long) | ||
| assert FlexiCubes._orient_tets(verts, tets).shape == (0, 4) | ||
|
|
||
|
|
||
| def test_orient_tets_removes_degenerate_elements(): | ||
| """Zero-volume (coplanar) tets are dropped.""" | ||
| verts = torch.tensor( | ||
| [ | ||
| [0.0, 0.0, 0.0], | ||
| [1.0, 0.0, 0.0], | ||
| [0.0, 1.0, 0.0], | ||
| [0.0, 0.0, 1.0], | ||
| [1.0, 1.0, 0.0], # coplanar with the first three (z = 0 plane) | ||
| ] | ||
| ) | ||
| tets = torch.tensor([[0, 1, 2, 3], [0, 1, 2, 4]]) | ||
|
|
||
| oriented = FlexiCubes._orient_tets(verts, tets) | ||
|
|
||
| assert oriented.shape == (1, 4) | ||
| assert (tet_signed_vol(verts, oriented) > 0).all() | ||
|
|
||
|
|
||
| def test_flexicubes_volume_mesh_has_only_positive_tets(): | ||
| """End-to-end: extracted volume mesh has strictly positive signed volumes.""" | ||
| for center in [(0.0, 0.0, 0.0), (0.13, 0.07, 0.21)]: | ||
| verts, tets = _sphere_volume_mesh(center=center) | ||
| assert tets.shape[0] > 0 | ||
| vols = tet_signed_vol(verts, tets) | ||
| n_bad = int((vols <= 0).sum()) | ||
| assert n_bad == 0, f"{n_bad} non-positive tets for center {center}" | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| test_orient_tets_flips_inverted_element() | ||
| test_orient_tets_handles_empty() | ||
| test_flexicubes_volume_mesh_has_only_positive_tets() | ||
| print("ok") |
Oops, something went wrong.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keeping this message as-is — the wording was explicitly requested by the maintainer. The tolerance only exists to catch elements that are coplanar up to float32 vertex precision: the measured relative-volume distribution is cleanly bimodal (degenerates at ≤1e-7 from rounding noise, real elements at ≥1e-5), so everything removed here is zero-volume at working precision, not merely "near-zero".
Generated by Claude Code