Commit Graph
21 Commits
Author SHA1 Message Date
bherbruckandClaude Opus 5.5 6d5df4b9b3 Sketch on cut walls, chamfers, pattern copies, join-merged sides and split faces (#625)
A flat face that no construction certificate names on its own now attaches by its exact history name (a new lineage face certificate): cut walls and floors, chamfer faces, each pattern or mirror copy, side walls a Join merged, and the pieces a later feature split a face into. Construction certificates still come first; a seed keeps its certificate when it is patterned. Two flush extrudes of one outline joined end to end keep their exact history in the prism boolean. Face sketch 52% -> 71%, offset plane 52% -> 71%, press-pull/extrude from face 41% -> 60% in the action matrix; baseline blessed.

Fixes #491, fixes #492, fixes #493, fixes #557.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 05:26:29 -04:00
NOWN-DEVandClaude Opus 5.5 2f7046efac fix: lines lying on one another do not cross in planar booleans (#507)
Two line segments that lie on one another within the tolerance, a hair from parallel, no longer report a crossing somewhere along their overlap; the ends of the overlap split the edges instead. This stops booleans from leaving sub-tolerance edges or stray vertices.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-13 00:11:55 -04:00
Irakli KourtisandClaude Opus 5.5 01bf0e4eaf perf: pattern joins skip pushing apart faces that don't meet (#437)
Pattern copies of a post joined to a body already holding the original post had
their tops in its plane, so every join first pushed faces apart (about 190 ms,
then discarded). Faces now coincide only where their boxes meet, the push-apart
retry runs once per boolean instead of twice, and splitting prism outlines skips
the sampled arc projection for points off the arc's circle.
Sensor enclosure evaluation: 3.07 s -> 1.63 s, same bodies.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:35:43 -04:00
NOWN-DEVandClaude Opus 5.5 0d995c6a78 fix: lines and arcs that touch meet at one point in planar booleans (#432)
The planar arrangement solved a line and a circle, or two circles, for their two
crossings even where the curves only touch. At a tangent contact the two roots are
rounding noise spread along the curves by its square root: a 1e-12 mm error in the
centre's distance from the line puts them 2e-6 mm either side of the contact on a
2 mm arc, well inside the tolerance of both curves; when the noise falls the other
way there is no root at all. Cutting a rounded corner (an arc tangent to the two
edges it ends on) out of a plate with planar_regions_boolean then ran that far along
the plate's edge past the arc's end before turning onto the arc: a 200 x 37 plate
turned by 0.25 degrees came back with six edges, one of them 3.45e-6 mm long.

Curves that touch within the arrangement's tolerance now meet at the one point their
centres give: the foot of the circle's centre on the line, or the point on the line
of centres of two circles tangent inside or outside. Circles of nearly one radius
about nearly one centre keep the general formula.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 19:22:39 -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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 17:17:01 -04:00
bherbruckandClaude Opus 5.5 57e6396fbb Tangent hole contacts split no faces, consistently (#307) (#364)
* Tangent hole contacts: every symmetric contact gives the same faces (#307)

Three things made the four symmetric contacts of reference case 42 differ:

- The 2D prism boolean's ray-parity test miscounted a ray grazing the bottom
  of a patterned hole, whose two halves are read back with centres a few ulps
  apart: one half counted the touch, the other missed it. The loop chaining
  then failed and those cuts fell back to the general boolean, which treats
  circles tangent within its tolerance as overlapping and splits the hole.
  The ray is now moved off vertices and arc extremes by far less than any
  modelling tolerance.
- The prism result's volume check used a coarser mesh than the operands, so
  a plate with many holes read too large and correct results were rejected.
- The merged topology did not join a hole's two pieces across the line where
  two tangent holes touch (four faces meet there).

Case 42 now gives 39 faces (33 holes, 6 planes); its expected.json pins it.

Fixes #307

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

* Kernel test: tangent hole pinch no longer splits the wall (#307)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 15:01:03 -04:00
a7e47fdae6 fix: unfold sheets shrunk by a parameter change (#349)
A sheet-metal tray built at 2000 x 2500 mm with an edge flange on all four
edges (72° or 90°) and unfolded failed to rebuild when W and H went to
400 x 300, 600 x 450, or W alone to 400: "planar region arrangement failed
or exceeded its bounded processing budget". The same tray drawn at 400 x 300
unfolded, and growing it worked.

The sketch solved again after the change leaves its corners ~1e-13 mm off,
so the flanges inherit a hair of tilt and their panels and bend zones meet
the trimmed base within 1e-13 mm instead of exactly. The flat pattern is a
balanced union of those pieces, and the arrangement chains its output loops
within 10 tol. In a later round, ray parity classified a bend zone's edge
midpoint that lay level with a corner whose two lines did not quite meet:
the ray slipped through the gap without a crossing, the zone's edges counted
as inside the other operand and were dropped, and the outline no longer
closed. A rectangle turned by 1e-14 rad failed the same way.

inside_loop now closes the gap where one line ends and the next begins with
a straight connector while it counts crossings; exactly closed joints are
unaffected. Joints with an arc keep the arc's own endpoint rule, which
treats ends within its angular tolerance as on the ray (a connector there
double counted at a circle split into two arcs).

Co-authored-by: NOWN-DEV <257771410+NOWN-DEV@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-12 14:15:55 -04:00
Iraklis KourtisandClaude Opus 5.5 08d797235d feat(kernel): history across coalesced stepped walls (#136)
A cut of stepped prisms sews a wall over one segment through successive
slabs as one face, and the generated planar walls are then joined on
their common supports. Until now such a piece carried no history.

- prism_lineage: a sewn wall records what it is over in each slab it
  spans (Spec::Wall { levels, slabs }), so a coalesced wall comes from
  the operand walls under it in every slab
- the sewn piece's history is attached before the joining and carried
  through it (Built::Traced); planar_regularize composes the history of
  the body it joins with the join itself
- a composed face is Split only where record::mark_shared_split finds an
  origin under several faces; an inner Split alone no longer makes one
- Body::same ignores history: an operation that leaves a body as it is
  gives the same body, carrying that operation's history

The two boolean history tests that waited for this run again, and the
coalesced and regularized step cuts are covered.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
Iraklis KourtisandClaude Opus 5.5 97bcdb4d06 feat(kernel): settle a slab's far cap edge by operand topology (#136)
The far edge of a stepped slab (the operand cap edge where a segment's
wall ends) was recorded by testing whether each slab segment runs along
an ending cap's segment in 2D, a tolerance comparison of coordinates.
Matching by topology makes the far edge exact by construction instead:
when the wall's top is the ending level, nothing crosses it there, and it
meets the caps at that level in exactly one edge, that edge is over every
segment beside the wall, with no position compared.

A vertex walk up the wall's side edges from the segment's ends was tried
first and does not settle the cases that need it: a notched or stepped
wall continues past a segment's end (no side edge rises from it), and
walls split by earlier stations have mid-chain vertices with no side edge.
Whenever the walk succeeds, the wall is a rectangle over the segment and
the one-edge rule above already holds.

The positional match remains only where topology cannot say which edge
is over a segment: a wall that meets the ending caps in several edges (a
top split at earlier station vertices, or beside a wall crossing it at
that level) or that carries on past the level elsewhere. It is documented
in `Section::mark_far` and its pair budget no longer stops topological
marking. Far edges are also only marked on the slab that actually ends at
the level (a gap level no longer revisits an earlier slab).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
Iraklis KourtisandClaude Opus 5.5 688f806682 feat(kernel): exact chamfer history after pocket, step, slot and bite cuts
Chamfer is one of the most common features and is usually applied right
after a cut. A chamfer cuts with a prism cutter, and its history came out
None after four of the six common box cuts. Without exact history, any
reference to a chamfer face (or a face it trimmed) falls back to geometric
guessing in naming, which can silently re-attach to the wrong face.

Two gaps in the stepped-prism section tags caused it, both now closed by
bookkeeping at construction, never by sampling or geometric tie-breaks:

- Cap edge at the far end of a slab. A slab's section is read off the cap
  where it starts and carried up to the cap where it ends; that cap's
  outline can run along one wall in several collinear edges, so which one
  a result edge lies on was unknown. When the stack is read, each slab
  segment that runs end to end along one segment of an ending cap's
  outline (beside the same wall) records that cap edge as `far`; the
  lineage takes it when it bounds the wall and the result cap.

- Walls an earlier cut left in coplanar pieces. A segment carried through
  a level kept the wall it was read beside, even where that wall gives
  way to another piece at the level (or within the slab), so the tag named
  the wrong face. `Stations` records the operand's edges across walls;
  at each level a carried segment keeps its wall when nothing crosses it
  there, moves to the one wall across it when it ends there, and is
  otherwise unknown (no history). A wall crossed inside a slab is unknown
  too, for simple and stepped prisms alike.

chamfer_after_box_cuts now covers all six cuts (notch, pocket, step,
slot, hole, bite), each verified against geometry and composed through
the cut over [block, tool]. The layered partial-depth cut test now
verifies its second cut, whose history was None before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -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 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J53sR6gEaVt56soFDpTck8
2026-10-12 11:52:53 -04:00
bherbruck c53aff7592 Fix artificial Shell wall splits on stepped bodies 2026-10-11 22:32:53 -04:00
bherbruck ef8f6ca6f9 fix: restore shell and cut wall topology in 0.2.1 2026-10-11 15:17:05 -04:00
bherbruck 4e595deff2 feat: preserve adaptive sketch profiles and curved modeling workflows 2026-10-11 09:06:25 -04:00
bherbruck c1d819f235 feat: preserve body history and placed modelling workflows
Record ownership transfers in the timeline so earlier Join/Cut membership,
world placement, machining data and styles survive component moves, edits,
independent copying, undo and reopening. Preserve pending positions in history
snapshots and keep constructor transfers ordered during feature redefinition.

Retain shallow sheet pockets and exact planar intersection islands through
unfold/refold, with depth-aware flat previews and DXF export. Store explicit
3D wire coordinate spaces and migrate known legacy provenance without moving
saved points or analytic fits.

Infer unique eligible cylindrical Emboss targets, align Revolve manipulators
with actual extent geometry, and discard obsolete preview errors after input
correction. Certify constructed and immutable imported face styles using exact
source metadata while preserving legacy face names. Upgrade designs to format10
with bounded validation and geometry-preserving legacy migration.
2026-10-11 03:59:12 -04:00
bherbruck 07932d0f42 feat: preserve modeling intent across sketches, assemblies, and fabrication
Persist typed sketch dimensions and bounded ordered configuration rules in format 8. Use exact occurrence paths and source identity for editing, movement, appearance, and mass. Preserve sheet material regions through cutting, folding, and exact DXF export; retain nested cavities and material islands.

Validation: cargo xtask ci passed, including 368 engine tests, 178 UI tests, 68 UI scenarios, 136 kernel tests, and the 10-crate wasm check. Actual preview workflows and legacy format-7 origin-corner reopening were inspected.
2026-10-11 01:28:01 -04:00
bherbruck 22672585c9 fix: join connected solids at exact edge contacts 2026-10-10 23:11:02 -04:00
bherbruck c1b6478ab5 fix: join additive extrusions and merge coplanar faces 2026-10-10 21:31:19 -04:00
bherbruck d6cdec40da Fix modelling regressions and reconcile WIP UI work 2026-10-10 15:37:00 -04:00
bherbruckandClaude Opus 5.5 69353faf75 Kernel: clippy
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 04:53:49 +00:00
bherbruckandClaude Opus 5.5 fc7cb5d60d Booleans: prisms along one direction combined exactly in 2D (overlapping holes in plates; equal sections stacked end to end), bodies touching along one whole face stitched (a part joined with its mirror image), pushing coincident faces works with any plane-and-cylinder neighbours
Oracle: 60/76.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
2026-10-08 04:53:49 +00:00