Skip to content

wire: boolean.merge_p1 MergeCoincidentSurfaces (unit to green) - #728

Merged
bherbruck merged 7 commits into
tangency-labs:mainfrom
zorak1103:wire/merge-coincident-surfaces
Oct 24, 2026
Merged

bherbruck merged 7 commits into
tangency-labs:mainfrom
zorak1103:wire/merge-coincident-surfaces

Conversation

@zorak1103

@zorak1103 zorak1103 commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor

Machine-generated (Claude Sonnet 5.5 agent) on behalf of @zorak1103.

What

boolean.merge_p1 reaches 0 deferred and is promoted to green. Its 4 deferred cases all stopped at the UNPORTED(boolean.topology_intersector_p3) stub for SmTopologyIntersector::MergeCoincidentSurfaces, called from SmMerge::FixFoundFaceCoincidence. The algorithm was already ported (TopologyIntersector::merge_coincident_surfaces, PR #211); the follow-up its notes left open was an IntersectorBrepP3 for merge p4's ArenaPair. This PR does that and wires the call.

  • boolean/merge/p1.rs: fix_found_face_coincidence is split into check_face_coincidence (the all-edges-mated return) and finish_face_coincidence (rbModifiedTopology from the edge counts). The merge between them needs &mut access to the adapter's own mate store, which the old signature held borrowed.
  • p4/arena_pair.rs: ArenaPair implements IntersectorBrepP3 (modelled on the tested difftest Two) with loop-use and face-use handle kinds, and, since Port MergeInterval imprinting (intersect.curve_class_p6) #721 made MergeIntervalBrep a supertrait of IntersectorBrepP3, MergeIntervalBrep and ClassGeometryMut. merge_context hands out the operand's arena, the entity, the handle mapping and the pair's notification records, attributes and context; the identity callbacks it borrows are held by the pair. A curve identity that caller-supplied keys refuse cannot pass through the context's infallible callback, so the first refusal is kept and the merge fails with it (no rollback of the edit in progress; this error path has no unit test). The private Objs classification wrapper now delegates classification_vertex_point, topology_zone_tol_3d, topology_entity and topology_handle_in; their absence surfaced as an SmVertex::GetTolerance deferral inside the merge. vertex_face_gap keeps the trait default, as the pair does.
  • p4/kernel_adapter.rs, p4.rs: ManifoldKernelAdapter::fix_face_coincidence runs the merge on an ArenaPair with the retained mate store; the ManifoldIntersector::fix_face_coincidence trait method gained kernels and attributes (threaded through classify_edge_faces).
  • Plan: plan/units/boolean.merge_p1.toml to green and an entry in plan/findings.md. (boolean.topology_intersector_p3.toml is not touched: that unit's numbers do not change, and its one-line notes field conflicts with nearly every PR in this area; its "stays UNPORTED ... follow-up" back-edge sentence is stale once this lands.)

Harness changes

Op 2 previously cloned and discarded the other B-rep and compared only the primary's graph plus the face lists, so the merge's edits of the second B-rep were invisible. Now:

  • the C++ shim (harness/cpp/shim/boolean_merge_p1.cpp) appends for op 2 the returned faces numbered by walks after the call, both directions of m_vTI's edge mates, and the other B-rep's raw export (length-prefixed);
  • the runner drives the real adapter with the context-only SmMerge tolerances (SM_EFF_ZERO_SQ, 30 degrees) and compares other_graph, other_geometry and the mates; the trailer parser rejects short or trailing data;
  • the generator gives op 2 another rectangle of the face's plane as other (overlapping, contained, enclosing, touching, sharing edges, and disjoint).

Results

Notes for review

  • What the new variants check. With port: topology.face_p4 (stacked on #693, merged with main) #718 and Port MergeInterval imprinting (intersect.curve_class_p6) #721 on main all rectangle variants pass. The touching and disjoint rectangles compare the two B-reps. For the overlapping, contained, enclosing and edge-sharing ones the merge returns an error status that C++ and Rust agree on (both_errored; no_values rises from 12 to 160 at --seeds 6000 when one such variant is generated alone), so they check the status, not the topology. No generated case has a merge that succeeds and splits faces, so the post-call face numbering and the edge-mate comparison are written for that case but not exercised by a splitting merge yet.
  • Not compared: notification records and attributes (op 2 uses fresh ones) and the geometry of curves the merge creates. The merge's temporary curves stay in the adapter's curve stores (handles are stable; memory only).
  • Possible textual conflicts with open PRs that also touch arena_pair.rs (wire: topology-faces (3 target units) #334), kernel_adapter.rs (wire: topology-edge-brep (7 target units) #335) or append to plan/findings.md (wire: topology-faces (3 target units) #334).
  • An independent review of the diff was done; its findings (face numbering after a split, uncompared mates, trailing-data check, operand checks, stale comments) are addressed in this PR.

zorak1103 and others added 5 commits October 24, 2026 09:48
SmMerge::FixFoundFaceCoincidence now runs
SmTopologyIntersector::MergeCoincidentSurfaces. p1 is split into
check_face_coincidence / finish_face_coincidence around the merge, which
ManifoldKernelAdapter::fix_face_coincidence runs on an ArenaPair that now
implements IntersectorBrepP3 (plus loop-use and face-use handle kinds). The
curve-on-face classification wrapper delegates the topology hooks it lacked.

Op 2 of the harness now compares both operands' graphs, the returned faces
(numbered after the call) and both directions of the edge mates.

difftest boolean.merge_p1: 248/248, 0 deferred (was 244 passed, 4 deferred);
6000 seeds 6152/6152. No other unit's numbers changed.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
IntersectorBrepP3 now requires MergeIntervalBrep (and so ClassGeometryMut).
ArenaPair implements both: merge_context hands out the operand's arena, the
entity, the handle mapping and the pair's notification records, attributes and
context. The identity callbacks it borrows are held by the pair; a curve
identity that caller-supplied keys refuse is reported as the merge's error.

With the face_p4 FindVertexSector and curve_class_p6 MergeInterval ports on
main, the op-2 generator takes the overlapping, contained, enclosing, touching,
edge-sharing and disjoint rectangles; all pass.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@bherbruck
bherbruck added this pull request to the merge queue Oct 24, 2026
@bherbruck
bherbruck removed this pull request from the merge queue due to a manual request Oct 24, 2026
@bherbruck
bherbruck added this pull request to the merge queue Oct 24, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Oct 24, 2026
@bherbruck
bherbruck added this pull request to the merge queue Oct 24, 2026
Merged via the queue into tangency-labs:main with commit 76f27c3 Oct 24, 2026
7 checks passed
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