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.
This commit is contained in:
bherbruck committed 2026-10-11 03:59:12 -04:00
1 parent 0398a813c8
commit c1d819f235
86 files changed
+6011 -488

No files matched your search

+8 -4
View File
@@ -18,7 +18,11 @@ replaced version is kept as `<file>.bak`. Unsaved changes are autosaved to a rec
and the next launch offers to recover them. Older design files are upgraded on open, and files
from a newer version are refused with a message.
Current designs use format 9 for semantic configuration styles, associative free-form offsets
and explicit cylindrical emboss selections. Older geometry and expressions retain their
meaning during upgrade; missing new fields use defaults. Association records and occurrence
paths are bounded and checked before they can alter geometry.
Current designs use format 10 for recorded body transfers, explicit 3D curve coordinate
spaces and certified face bindings, alongside semantic configuration styles, associative
free-form offsets and cylindrical emboss selections. Older ownership maps, geometry and
expressions retain their saved meaning. Legacy 3D curves with retained associations receive
their producer's coordinate-space marker without changing any saved points; detached curves
retain world coordinates. A lost cross-component association refreshed by an older build may
need an explicit relink or refresh when its source returns. Loading never guesses a numerical
correction. Association records, coordinate arrays and placements are bounded and checked.
+15
View File
@@ -38,3 +38,18 @@ Cuts can leave separate material pieces, including the centre of a ring cut. The
remain one logical sheet group through Unfold / Refold and export as separate flat outlines.
Large profiles that exceed the geometry processing budget report an error instead of
exporting a partial outline.
Parallel, untapered extrude cuts also preserve shallow pockets through Unfold / Refold.
The pocket floor and side walls remain solid geometry; overlapping cuts from opposite sides
become a through hole wherever they remove the whole thickness. Flat-pattern JSON lists
`pockets` with their side, depth and bottom/top thickness coordinates in millimetres.
DXF pocket boundaries use `POCKET_BOTTOM_Z…_TO_…_MM`, `POCKET_TOP_Z…_TO_…_MM`, or
`POCKET_INTERNAL_Z…_TO_…_MM` layers. These are machining operations, so do not treat every
pocket layer as a through-cut contour when importing the drawing into a CAM tool.
Extrude Intersect on a straight base or an unfolded sheet retains the exact planar material,
including interior holes and detached islands. A completely empty intersection removes the
sheet and its metadata together. Pocket profiles can move with planar panels when forming,
but a pocket crossing a bend zone cannot yet be refolded. Machining folded bend material,
tapered sheet cuts and other unsupported 3D sheet Cut/Intersect operations report an error before changing
the design; they cannot silently restore removed material during a later sheet rebuild.
+12
View File
@@ -29,6 +29,18 @@ Smooth open offsets can be offset again, including bounded refinement after a so
A closed offset uses a natural cubic spline whose seam can have different end tangents;
offsetting that result again is refused when the seam has no unique normal.
Enable **3D Sketch** in the Sketch Palette to draw lines, fit splines and points off the plane.
New 3D geometry follows its sketch's component placement, including the selected occurrence
and pending position changes. Click a drawn fit point to show its move triad; its arrows move
along world X, Y and Z. Scripts also supply world coordinates to `sketch.line3d`,
`sketch.spline3d`, `sketch.point3d` and `sketch.move3d`. Activate the desired occurrence before
editing an explicit sketch belonging to a component with multiple placements.
Older drawn or detached 3D wires keep their saved world positions. Included and surface-linked
wires with an explicit component marker keep that meaning after the link is broken. Old files
whose links became lost after an incorrectly scoped cross-component refresh may require a
fresh link once the source is available; their stored point values are preserved on opening.
## Constraints and dimensions
The solver is SolveCraft's own (damped Gauss–Newton with degree-of-freedom analysis). Constraints:
+18 -6
View File
@@ -44,13 +44,13 @@ feature that produces that body, and become visible when it returns.
body and semantic role. You can also select a viewport face before opening the menu and use
**Selected face on ...**. These assignments affect every occurrence sharing the definition.
Component columns use stable component IDs, so renaming a component preserves its rows.
Face columns use a definition body and semantic lineage, never a saved display face index.
Face columns resolve a definition body through certified lineage, never through a saved display face index.
```json
{"command":"config.configure","params":{"component_appearances":["Part"],"face_appearances":[{"body":"Box1","point":[5,5,10]}]}}
```
Use a point on the current surface to capture a face. World occurrence picks are converted
Use a point on the current surface to capture a face. The menu carries its already certified target directly, avoiding a second nearest-face pick on thin concentric walls. World occurrence picks are converted
to the shared definition coordinates. `config.table` returns canonical keys and readable
target labels. Use its returned face key when editing a row or deleting a face column:
`config.column` accepts `face_appearance: "<returned key>"` with `delete: true`.
@@ -60,7 +60,11 @@ Supported stable face roles are box axis faces, cylinder caps and unsplit side,
extrude caps, and one-sided revolve caps. From/nonzero or variable Start Offset/Two Sides extrude caps and
symmetric/Two Sides revolve caps are not yet certified. Mesh faces, ambiguous cap names,
generic index-derived names, and sketch side names based on nearest-curve heuristics are
rejected. Coplanar split pieces of one supported semantic face share
rejected. Untapered New Body extrusions additionally support line, circle and arc sides
with exact source-edge construction certificates. Ordinary face names and saved sketch or Emboss anchors retain their legacy naming; strict styles resolve separate source metadata and also require the original producing feature. All constructed pieces of the same
sketch curve share one appearance, including split circle seams; distinct coincident
curves are ambiguous and cannot be selected. Unsupported downstream modifiers remove
the certificate rather than transferring paint by proximity. Coplanar split pieces of one supported semantic face share
the configured appearance. If that lineage disappears while its body remains, Apply and
Preview reject the row atomically. There is no nearest-face substitution; later ordinary
topology edits also cannot transfer its paint to a replacement face. A suppressed owning
@@ -72,9 +76,17 @@ clearing it reveals inherited or imported paint. Body renames maintain face targ
Deleting a component or originating feature removes its configured targets and row cells.
Deleting one occurrence preserves the shared definition configuration.
Embedded STEP faces use certificates bound to the exact stored payload, source item and
original STEP face entity. Kernel seam pieces of that same source face share the override.
Replacing the embedded payload invalidates the old face target, even when the replacement
has identical geometry or reuses entity numbers. Body renames and exact rigid placements
preserve source identity; ordinary parameter edits rebuild construction certificates.
Independent component copies duplicate mapped configuration columns, row values, and rules
without retargeting the source. Copying a strict configured face from a foreign body frozen
as an import currently fails explicitly because imported face lineage is not certified.
without retargeting the source. An independent copy of the same embedded STEP payload
preserves its source certificate under the new feature. Copying strict paint on a foreign
body that requires re-export still fails explicitly because that exporter cannot yet
certify the source-to-output face mapping.
Activation evaluates all row parameter expressions together, so column order does not create
temporary dependency cycles. Preview and activation reject new or changed geometry errors
@@ -134,6 +146,6 @@ value lists support up to 128 expressions. These bounds are checked before saved
decoded. Driven appearance/material rules and repeated fixed-point evaluation are outside
the current rule scope.
Designs saved with component or strict face styles use file format 9. Older designs upgrade on opening without
Designs saved with source-certified face styles use file format 10. Older designs upgrade on opening without
changing their existing configuration values. Older SolveCraft versions must be updated to
open newly saved designs.
+8 -2
View File
@@ -24,7 +24,7 @@ Activate a placement to author shared geometry through its frame:
{"component":3,"occurrence":4,"path":[2,4]}
```
New geometry belongs to the component and appears in every instance. The selected frame determines how world inputs become local component geometry. Planar sketches display at the active placement during authoring. Component-only activation keeps the first-placement behavior. Existing 3D wires retain their prior coordinate behavior; their mixed legacy coordinate storage needs a separate migration before occurrence authoring can apply consistently.
New geometry belongs to the component and appears in every instance. The selected frame determines how world inputs become local component geometry. Planar sketches and new 3D wires display at the active placement during authoring. Component-only activation keeps the first-placement behavior. Format 10 stores an explicit World or Component coordinate marker for 3D wire samples and fit points. Older drawn and detached wires retain their world positions; retained Include and surface producer links keep their component meaning, including lost references. Breaking a link preserves its explicit marker. Activate the desired occurrence before supplying world inputs to an explicit sketch owned by a repeated, nonactive component.
Visibility is an independent view setting for exact placements. Hide a path and all descendants with `browser.visibility`:
@@ -44,4 +44,10 @@ Configuration columns, row values and internal rules are duplicated for copied t
A body reassigned from an external component receives an independent BaseFeature before the first copied feature that modifies it. Copied modifiers then replay once. The command reports these frozen bodies. Public user parameters remain design-wide; retained external sketch, project and feature links are reported. Joints and motion records wholly inside the copied occurrence graph receive new references. Records crossing its boundary are omitted with notices.
Copy evaluates on a scratch document, checks that original bodies remain unchanged, and verifies copied body measurements and sampled material occupancy before adopting it. Unsupported cross-boundary destructive operations, configured foreign faces without certified semantic lineage, reassigned mesh bodies, rolled-back timelines and exceeded work limits return errors without a partial copy. A successful copy selects the new occurrence, preserves your active component and unrelated pending positions, and places the copy under the chosen parent occurrence path. Activate the new occurrence to author features in it. Existing 3D sketch wire coordinate behavior is copied unchanged.
Copy evaluates on a scratch document, checks that original bodies remain unchanged, and verifies copied body measurements and sampled material occupancy before adopting it. Unsupported cross-boundary destructive operations, configured foreign faces without certified semantic lineage, reassigned mesh bodies, rolled-back timelines and exceeded work limits return errors without a partial copy. A successful copy selects the new occurrence, preserves your active component and unrelated pending positions, and places the copy under the chosen parent occurrence path. Activate the new occurrence to author features in it. Paste New preserves each 3D wire's World or Component marker and stored coordinates: Component wires follow the copied placement, while World wires retain their physical world positions.
Create Components from Bodies and Move Bodies to Component now add ownership-transfer features at the current timeline position. Earlier joins, cuts and face selections keep their original component frames. At the transfer, geometry converts once into the destination frame; later features authored there operate on the transferred body. Rolling the timeline back before the transfer displays the original owner. Body materials and face identity survive the transfer, and an inherited source-component appearance becomes a body override to preserve its visible look.
Transfers preserve the body's world pose through rotated or translated parents. Pending positions on the involved source and destination paths are captured atomically with the transfer so save/reopen retains that pose; unrelated pending positions remain pending. Undo and checkpoint restoration recover the original pending positions as well as the feature history; redo restores the captured transfer. The operation requires one source and one destination placement. Shared instance definitions with several placements are rejected because a single ownership change cannot preserve several different world poses. A component that supplies transfer history outside its subtree cannot be deleted until that dependent history is removed.
Older files without transfer features keep their saved assignment and offset behavior. No transfer timestamp is inferred from their final ownership map. Paste New freezes externally authored geometry after its successful entry transfer and remaps internal transfers, then replays later modifiers once. All transfer commands validate and evaluate on a scratch document before adoption.