Commit Graph
1629 Commits
Author SHA1 Message Date
aj 855d686a6a docs(expand): describe cancelling a long Expand Spacing search 2026-10-14 20:39:58 -04:00
aj b7779904f6 feat(desktop): add Cancel to Expand Spacing
Expand Spacing ran its search on the UI thread, so a complex layout froze
the app for minutes with no way out. Run the search on a worker; when it
lasts past 0.3 s, show a small modal window with elapsed time and Cancel.
Cancel, Escape and the close box request cancellation through the
Expander token and the window stays open until the worker stops, so the
layout is never touched afterward. A cancelled run moves no part and
reports it in the status bar instead of the "select two parts" notice.
2026-10-14 20:39:58 -04:00
aj f9e3c361b4 fix(cutoffs): trim lines through clearance-outline vertices to the part
A cut-off line passing exactly through a vertex of the clearance outline
got duplicate intersection hits and fell back to the part's bounding box.
Automatic strip lines sit on a 0.05 lattice that often lands on such
vertices, and the strip search preferred them because the box fallback
measured as less cutting, so planned cut-offs looked box-trimmed while a
slightly moved manual line was trimmed correctly.

Slice the polygonal clearance outline exactly with half-open edges:
crossing vertices count once, touching vertices zero or twice, edges on
the line are excluded whole. Zero clearance and non-polygon outlines keep
the existing path and its conservative fallback.
2026-10-14 20:18:32 -04:00
aj 8834abc854 fix(desktop): pick up a drawing on mouse down in the parts list
Choosing a part from the editor's drawing list armed the pickup only in
Click. Moving the mouse more than 3 px before release started a
drag-and-drop, which takes mouse capture, so the list never raised Click
and nothing attached to the cursor on the plate.

The list now raises DrawingPickedUp on a single left press over a row
and the editor arms the pickup there. Dragging onto the plate still
drops a part at the release point; a completed drop clears the pickup so
a second copy does not follow the cursor. Presses below the last row,
right presses and the second press of a double-click do not pick up.
2026-10-14 16:11:23 -04:00
aj 720c3d9b7a fix(desktop): allow pixel rounding in cutoff drag test
The Windows run 38614147947 failed ActiveCutOffDragNeedsLeftMotionAndEndsAfterSelectionClears because a screen-space drag to world X=11 rounded to X=10.96. Assert bounded movement, then verify the released coordinate stays unchanged.
2026-10-14 14:23:52 -04:00
aj e8c0eea0b0 test(desktop): guard cutoff drag mouse lifecycle 2026-10-14 14:19:08 -04:00
aj bf8ca19ce5 fix(desktop): finish cutoff drag and regenerate after mixed delete 2026-10-14 14:10:39 -04:00
aj 21d38beb53 fix(desktop): select cut-offs with plate windows 2026-10-14 14:10:39 -04:00
aj 18be8a2c81 Match cutoff and remnants icons to cutting toolbar 2026-10-14 13:50:50 -04:00
aj efc2b73709 Add cutting action icons and toolbar shortcuts 2026-10-14 13:50:50 -04:00
aj 1d745d20ba feat(desktop): draw cut-off lines as a prominent orange-red dash
Cut-off scrap lines were a solid 1.5px near-black stroke that read like
another sheet/part outline. They now render as a 2px orange-red dash so
operators can spot scrap cuts at a glance, and the manual cut-off preview
is recolored to match the applied line. Selected cut-offs keep their solid
blue highlight.

Add bitmap regression tests (CutOffDisplayTests) that verify the dashed
orange style, the dashed gaps, and the unchanged selection highlight.
2026-10-14 12:01:11 -04:00
aj 74f32f0516 fix(nests): keep etch marks when clearing lead-ins of PEP nests
PEP-converted nests stored etch marks only in each placed part's locked
cutting program; the drawing program held the contour cuts alone. Because
Remove Lead-ins rebuilds a part from its drawing, clearing lead-ins also
erased the marks from every part.

Recover the marks while reading the nest: when a drawing has no scribe
moves and every placement that kept its saved program carries the same
marks, add them to the drawing in its own frame and refresh that drawing's
clean placements. Saved programs are never rewritten, drawings that already
have marks are untouched, and drawings whose saved programs disagree are
left alone rather than guessed at.
2026-10-14 06:58:24 -04:00
aj 6424512e8c fix(expand): distinguish open-path material entry from bounds 2026-10-13 22:34:21 -04:00
aj 27f8c9799b fix(expand): measure open cutoff segments and refuse uncertain curved gaps 2026-10-13 22:11:12 -04:00
aj 775ece5d21 fix(expand): certify disk and cutoff paths and report invalid input 2026-10-13 21:49:28 -04:00
aj cad1083287 test(expand): bound pinned relaxation passes 2026-10-13 21:31:57 -04:00
aj 4183af4142 fix(expand): retain convex exits and report tiny clamp overlap 2026-10-13 21:31:57 -04:00
aj 73be301ebf test(expand): verify cancellation after scratch movement 2026-10-13 21:31:57 -04:00
aj fdc6f074ee fix(expand): distinguish part blockers from plate edges 2026-10-13 21:31:57 -04:00
aj dc4b07ddf5 fix(expand): separate parts touching cutout walls 2026-10-13 21:31:57 -04:00
aj 6c76617905 fix(expand): clip translations against material along their path 2026-10-13 21:31:57 -04:00
aj 43e08965b9 fix(expand): preserve entry clearances and retry blocked pairs 2026-10-13 21:31:57 -04:00
aj ddd1e422be feat(cutoffs): cut sheet-separating cut-offs after every part 2026-10-13 21:09:35 -04:00
aj b9a387b517 feat(desktop): choose cutting-planner cut-off settings in the automatic cut-off dialog 2026-10-13 20:55:24 -04:00
aj 9f2ece37ed feat(desktop): add automatic cut-offs, existing-work banner and clear button to the cutting planner 2026-10-13 20:39:43 -04:00
aj 81cccfc610 feat(cutoffs): stage revertible automatic cut-offs and clear applied cutting work 2026-10-13 20:39:43 -04:00
aj c107ab13f7 fix(cutoffs): preserve exact integral scores in strip search
Avoid shortest round-trip decimal text for already-integral doubles. The failing tie regression and the independent 9,163-case exact-integer sweep now keep the fewer-pierce result.
2026-10-13 20:12:44 -04:00
aj 57450ecea8 fix(cutoffs): honor candidate budget and truthful cut-length ties
Reserve nominal-line slots in the candidate lattice, compare rounded lengths in exact micro-units before pierce ties, and report real fixed-grid cut length. Per-line notices name local increases instead of negative savings. Failing-first regressions cover dense spacing, decimal ties and the legacy summary.
2026-10-13 20:01:48 -04:00
aj b245290664 test(cutoffs): verify shifted lines through apply save and rerun 2026-10-13 19:45:22 -04:00
aj 6d5d963654 feat(cutoffs): move strip lines off clamps 2026-10-13 19:41:57 -04:00
aj 178954e2df feat(cutoffs): keep existing cut-offs as strip boundaries 2026-10-13 19:41:57 -04:00
aj f63fee7392 feat(desktop): add minimum strip and cut-length summary to automatic cutoffs 2026-10-13 19:34:02 -04:00
aj 5857e7fc69 feat(cutoffs): shift strip lines to shorten cuts 2026-10-13 19:29:32 -04:00
aj 15055aef4d feat(cutoffs): measure a cut-off line without building its program 2026-10-13 19:29:32 -04:00
aj c57e0ded83 fix(diagnostics): keep tiny clamps beyond coarse chords in the overlap check
Check Overlaps dismissed a tiny clamp by the part's coarse material bounds
before the fine tolerance-free test ran, but that material is inscribed at
the 0.001 chord tolerance: real material in the sliver beyond a convex arc
(a short arc cap, a rotated crescent) lay outside those bounds and the clamp
read as clear. For clamps below the tolerance the bounds are widened by the
chord tolerance before rejecting.

PM 407f5eb7-329f-41e4-947e-64ad52aa4034 (review s6-delta3-review.md)
2026-10-13 18:15:50 -04:00
aj f2cc471a33 fix(clamps): test tiny clamps against both arc flattenings
Circumscribing every arc holds all material along convex arcs but drops a
sliver along concave ones (a notch), so a tiny clamp 6e-7 into the material
beside a notch read as clear. Tiny-clamp checks now test the part flattened
both ways (all arcs inscribed, all arcs circumscribed): along any arc one of
the two holds the real material, so together they find every real overlap.

PM 407f5eb7-329f-41e4-947e-64ad52aa4034 (delta review s6-delta2-review.md)
2026-10-13 18:15:50 -04:00
aj 07cba5719f fix(io): write an empty sheet whose rail differs only in removal time
The writer's sentinel rule compared zones only, so an empty sheet following
a rail that differs from the default only in clamp removal minutes was
dropped on save although ChangePlateDefaults treats it as configured stock.
The rule now also requires the sheet to follow the default rail itself.

PM 1469b4e0-dc59-416b-8118-560b726aa1e1
2026-10-13 18:15:50 -04:00
aj 9df9a802cd fix(clamps): flatten part material conservatively for tiny clamps
Fine inscribed flattening still let a native arc cut 6.2e-7 into a 1e-5
clamp unseen: less than one chord's sag, so the layout check, interactive
fill and Check Overlaps all called it clear. Tiny-clamp checks now
circumscribe perimeter arcs and inscribe cutout arcs (lines stay exact), so
the polygons hold every bit of real material. Any real overlap is reported;
the cost is a possible report within the tolerance of an arc, never a false
clear. The analyzer builds the same polygons instead of a second
OverlapMaterial read.

PM 407f5eb7-329f-41e4-947e-64ad52aa4034 (delta review s6-delta-review.md)
2026-10-13 18:15:50 -04:00
aj 1bcead4b3a fix(io): write empty clamp sheets whose spacing differs from the defaults
The writer omitted an empty rail sheet when its size, quadrant and zones
matched the defaults, ignoring spacing, so a sheet left at the old part or
edge spacing after a defaults change (configured stock under C17) was
dropped on save. The comparison now includes edge and part spacing.

PM 455f6763-f0aa-40da-b9ad-11de4b2ea95b
2026-10-13 18:15:50 -04:00
aj d9273c889f fix(io): keep a sheet's own clamp rail and its removals through save and reload
Commit can attach the stock's rail to a sheet whose nest has no (or another)
default rail, but only the default rail was saved and the reader re-attached
sheets only to it, so the removed clamp and its time vanished on reload. A
sheet following a rail other than the default now saves it in an optional
per-plate clampRail (read leniently, omitted otherwise), and the reader
re-attaches the sheet to it.

PM 22daec3d-dabb-4aae-95f7-c1d090d5dcdf
2026-10-13 18:15:50 -04:00
aj 4226c0f902 fix(engine): find the fewest clamps to remove, not only neighbouring runs
Recovery only tried contiguous runs of clamps, so a part with a notch over
a middle clamp had all three clamps removed although the two outer ones
were enough (D8: 'the fewest clamps that let it fit'). One probe per clamp
now finds the clamps every removal must include (a part that cannot fit with
only that clamp left needs it off; removal is monotone), and the search
tries every set by size, mandatory clamps plus the optional ones nearest the
origin first. Full-sheet parts resolve with one probe per clamp.

PM 3df03af2-35a6-49c2-9082-fc6208f5b708
2026-10-13 18:15:50 -04:00
aj 6908e00969 fix(clamps): judge tiny clamps against the part's real material
The tolerance-free rectangle test was fed approximated material: the layout
check passed it the 1e-4-grid validation outline (a strip of real material
that wholly contains a 1e-5 clamp could vanish), and interactive fill and
the overlap check passed 0.001 inscribed arc chords (a clamp inside a disk
but outside its chords read as clear). All three now flatten the native
contours at a quarter of the clamp's smaller side, lines kept exact, so the
arc-chord sliver can never hold the clamp. Ordinary clamps are unchanged.

PM 407f5eb7-329f-41e4-947e-64ad52aa4034
2026-10-13 18:15:50 -04:00
aj e38980e54b docs(clamps): describe last-resort clamp removal and current clamp coverage
automatic-nesting.md still said interactive fill/push, the overlap check and
cutoffs ignore clamps, and nesting-engines.md listed the large-spacing and
tiny-zone defects fixed in this slice. Both now describe current behaviour,
and the new last-resort removal section states its limits (1000-probe budget,
sub-grid clearance) as settled with the user (plan D12-D15).
2026-10-13 18:15:50 -04:00
aj a1914e147a fix(engine): reuse clamp-removal probes across identical stock
Offering several identical sheets (same size, spacing and clamps) multiplied
every feasibility probe, so eight full-sheet parts on four 48x120 options
with the eight-clamp rail spent the 1000-probe budget and recovered nothing
although each part fits with its clamps removed. A probe's answer is now
reused for the same part, engine and physically identical stock.

Delta review (s3b-delta-review.md) policy gate 3; PM 0e655fdb-a99a-40d8-968a-1863d8068c3e
2026-10-13 18:15:50 -04:00
aj 64ebda2f6f fix(engine): let clamp recovery move on to another stock with sheets left
Each blocked requirement was tied to the one stock where it needed the
fewest removals; once that stock's finite pool ran out the part stayed
unplaced even with another offered stock untouched. Recovery now runs in
rounds: a blocked part with demand left takes its best removal among the
stocks it has not tried that still have sheets (that stock's own minimal
run, C11). A variant used in several rounds stays one stock entry.

PM bf4438ac-929a-405f-ba26-fcfaa9b1c55e
2026-10-13 18:15:50 -04:00
aj 360f58c101 fix(engine): record a committed clamp removal whatever the target sheet holds
SyncClampZones returned early when the empty target already held exactly the
solved reduced zones, and otherwise preferred the target's own rail over the
stock's, so a removal committed onto such a sheet kept no rail, removed ids
or time. The stock's rail now wins, and the rail/removal state is reconciled
even when the zones themselves need no replacement.

PM 60f7a673-455e-4a87-b865-a4806f417ee6
2026-10-13 18:15:50 -04:00
aj 6fc1a0ebdc fix(core): move an untouched trailing sheet to new nest defaults
Changing the nest defaults (Nest Info, Set as default, Edit Plate on an
empty sheet) left the editor's trailing empty sheet on the old size and
quadrant, so the writer's clamp-preserving empty-sheet rule saved it as a
stale extra sheet. PlateManager.ChangePlateDefaults wraps a defaults edit:
a trailing empty, cutoff-free sheet that exactly matched the old defaults
(and followed their rail with no removed clamps or explicit zones) takes the
new defaults; every other empty sheet keeps its configuration and is still
written.

PM cade6901-5f4a-4503-85bf-0ea681d9ca7f
2026-10-13 18:15:50 -04:00
aj 6b995ac40a fix(core): make a plate's removed-clamp set immutable
Plate.RemovedClamps exposed a HashSet (and every untouched plate shared one
static empty HashSet), so a downcast could change one plate's removal state
or every plate's at once without re-resolving zones. It is now an
ImmutableHashSet.

PM 6ded8ac4-84fd-4e8b-9a3b-6f41e494542c item (e)
2026-10-13 18:15:50 -04:00
aj 7ed40d4bb8 fix(core): charge removal time only for removed clamps on the sheet
Plate.ClampRemovalMinutes multiplied every listed removed id by the
removal time, including ids the rail places beyond the sheet after a resize
or does not know at all. Only removed clamps the rail resolves on this sheet
are pulled, so only those add time; the ids themselves stay listed (C13).

PM 6ded8ac4-84fd-4e8b-9a3b-6f41e494542c item (a)
2026-10-13 18:15:50 -04:00
aj 04d538b0a4 fix(io): omit removedClamps from sheets without a removal
Every plate was written with "removedClamps": [], so files without the
feature changed. The key is now omitted unless a clamp was removed, like
the other additive sections; nest-file-format.md documents removedClamps
and removalMinutes and their lenient reading.

PM 6ded8ac4-84fd-4e8b-9a3b-6f41e494542c item (c)
2026-10-13 18:15:50 -04:00