Adds a MergeBreps runner op (shim op 35, SmBrep::MergeBrep) that puts both
operands in the primary B-rep as SmMerge does, and merged_* cases that run
SetEditing, EdgeFace and FaceFace on faces of that one B-rep.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Adds a SetEditing script op (shim op 34, m_bEditingEnabled), a ChainFaces
marker that lets a FaceFace without input vertices follow a VertexFace or
EdgeFace (the FFI guard now allows exactly that), Vertexuse handles in the
runner's topology_entity, and crossing-plane fixtures. Existing cases are
unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
map_to_2d_on_curve evaluates the UV curve of a curve on this very surface
object (std::ptr::eq with the base surface) instead of returning Unported.
The surface_p9 analytic-surface stub was unreachable: the diagonal
SmCrvOnSurf already holds the analytic surface. Eight sphere and torus
diagonal cases (shim kinds 5 and 6) compare against C++.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
offset_executive_p2: tiny/far-translated boxes build as an empty B-rep and
merged/dropped-face sheets as a degenerate face; both are defined native
results (no crash, hang or UB) and are now built and compared on both sides.
Only a selection of the nonexistent face 0 stays rejected (nothing to run).
trans_sweep_geometry: a curve constructor failure status is compared with
Rust's instead of rejected; null curves are never passed to
CreateWireEdgeFromCurve.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
A runtime backtrace shows AdjustConcaveCornerTopology (SmFilletCorner.cpp:7185)
extending the side surface by 10 * dGapDist; with dGapDist == 0 the
CreateExtendedSurface halving loop (HANG-9) never ends. Add an addendum to HANG-9
and point the shim guard comment at it; the guard condition is unchanged.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Generated patch and calc_geom corner cases give the model's fillet geometries a base solver
with a cross-section generator, identically in the Rust runner and the shim, so the
analytic-corner fits that read the solver run instead of being refused. The shim now
follows MakeAnalyticCornerSurface past the solver reads (chamfer re-intersection, the
constant radius conversion's generator checks); solver-less geometries stay refused.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
A new classification kind 5 puts the model's side edge use on the first loop of a
target face, so the side face (and its radial's face) exist and
AdjustConcaveCornerTopology reaches the surface extension. Rejected cases 19 -> 7.
The shim also refuses coincident rail points with a zero tolerance, where
CreateExtendedSurface (by 10 * 0) does not return.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
boolean.api_brep now records, per region in GetRegions order, IsVoid,
IsInfiniteRegion and the shell count, and per shell its faceuse count and
the region behind its first faceuse's mate, so region and shell order are
compared against SMLib.
That exposed three merges of inverted spheres (gen0001, gen0033, gen0118)
whose region list differed from SMLib's. The B-rep region list was modelled
as the region arena rotated to its head, which is only SMLib's circular list
while the head is the oldest region. Once the head moves to a later region
(the inverted sphere's infinite region), SmOwningTopology::PostInsert
appends before the head, but the arena model put new regions after the
newest one. The Brep now records the link order whenever the head moves or a
region is pre/post-inserted or removed; regions appended since follow in
arena order, as PostInsert.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
The shim no longer refuses a corner edge without a 3D curve: upstream
CreateCornerBlend returns SM_ERR below four curves and otherwise
SM_ERR_NULL_POINTER, without crashing. create_corner_patch now checks the
count before dereferencing curves, matching that order.
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Follows #1077: a result-changing fix of an upstream defect is an opt-in
`Kernel::fixes` field and the default is pinned SMLib behaviour.
- WR-214 (#480): the Boolean's topology intersector sets
`split_self_loops_on_vertices` from `proto_edge_self_loop_on_vertex_degenerate`
instead of forcing it off.
- WR-254 (#528): the slice side rule for coincident faces needs
`slice_coincident_faces_sheet_side`; by default the slice takes upstream's
difference rule.
- WR-265 (#388): `put_outer_shells_first` (shell order and the nested-solid
void-flag rewrite) needs `boolean_outer_shell_first`.
The boolean.api_brep runner can now build sheets (SmApiCreatePlane) and operands
that are an SmApiBoolean result, and it gains the C++-confirmed WR-254 and WR-265
repros as fixture cases that pass at the default. Each fix has an issue test with
the field on and a test that pins the default.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Both CheckLoop fixes stay independent opt-ins: check_loop_vertex_tolerance
(WR-381) widens the junction gap limit, check_loop_projected_seam_ends
(WR-440) lifts projected ends across periodic seams. BCheckLoop inputs keep
both PRs' pre-steps (gap, tolerances, then project) in the Rust runner, FFI
guard and C++ shim; the fixture keeps both PRs' cases. A new test runs a
mixed-seam gap that needs both fields to close.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Main split the frozen archives and the known-mismatch list into one file
per entry. #709's records move accordingly:
- plan/findings.md section -> plan/findings/topology.trimming_tools--projected-loop-endpoints-periodic-seams.md
- plan/upstream-issues.md WR-264 -> plan/upstream-issues/WR-440--checkloop-projected-periodic-ends-as-exact-sheets.md
(renumbered: #700 also uses WR-264)
- crates/difftest/known_mismatches.toml entries -> crates/difftest/known_mismatches/topology.trimming_tools.toml
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf
Resolved by #358's intent:
- heal.gap topo and heal.heal_data_p2 block guards (>= 1e154) dropped: main's
topology.vertexuse export, which both units build on both sides, already
refuses B-rep blocks above 1e150 (HANG-29, d725baf2c). The PR's regression
tests still run its triggers and now expect that refusal.
- boolean.topology_intersector_p1 coordinate bound, UB-166 knot read-back and
blend.fillet_geom_p2 RailRail original-face bound kept unchanged.
- plan/findings.md and plan/upstream-issues.md edits moved to per-entry files
(HANG-29 and UB-166 addenda, three findings files), as main split those
archives.
- Both sides of the conflicting test modules kept.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011gJAwcLRBPQXYLmvXd3pWf