Clip fault assemblies against the mesh's own boundary; label the outcrop trace - #582
Clip fault assemblies against the mesh's own boundary; label the outcrop trace#582lmoresi wants to merge 5 commits into
Conversation
… geometry The assembly clip (place_thin_volume, 2-D and 3-D) now intersects with the domain the mesh actually has: unshared support-1 facets are gathered collectively, stitched by exact coordinate identity, and rebuilt in OCC — collinear runs (coplanar triangles, one dimension up) compressed to their corners, so a box constructs the same four-sided / six-faced tool the analytic addRectangle/addBox clip did, and the boolean does not imprint the wall's mesh spacing onto the clipped faces. The post-mesh snap becomes a pure normal-component move onto the boundary's own facets, which on an axis-aligned wall reproduces the wall-plane snap exactly. The cut lands on the mesh's own facets (measured 3.5e-17 from the chords, against the 8.6e-3 sagitta a cut on the smooth circle would leave), so no corefinement library is needed and clip-then-mesh order is preserved. Box regression oracle unchanged: test_0854, test_0855 serial and at np=2/np=4. New tool unit tests in test_0859 assert exactness both ways — OCC mass equals the mesh's summed cell measure to round-off, and differs from the smooth-geometry measure by far more (the negative control). Outcrop-band identification still runs against the axis-aligned box frame; generalising the band to the boundary trace is the next stage. Underworld development team with AI support from Claude Code
The band split no longer tests coordinate equality against wall-plane values: _split_skin_trace takes the domain's own boundary complex and keeps a skin facet when every vertex and its centroid lie on it — exact after the post-clip snap, and defined on any boundary. The single-wall frame the carve/sew still runs in is derived afterwards by _trace_wall_code, which keeps the established refusals (more than one wall; and, until the general carve/sew exists, a non-axis-aligned outcrop). The band facets — the intersection itself, never a partition of the wall into named pieces — now carry 'label_trace' alongside the skin and wall labels, full closures included, in 2-D and 3-D, and the facet count is reported as info['n_trace_facets']. The outcrop tests assert the trace coincides with the band, with the interior twin as the negative control. Underworld development team with AI support from Claude Code
…lus outcrop lands The 2-D outcrop machinery no longer assumes a straight axis-aligned wall: - The ring splice detects the wall span topologically (the mesh's own boundary-edge pairs), and coverage and chain orientation are arc projections onto the removed span's polyline, so a curved boundary orders exactly as a straight wall did. - Which boundary vertices the carve may delete is decided by _outcrop_frame_2d: a vertex goes when the band re-provides its geometry (it lies ON the band) or when it lies on a band-touched straight segment, where the splice's cap stays collinear; a compressed corner off the band is the domain's shape itself and is protected. On a box this reproduces the wall-plane rule exactly. - One contiguous band only (_refuse_multiple_bands); two ribbons out two walls and an arch out the same wall twice keep their refusals. - The boolean imprints tool corners into the clipped face; a clipped corner within 0.1*size of an imprinted domain vertex is merged into it (_collapse_boundary_imprints) — measured 0.18-degree sliver restored to 29.4 degrees against the 29.6 interior twin, with the domain's shape and area untouched since the merge moves the band end along the boundary segment. New test: a radial ribbon out of the annulus's outer boundary embeds, with the interior twin as the negative control; area conserved to 1e-12, every boundary edge relabelled, trace coincides with the band, minimum angle floored at 15 degrees, and the P2 oracle exact through the zone. Box tests unchanged, serial and np=4. The 3-D cap keeps the box frame; generalising it is the next stage. Underworld development team with AI support from Claude Code
…rtition-independent The annulus outcrop runs through the same gather-first mechanism at np=2, 3 and 4, and the info dict — trace count included — is identical at np=1, 2 and 4 (measured: trace=1, zone=44, skin=24, placed=60, removed=17 at every rank count), because the boundary complex is gathered from unshared support-1 facets and sorted into a canonical order before the clip. The new ptest's boundary census skips SHARED facets, not just SF leaves: a partition-seam facet also has local support 1 on its owner side, and a leaves-only probe reports phantom bare boundary edges. Underworld development team with AI support from Claude Code
|
Adversarial review (self, pre-merge): Found and fixed during the work — reporting the negative results:
Checked and held:
Residual risks we have argued but not measured:
Deferred, explicitly: the general 3-D cap (bowl-minus-band collar per coplanar region) — refused with the reason and marked |
…moved segment The general carve/sew subsumes the box-corner outcrop the wall-code frame used to refuse: the corner vertex lies ON the band, so it is deletable and the band re-provides its exact position. What the corner exposed was the label harvest, not the geometry — labels common to ALL removed wall edges are empty across a corner (Top one side, Right the other), leaving the new wall edges bare. The harvest is now per removed edge, and each splice/band edge takes the labels of the removed segment it lies on, so the corner node itself recovers both walls' labels through the two closures. Uniform spans (one wall, the annulus loop) are unchanged. Pinned by a new test: the diagonal corner ribbon embeds with area conserved to 1e-12, the trace present on both walls, no bare wall edge, and minimum angle above 15 degrees. Two separate bands stay refused. Underworld development team with AI support from Claude Code
|
Review addendum (04cca8e): probing the question "is every 2-D outcrop case covered?" found one that was neither tested nor refused. The general carve/sew had silently subsumed the box-corner outcrop the old wall-code frame refused — a single ribbon out through the (1,1) corner embeds, area conserved to 1e-12 — but the wall-label harvest was wrong there: labels common to ALL removed span edges are empty across a corner (Top one side, Right the other), leaving four bare wall edges. The harvest is now per removed edge and each new wall edge takes the labels of the segment it lies on; the corner node recovers both walls' labels through the two closures. Pinned by a new test; uniform spans (one wall, the annulus loop) unchanged; two separate bands stay refused. |
Addresses the curved-boundary side of #555 and builds the trace primitive agreed on #553.
What this does
The thin-volume assembly clip (
place_thin_volume, 2-D and 3-D) no longer intersects with an analytic axis-aligned box. It intersects with the domain the mesh actually has: the boundary facets (support 1 and unshared) are gathered collectively, stitched by exact coordinate identity, and rebuilt as OCC geometry — collinear runs and coplanar triangles compressed to their corners, so a box constructs the same four-sided / six-faced tooladdRectangle/addBoxdid, and the boolean does not imprint the wall's mesh spacing onto the clipped faces. The cut lands on the mesh's own facets (measured 3.5e-17 from the chords, against the 8.6e-3 sagitta a cut on the smooth circle would leave), so no corefinement library is needed and the clip-then-mesh order is preserved: the ribbon still meshes at gmsh quality.The outcrop band is now identified as the trace — membership of the domain's own boundary facets, defined on any boundary — and the band facets carry
<label>_tracealongside the skin and wall labels, in both dimensions. The trace is the intersection itself; it never partitions the wall into named pieces, so an annulus (closed wall) and a 3-D footprint need no naming convention.info["n_trace_facets"]reports the count.The 2-D carve/sew is fully general:
0.1*sizeof an imprinted domain vertex is merged into it, along the boundary segment — measured: a 0.18-degree sliver on the annulus radial outcrop restored to 29.4 degrees against the 29.6-degree interior twin, with domain shape and area untouched.What this does not do yet
The 3-D outcrop keeps the box frame: a zone outcropping on a non-axis-aligned 3-D boundary is refused with the reason (marked
TODO(DESIGN)at_trace_wall_code). The general 3-D cap must re-triangulate the bowl-minus-band collar per coplanar boundary region, with 1-D overlays where the band outline crosses creases — a separate, spike-validated piece of work. The 3-D clip, trace identification and trace labelling in this PR are already general; only the carve/sew cap is not.place_sheet's discrete Sutherland–Hodgman clip is also untouched, deliberately — unifying it is follow-on work.Evidence
test_0854,test_0855,ptest_0854,ptest_0855pass in serial and at np=2/np=4.test_0859: the tool's OCC mass equals the mesh's own summed cell measure to round-off in both dimensions, and — the negative control — differs from the smooth-geometry measure by far more, proving the tool is the polygon, not the circle. A cube merges to exactly six faces.Underworld development team with AI support from Claude Code