Skip to content

fix(tessellation): a triangle seen edge-on from its surface turns like its face - #52

Open
Basnederveen wants to merge 2 commits into
OpenGeometry-io:mainfrom
Bas-Automation-Services:fix/edge-on-trim-triangles
Open

Basnederveen wants to merge 2 commits into
OpenGeometry-io:mainfrom
Bas-Automation-Services:fix/edge-on-trim-triangles

Conversation

@Basnederveen

Copy link
Copy Markdown

What

"triangle orientation could not be resolved" on a sliver of a curved face. A hole through the corner of a bent sheet (a 180-degree bend, cylinder faces) leaves a small piece of the bend between the hole, the bend's straight start and the sheet's end. In the earcut + refinement path (general_curved_trimmed_face), the samples along the end lie on one line in UV (v = 0) except the last, which rounding puts 2e-14 off it, so earcut clips the three as a convex ear. In 3D they lie on the end's circle, in a plane normal to the cylinder axis, so the triangle's normal is perpendicular to the surface normal at its centre and the orientation dot product in Tessellation::triangle is exactly 0.

Earcut gives every triangle of a ring the same winding, and refinement keeps it, so all triangles of one face need the same flip. push_triangles_with_one_winding (split out of general_curved_trimmed_face) takes the flip from the face's first triangle whose normal is clearly on one side (|n . d| > 1e-6 |d|) and applies it to any triangle seen edge-on. Every other triangle is oriented exactly as before.

This is the general form of the second fix in #37 (snapping a run off its corner vertex by up to 64 ε): here the offset is 2e-14 on a ring of magnitude 0.43, about four times that threshold, and it comes from where the vertex was projected, not from a pcurve. The two don't overlap textually.

Tests

  • New tessellation/tests/edge_on_triangles.rs: an_ear_of_end_samples_rounded_off_their_line_turns_like_its_face feeds the trim ring of such a sliver (UV coordinates as they came from the failing body; the end's three samples on the end circle exactly) on a cylinder of radius 3.35 to general_curved_trimmed_face (now pub(super) for the test), and checks every edge two triangles share runs opposite ways in them. Before: "triangle orientation could not be resolved".
  • cargo fmt --check, cargo clippy --all-targets -D warnings and the source rules pass. cargo test --all-targets: the same tests pass and fail as on main on this machine (Windows; the stored-fixture, golden-scene and IFC-digest tests differ here on main too).

Files

  • main/opengeometry/src/tessellation/trimmed_face.rs
  • main/opengeometry/src/tessellation/tests/edge_on_triangles.rs (new), tests/mod.rs

🤖 Generated with Claude Code

Basnederveen and others added 2 commits November 10, 2026 09:38
…e its face

Earcut can clip an ear from samples along one straight trim edge when
rounding puts one of them off the line in UV. On a cylinder those
samples lie on a circle, so the triangle's normal is perpendicular to
the surface normal and the orientation test found exactly zero. Earcut
and refinement give one face a single winding, so such a triangle now
takes the flip of the face's other triangles.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
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.

1 participant