Ports tangency-labs/smlib@2223108 behind
Kernel::fixes.fillet_mitre_gap_patch: SmFilletNx2Corner::AdjustTopology
builds the concave corner's topology (AdjustConcaveCornerTopology) for a
bevel at a face's concave corner whose rails meet the side edge at two
places, and CreateCornerPatch fills only that gap (m_bBevelGapPatch).
Tested on the fork's sloped basin and SolidCraft's 1080 basin cases.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
Ports tangency-labs/smlib@4f06e72 (the owner's ruling of 2026-10-30)
behind Kernel::fixes.fillet_mitre_concave_face_corners: the Nx2
corner's mixed-convexity 3-sided face is skipped, so a pocket's rim or
a boss's root is mitred at its sharp corners as at a corner of uniform
convexity. Tests against the fork's closed forms, including the pocket
rim chamfer past the floor (d 5.5, a cliff overflow closed by WR-636).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
Preserve main's default-compatible interval-knot fix and WR-474 record.
Retain the original unit regression for default and opted-in behavior,
and remove obsolete mismatch waivers by matching main.
Co-Authored-By: OpenAI Codex <noreply@openai.com>
An accepted cliff overflow on #1467's box at r10.01/r10.02 subtracted a
closed removal region, and the Boolean returned success with an open or
empty body. SubtractRemovalRegion now requires the result of a subtraction
from a manifold solid to be a manifold solid with faces; otherwise the
target is put back and the blend is refused as no room
(NoRoomReason::CliffSubtractionLeavesNoSolid). The fork has no such check
(it tests only the Boolean's status); recorded in a WR-631 addendum.
Test: wr631_cliff_overflow_construction.rs,
an_overflow_whose_subtraction_leaves_no_solid_is_refused.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
Ports the SolidCraft fork's tangency-labs/smlib@eddf0ed and @bba9914 (branch
replay/1.0.1) into CloseRemovalRegion, under fixes.fillet_cliff_overflow:
- WR-635 (eddf0ed): a lamina edge's host is never the surface its own sheet
face lies on (sm_LiesOnSurface), a chain ending at a filleted edges' vertex
of its host closes there, and a planar surface of any kind continues as its
plane (sm_PlaneOf) for the distance and the covering surface. A sloped
basin's rim chamfer past the slab's front builds instead of "lies on the
surfaces of two faces".
- WR-636 (bba9914): a closed chain on a planar host closes with the face
between it and the host's fully blended loop (sm_CloseRoundLoop). A pocket
rim chamfer past the floor builds instead of "closes on one face".
Tests: tests/wr635_636_cliff_overflow_closing.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
Upstream's CopyFaces notifies SM_NO_COPY on each copied face, edge and vertex
(SmMerge::MakeFaceuse), so attributes reach the copies as their behaviours say.
The port's copies ran with an empty attribute store.
- topology::brep::p2::CopyNotifyState: notification state for a copy between
two B-reps, holding both B-reps' own attributes (source objects under tagged
copy_source_ref identities) and giving each B-rep its own back.
- topology::brep::p7::copy_faces_from: copy_faces with distinct source
identities (copy_faces delegates to it unchanged).
- SmFeatureExecutive: PartitionFeature and RestoreFeature copy with the
attributes. The patch path does not yet: its merges still differ from SMLib
(finding addendum).
- Shim, FFI and runner: optional SmLongAttribute inputs, plus per-id face and
edge counts of every B-rep in the record; 4 attribute cases (3 pass; the
extrusion case fails until the patch path carries).
- Unit test: copy and reference attributes reach the feature B-rep, temporary
ones do not.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
SmApiCreateSweep polygonizes the path to dTol / 2 in N_CreateSweepScale before
it relaxes the tolerance; on a quarter-arc path the C++ takes 0.44 s at radius
1e5, 4.8 s at 1e6, 26 s at 3e6 and gives no result in 30 s at 1e7, 1e8, 1e9,
all admitted by the old 1e12 control-polygon bound. Straight paths return at
once at any length. check_path_extent (public) keeps the 1e12 bound for every
path and refuses a curved path (any but a degree-1 NURB) above
MAX_PATH_EXTENT = 1e8, the sweep.api_brep bound of #1873; the runner's Rust
side, which had no guard, applies it too. Corpus fuzz00746 now runs both
sides; new constructed corpus case; runner and FFI tests; HANG-5 addendum,
finding, unit notes.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqrY3KqUA9vpCbwBCMF1av
A surface control point of -1e300 (and already -1e155) makes the C++ graph
export never return (SmFace::CreateUVTrimCurves -> CreateUVTrimCurve ->
SmCurve::GlobalCoincidenceChecker, reached through GetVertexFaceGap). The
2026-10-20 guard in topology_loopuse::eval came after the runner's own
topology_edgeuse_p1 export and was dropped. The FFI gains export() (block
parse, check_block_magnitudes, then the native export), which the runner's
graph_of now uses, and eval checks the block before its export; the runner's
Rust side applies the same check. Corpus case, runner and FFI tests, HANG-29
addendum, finding, unit notes. Follows #1873 (topology.edgeuse_p3).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PqrY3KqUA9vpCbwBCMF1av
With fixes.fillet_cliff_overflow, an accepted cliff overflow builds instead of
being refused (the rest of tangency-labs/smlib@8ba4667, ae2a6de at rev 68fb9162,
and the Nx1 miss test of 3f22e97):
- FilletCorner::drop_end_rib (SmFilletNx1Corner::CalcCornerEdgeGeom): in an
overflow a rail end off the fillet surface, or on its side edge's line past
the edge's end, is a miss; both rails may miss; a miss that does not run on
deletes the end rib and notes the open end instead of the global merge.
- blend/fillet_cliff_overflow.rs: CutFilletAtOpenEnd and CloseRemovalRegion,
its host test, chain walk and closing face kept as separate functions.
- session/cliff_overflow.rs: SubtractRemovalRegion and sm_HoldsItsLaw; the
session's DoFilleting runs it instead of the merge and passes its own error
on (ae2a6de, WR-638).
Flag off, every path is unchanged. Regression tests with closed-form volumes:
tests/wr631_cliff_overflow_construction.rs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MNXLXj2sJf943y2dDF36Vy
Nine generated cases drew operands the constructors refuse, so they compared
nothing. The first draw is unchanged; only a refused setup redraws (up to 16).
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>