Repository navigation
wire: boolean.merge_p1 MergeCoincidentSurfaces (unit to green) - #728
Merged
bherbruck merged 7 commits intoOct 24, 2026
Merged
Conversation
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>
…does (identical hunk, no conflict)
github-merge-queue
Bot
removed this pull request from the merge queue due to a conflict with the base branch
Oct 24, 2026
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Machine-generated (Claude Sonnet 5.5 agent) on behalf of @zorak1103.
What
boolean.merge_p1reaches 0 deferred and is promoted togreen. Its 4 deferred cases all stopped at theUNPORTED(boolean.topology_intersector_p3)stub forSmTopologyIntersector::MergeCoincidentSurfaces, called fromSmMerge::FixFoundFaceCoincidence. The algorithm was already ported (TopologyIntersector::merge_coincident_surfaces, PR #211); the follow-up its notes left open was anIntersectorBrepP3for merge p4'sArenaPair. This PR does that and wires the call.boolean/merge/p1.rs:fix_found_face_coincidenceis split intocheck_face_coincidence(the all-edges-mated return) andfinish_face_coincidence(rbModifiedTopologyfrom the edge counts). The merge between them needs&mutaccess to the adapter's own mate store, which the old signature held borrowed.p4/arena_pair.rs:ArenaPairimplementsIntersectorBrepP3(modelled on the tested difftestTwo) with loop-use and face-use handle kinds, and, since Port MergeInterval imprinting (intersect.curve_class_p6) #721 madeMergeIntervalBrepa supertrait ofIntersectorBrepP3,MergeIntervalBrepandClassGeometryMut.merge_contexthands 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 privateObjsclassification wrapper now delegatesclassification_vertex_point,topology_zone_tol_3d,topology_entityandtopology_handle_in; their absence surfaced as anSmVertex::GetTolerancedeferral inside the merge.vertex_face_gapkeeps the trait default, as the pair does.p4/kernel_adapter.rs,p4.rs:ManifoldKernelAdapter::fix_face_coincidenceruns the merge on anArenaPairwith the retained mate store; theManifoldIntersector::fix_face_coincidencetrait method gainedkernelsandattributes(threaded throughclassify_edge_faces).plan/units/boolean.merge_p1.tomltogreenand an entry inplan/findings.md. (boolean.topology_intersector_p3.tomlis 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:
harness/cpp/shim/boolean_merge_p1.cpp) appends for op 2 the returned faces numbered by walks after the call, both directions ofm_vTI's edge mates, and the other B-rep's raw export (length-prefixed);SmMergetolerances (SM_EFF_ZERO_SQ, 30 degrees) and comparesother_graph,other_geometryand the mates; the trailer parser rejects short or trailing data;other(overlapping, contained, enclosing, touching, sharing edges, and disjoint).Results
difftest --unit boolean.merge_p1:PASS cases=248 passed=248 failed=0 deferred=0 with_values=236(main before this PR: 244 passed, 4 deferred).--seeds 6000:PASS cases=6152 passed=6152 failed=0 deferred=0.7292bda1d):cargo fmt --check;clippy --workspace --all-targets -D warningswith and withoutdifftest/cpp;cargo test -p solidcore(2096) and the difftest-crate tests (273);cargo check --target wasm32-unknown-unknown;--green: 260 units, 213 passed, 47 partial, 0 failed.95c30590a): fmt, clippy both ways,cargo test -p solidcore --lib(2099), wasm, anddifftestofboolean.merge_p1(248/248; 6152/6152 at 6000 seeds) through_p5,boolean.api_brepandboolean.topology_intersector_p1to_p3: 0 failed, deferral counts as on main. The full--greenrun was not repeated after that last merge (it was stopped twice for memory pressure); CI will run it.boolean.merge_p1changed, including the other users of the path (boolean.merge_p4311/140/0/168,boolean.api_brep287/151/0/136).unmated_faces_reach_the_coincident_surface_merge(the path used to returnUnported).Notes for review
both_errored;no_valuesrises from 12 to 160 at--seeds 6000when 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.arena_pair.rs(wire: topology-faces (3 target units) #334),kernel_adapter.rs(wire: topology-edge-brep (7 target units) #335) or append toplan/findings.md(wire: topology-faces (3 target units) #334).