15 Commits
Author SHA1 Message Date
phanoob 56747edb46 Boolean: a point at a boundary curve's end is that end, whatever its parameter (text cuts, #391) (#1195)
A point within the point tolerance of a boundary curve's end is that end in the boolean, whatever its parameter, so text cuts no longer leave unmatched sliver vertices (#391). Robustness goldens re-recorded for seeds 0, 34, 39, 41 and 57 with reasons.
2026-10-15 13:31:37 -04:00
Lasse Lian 3fa8fbd162 Mesh edges that do not evaluate without a panic; refuse such boolean results (#1252) (#1364)
The mesher samples edges through a fallible evaluation, so an intersection curve whose projection fails to converge no longer panics; a boolean result with an edge that does not evaluate is refused with an error. Fixes #1252.
2026-10-15 11:10:55 -04:00
Lasse Lian 8f081679bc Equal cylinders crossing each other no longer refuse a cut (#788) (#1179)
Equal cylinders crossing each other no longer refuse a cut (#788).
2026-10-14 17:56:02 -04:00
bherbruckandClaude Opus 5.5 dfbf7dd6a8 fix: a lenient parameter boundary found across a seam is not used; record seed 81 (#1003)
#970's lenient retry of a face's parameter boundary searches the whole surface as a last resort; on robustness seed 20 it found an edge's points across a cylinder's seam, half a turn apart, and the Cut failed. A lenient boundary whose points jump half the parameter range or more is refused, and the face is left undivided as before (#970's elbows step at most a fifth of the range). Seed 81's volume moved by 0.1 mm3 with #952's hole direction; recorded.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-14 04:56:39 -04:00
Giovanni 9c51f9d433 Retry a face's parameter boundary leniently (#970)
Cutting one lofted round tube from another failed in truck's divide_face ("parameter boundary") for some section counts: the intersection points lie on the loft's seam, the previous point's parameter can sit a hair outside the range, and the Newton search from there fails.

The boundary is built as before; only when that returns None is it built again leniently, starting each search from the hint clamped into the parameter range and, as a last resort, searching the whole surface. Nothing that succeeds today changes. The boolean-retry guards are untouched.

Fixes 5 of the 6 failing hollow-elbow cases in #968 (new test crates/engine/src/tests/loft_cut.rs, volumes within 0.3% of exact). 90 degrees / 14 sections still fails in a later step and stays open in #968.
2026-10-14 01:50:00 -04:00
bherbruckandClaude Opus 5.5 a3dfbaa0b0 Booleans build the same body every time: face order no longer follows heap addresses (#748)
truck's face and edge IDs are their addresses, so walking maps keyed by them followed heap layout, and the ribbed lid's side-wall hole passed or failed by chance. The planar boolean's rebuild and glue now take truck's connected components in the shell's order, and the planar boolean's own maps are ordered. Healing's union-find keeps the lesser root and takes a run's ends in order of use. The face classification after an intersection orders each component's faces by the shell first. The lid now builds the same body on every run, with a test that builds it six times in one process. Its 0.5 mm side-wall holes, and one sensor enclosure hole of the same kind, now fail every time and are marked failing in the baseline.

Fixes #707.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-13 12:31:23 -04:00
bherbruckandClaude Opus 5.5 296683229d Rename SolveCraft to SolidCraft everywhere, with compatibility shims (#389)
* WIP deep rename (not for push)

* WIP2

* WIP3

* WIP4 wxs fix

* rustfmt

* Rename the remaining identifiers in merged crash-report code

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <[email protected]>
2026-10-12 17:17:01 -04:00
Iraklis KourtisandClaude Opus 5.5 d5cb276965 feat(kernel): every boolean path reports exact face and edge history
ops::boolean's result carries its history over [a, b] whichever path made
it, recorded by the code that builds the faces:

- truck path (incl. jitter retries): shapeops history mapped through the
  order-preserving copies and the cut's turned tool, then through healing
- heal records which input faces each healed face merges and which input
  edges each joined or exact edge replaces (HealMap); opt-in, so heal_keep
  callers pay nothing
- trivial shortcuts, the void, glue, faces pushed apart (push_faces records
  its own history; the slab cut back on a union maps to the operands'
  faces in that plane), the nudged retry, by_lumps and join composition
- prism booleans: section segments carry tags (operand cap edge, the wall
  beside it, its vertices) through the 2D boolean; walls, caps and edges of
  the extruded or sewn result follow from them
- planar and faceted polygon booleans: polygons carry their operand face;
  faces join the pieces across edges, edges come from the pieces either side

History gains renumber/over (and consuming forms) for composition;
record gains regions/traced/build helpers. truck-shapeops
*_with_history now return the solid with an Option history. Paths that
cannot report (bore narrowing via offset, inexpressible lineage) leave the
result without history. Boolean results, tolerances and fallback order are
unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
Iraklis KourtisandClaude Opus 5.5 cc4955a8da feat(shapeops): face and edge history from booleans
and_with_history / or_with_history return, with the solid, the operand face
each result face is a region of (and whether it is that face untouched) and,
for each result edge, the operand edge it is (a piece of) or the pair of
operand faces whose intersection made it. Faces and edges are recorded where
they are created (face division, intersection edges, split edges, edges
rebuilt on a moved vertex), resolved to operand terms at creation, so the
passes folding in extra shells compose without bookkeeping. and / or wrap
the same pass and drop the history; a missing record never fails them.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
lillith ed102b5393 fix: reject degenerate boolean intersection polylines 2026-10-12 08:36:40 -04:00
bherbruckandClaude Opus 5.5 1bf377c14b No panics in the boolean's final assembly (the web build aborts on any panic: the Plastic Enclosure sample panicked 8 times and crashed the browser's start page); face pushes check their result and fall back to the general offset (a boss standing on a plate joins again with off-axis cylinder seams); offset errors name the face they can't move; docs/robustness.md with the before and after rates; caught panics counted per design in the robustness runs
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-10 00:04:37 +00:00
bherbruckandClaude Opus 5.5 81c85b553c Booleans are deterministic: result faces keep their shell's order
truck's connected components came out in hash order of face addresses, so a
boolean's faces, and everything built on them (fillet bands, STEP entity
order), changed from run to run. That made the oracle 35 export differ run to
run. Its old step_export flakes came from the orientation check's drifting
search, removed in 2db9e66. The result's shells and faces now keep the
order of the shell they come from (vendored truck-shapeops). Oracle results
are unchanged (73 PASS before and after). Test: the tee of oracle 35 with its
junction fillet exports byte-identical three times in one process (it failed
before).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 09:53:16 +00:00
bherbruckandClaude Opus 5.5 5539de8fd4 Booleans: a face crossed by nested intersection loops (both walls of a tube) gives each hole to the innermost piece holding it (vendored shapeops; tubes and tori cut across now work); revolved full circles start at an odd angle so their seams don't lie in common cut planes
Oracle: 70/76.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 05:59:28 +00:00
bherbruckandClaude Opus 5.5 57d01f8405 Kernel: revolved faces turned away from the angle wrap (booleans with revolved bodies work), cuts that leave pieces make separate bodies, trivial booleans (clear of / inside) by sampling, body mirrors with join; recipes: pattern source names, thread, holes at sketch points, mirror of bodies
Oracle: 43/66.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 00:00:51 +00:00
bherbruckandClaude Opus 5.5 043a542e29 Kernel: pole-free six-patch spheres; vendored truck-shapeops with robust meshing and nearest-parameter loop projection (sphere and box booleans work); least-squares sphere classification
Oracle: 25/29 (14 and 15 now match Fusion).

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-07 21:30:18 +00:00