Commit Graph
1763 Commits
Author SHA1 Message Date
ajandClaude Fable 5.1 e6c87df372 perf(engine): pool best-fit pair searches by part geometry across jobs
Every Auto Nest run, and every Default-engine run, recomputed each part's
best-fit pairs: job snapshots are fresh objects and BestFitCache keyed
its entries on Drawing reference, so the Irregular engine paid
PairCatalog.Build (about half of a 118-part solve) on every run of the
same drawings.

BestFitCache now keeps a process-wide, bounded (512 sets, least recently
used first) pool of unfiltered candidate sets keyed by the exact content
of a PartGeometrySnapshot (mode and every motion value, bit for bit;
PartGeometrySnapshot.ContentComparer) and the spacing. Every drawing
DrawingJobMapper.CreateDrawing reconstructs from a snapshot declares
that geometry (BestFitCache.ShareByGeometry), so the Irregular pairs and
blocks, the cutout lattice and the Fill/Default job paths all read and
fill the pool. Candidates depend on the program geometry and spacing
alone, so a pooled set is the set the search would produce: benchmark
layouts, costs and placements are unchanged on the synthetic nests (all
engines) and on the 67-drawing, 118-part job. Failed searches are not
pooled, Invalidate leaves the pool alone, Clear empties it, and a
drawing whose Program is replaced stops vouching for its geometry.

Same 118-part job solved twice in one benchmark process (--parallel 1):
the second solve now takes 13.1 s after a 33.0 s first; before, 35.6 s
after 41.8 s.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 22:17:53 -04:00
ajandClaude Opus 5.5 13ab8e02f8 fix(cutting): plan with staged scrap cut-offs within budget
Staged cut-offs were appended after every part, so a kept order (the
"Keep the current part order" option, or the fallback after a free
search runs out of budget) always conflicted with any cut-off crossing
a part. PlateSequencing.PlaceCutOffs moves each new cut-off to just
before the first part it crosses, separators last, without moving
anything else; the panel applies it after staging.

The free search also learned "cut the cut-off first" only after a full
stall, re-planning the many-holed parts before it. A cut-off is a fixed
program that never gets harder to cut earlier, so a crossing approach
into a non-separating cut-off now teaches that rule at once. On the
reported 35-part plate this drops the plan from 23,930 expansions (over
the 20,000 budget) to 15,605.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:14:28 -04:00
ajandClaude Opus 5.5 ee8be3d79e fix(cutoffs): accept absolute arc roundoff in automatic cut-off planning
Rotated imported arcs whose start and end radii differ by ~5e-11 are
converted without refitting their centre, so their rebuilt start point
lands just outside the cached part bounds. The allowance scaled with
coordinate magnitude (4096 steps, ~2.9e-11 here) and rejected them,
which stopped Plan Cutting's "Add scrap cut-offs" with "Converted
material extends outside cached part bounds". Use the existing 1e-10
cap as an absolute allowance; larger mismatches still block planning.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 22:14:21 -04:00
ajandClaude Opus 5.5 fb505ef0ff fix(cutting): plan outlines with a seam gap before an arc, and memoize lead checks
A converted outline whose seam closes within the admitted 1e-6 gap could
only be entered at its seam: entered anywhere else, the arc after the
seam started off its own circle and every emission was refused as an
inconsistent radius. The search then spent its whole budget on that
part and the plate never planned. Emission now bridges the gap with a
straight move and cuts the arc as drawn; the verifier already admits
that slack. An entry on the seam vertex is left as before.

Each prefix of a part re-checked its earlier contours' leads against
every other part's material. One search now remembers each verdict by
the lead curve's exact bits and the material's reference, charging the
same native query budget; replay never uses it. On the reported plate
the memo alone gives a byte-identical result in 57 s instead of 12 min 47 s;
with the seam fix the plate plans Ready in about 17 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 21:21:20 -04:00
ajandClaude Fable 5.1 d317a90f1e perf(engine): cut Auto Nest time on many-part jobs
A 67-drawing, 118-part job took about six minutes through the desktop
Auto Nest path and was cancelled before any layout appeared. Almost all
of it was the cutout pre-pass, the rest the Irregular engine.

Cutout pre-pass (317 s -> 8 s on that job, same bundles and poses):
- The lattice and NFP searches prepare the frame's and the occupants'
  validation outlines once per search (NestLayoutCheck.Prepare) instead
  of re-outlining and re-triangulating the frame at every candidate, and
  test candidates against the small occupants before the frame. Answers
  match the pairwise check exactly, including its leftmost-inflated rule.
- A hole's proposal is replayed for the same frame, hole and offered
  inserts: automatic-rotation inserts ask the same question at every
  frame angle.

Irregular engine (40 s -> 15 s, benchmark 42 s -> 19 s, same layouts):
- Concave no-fit polygons are built as the union of pairwise convex sums
  of each footprint's convex pieces (ear clipping plus Hertel-Mehlhorn
  merging on the Clipper lattice) instead of n*m edge-pair quads; a
  footprint that cannot be decomposed keeps the old sweep.
- Pair and block catalogs share one private drawing per part geometry,
  owned by the engine instance, so each part's best-fit search runs once
  per instance and across a pipeline's trial and ordinary solves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-10-18 21:13:15 -04:00
ajandClaude Opus 5.5 f26c75ada5 feat(ui): let Drawing Properties return a custom color to automatic
Drawing Properties now says whether the drawing's color is custom or comes
from the color scheme, and an Automatic button clears the custom color. On
save the drawing gets its palette slot back through RecolorDrawings when the
nest is known, otherwise by its non-cutoff index.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:30:18 -04:00
ajandClaude Opus 5.5 f009fab31d feat(ui): make color schemes app-wide and keep only hand-picked drawing colors
- Add Drawing.HasCustomColor, set when a color is picked in Drawing
  Properties or comes from a library record with a stored color.
- Persist it as customColor in .nest files (omitted when false) and keep it
  out of drawing packages; split pieces inherit it.
- Recolor non-custom drawings from the active palette when a nest opens and
  when the scheme changes; custom colors keep their palette slot.
- Library settings store a color only when it is custom.
- Document drawing colors in nest-file-format.md and nesting-view-colors.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:24:33 -04:00
ajandClaude Opus 5.5 d548ba4e6f feat(ui): add a Simulate Cutting toolbar button
Restore the toolbar shortcut for Plate > Simulate Cutting next to Plan
Cutting, using the cut_simulate icon.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:15:41 -04:00
aj 87b6d7ee90 Revert "fix(ui): make part fills, labels and the cut trail easier to read"
This reverts commit 66afea5a51.
2026-10-18 20:14:18 -04:00
aj 9d68945e75 Revert "feat(ui): make Blueprint the default color scheme"
This reverts commit c875edcdd1.
2026-10-18 20:14:18 -04:00
ajandClaude Opus 5.5 c875edcdd1 feat(ui): make Blueprint the default color scheme
- Add the Blueprint scheme: navy canvas, pale blue sheet, dark navy part
  outlines, orange-red rapids and twelve distinct, readable part fills.
- Use it as the settings default and the fallback for unknown scheme names,
  and list it first in Options. Saved scheme choices are kept.
- Run the palette spacing and readability tests over Blueprint and Classic.
- Document the default in nesting-view-colors.md.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 20:04:41 -04:00
ajandClaude Opus 5.5 66afea5a51 fix(ui): make part fills, labels and the cut trail easier to read
- Replace the Classic part palette with twelve clearly distinct fills that
  stay readable with black IDs and clear of etch green; darken the canvas.
- Pick black or white part-ID labels by fill luminance; drop the underline.
- Give the cut simulator trail a pale casing so it shows on warm parts.
- Number plates in the status bar the same way as the plate header.
- Add ClassicPaletteTests covering palette spacing, contrast and labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:26:40 -04:00
ajandClaude Opus 5.5 d1aa056b9b fix(ui): keep the cut simulator smooth while panning and zooming
The overlay re-stroked the whole finished trail on every paint: about
275 ms at zoom-to-fit on a 392-part plate and over 11 s zoomed in, where
dashed rapids spanned millions of on-screen dashes.

The finished trail is now cached in a bitmap at the current scale, so a
pan or playback frame blits it and draws only the moves since. A wheel
zoom stretches the cached image until the wheel has been still for
150 ms, then redraws it sharp. When the trail would be too large an
image, each paint draws only the moves on screen and clips straight
rapids to the view. Arcs are added as GDI+ arcs instead of 5-degree
polylines.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 19:08:08 -04:00
ajandClaude Opus 5.5 bbe0f17a64 feat(ui): allow clearing lead-ins and cut-offs while a cut plan runs
The Clear Lead-ins & Cut-offs button stays enabled during planning.
Confirming cancels the running plan, clears once the cancellation lands
so the plates never change under the planner, then replans.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 18:45:31 -04:00
ajandClaude Opus 5.5 78ca08efe1 feat(reporting): show estimated cut time in nest reports
The nest report PDF gains an estimated cut time: the job total on the
summary, an Est. cut time column in the plates table, and per-plate and
all-copies times on each plate page. Times come from the cut simulation
with the settings last used in Calculate Cut Time, plus clamp removal.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:40:33 -04:00
ajandClaude Opus 5.5 d3cb23f117 fix: time display-layer cuts, add hole feed and etch skipping
The cut simulation treated Display-layer contour moves (what cutting
strategies emit) as head-up travel, so plates with assigned lead-ins were
timed as rapids. They now cut, matching the verifier and posts, and
suppressed moves are left out.

Cut time now follows the CI Fiber post: closed clockwise contours and
cut-offs take an outside feed, other contours a hole feed, and etch-only
contours can be skipped like its SkipScribe default. The settings are
shared by Calculate Cut Time and the simulator, and plate/nest times now
always come from the simulation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 17:32:38 -04:00
ajandClaude Opus 5.5 095b4d6e72 feat: time cuts with machine acceleration limits
A Grbl-style lookahead planner re-times the cut simulation with
trapezoidal acceleration, junction-deviation corner speeds and a
centripetal cap on arcs. Machines gain cut/rapid acceleration and corner
deviation in Machine Configuration, with placeholder values until the
controller's are entered. The simulator and Calculate Cut Time pick the
machine (or full speed), and the simulator shows the live head speed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:36:43 -04:00
ajandClaude Opus 5.5 530456a91b feat(ui): add a cut simulator for plates
Plate > Simulate Cutting replays the active plate in cutting order: the
torch traces cuts, rapids and pierces timed like Calculate Cut Time, with
play/pause, scrubbing, 1x-250x speed, step and part/cutout jumps. Parts
the torch has not reached are drawn muted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 16:27:32 -04:00
ajandClaude Opus 5.5 dd2c00aed4 perf(engine): replay cutout pre-pass clearance checks and trim hole subtraction
Profiling the cutout pre-pass on real round-part jobs put ~97% of its time in
the frame-wall NestLayoutCheck.Clears inside CutoutCirclePacker.Fill. Ear-clipped
round frames make every perimeter/insert triangle pair overlap, so a clear pair
runs hole subtraction for every pair. The same question repeats for every frame
angle and repeated frame instance, because Automatic inserts get identical
frame-local poses.

- CutoutMemo, one per Prepare, replays geometry reads, circle items and Clears
  answers. Keys hold geometry by reference, pose bit patterns, argument order
  and spacing. It is threaded through CutoutCirclePacker.Fill and the router's
  round-only path.
- TriangulatedRegion.SubtractAllHoles measures each piece's bounds once, skips
  holes and hole triangles that no piece reaches, and ping-pongs the remainder
  between scratch buffers instead of copying it into pooled ones. Clip
  arithmetic and order are unchanged.

Bundles are byte-identical on 14 real and 10 synthetic ring jobs. Pre-pass time
over the real set drops from 99.6 s to 10.1 s (N0414-02 35.8 s -> 0.6 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 15:36:02 -04:00
ajandClaude Opus 5.5 f01b2cec67 perf(engine): speed up round cutouts and re-plan Circles' last sheets
- The cutout router uses the circle packer alone for a round hole whose
  inserts are all round. Lattice and NFP never placed more there, and when
  demand exceeded what fit they spent 20+ minutes on one job.
- The cutout pre-pass skips a hole whose area is smaller than an insert's
  outline, so bolt holes no longer run the searches.
- Circles re-packs its last sheet, and its last two sheets together, onto
  each single stock and keeps the result when the whole job gets cheaper.

On 14 real round-part jobs costs are unchanged and pipeline time drops from
262 s to 144 s for Circles and 355 s to 245 s for Default.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 14:54:01 -04:00
ajandClaude Opus 5.5 0e4fd5f90f fix(mcp): name FlatBar in the autonest engine description
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:29:27 -04:00
ajandClaude Opus 5.5 278252fe79 feat(console): allow multi-sheet autonest with --max-sheets and --stock
--autonest can now use more than one physical sheet. The first layout
replaces the target plate's parts, further layouts are inserted as new
plates after it, and --stock offers explicit sheet sizes (with optional
costs) built from the target's spacing, quadrant and clamp rail.
NestPipelineCommit gains ApplyToPlates for callers without a
PlateManager. Per-sheet results and overlap checks cover every
committed plate.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 13:27:14 -04:00
ajandClaude Opus 5.5 b115b9dcb0 feat(ui): add Halloween, Christmas and 4th of July color schemes
Built-in festive schemes theme the background, sheet and accents while
keeping 12-color part palettes distinct, light enough for black part IDs
and clear of the green etch stroke. They are only applied when chosen;
there is no automatic seasonal switching.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 9f2e3d5291 feat(engine): compare clamp-hit dropping with filling past the clamp strip
Dropping the parts that land on a clamp suits small parts, which fill the
gaps between clamps. Large parts often do better if the fill area stops
short of the clamps. The rows still fit, and no part is lost on a clamp.

When every clamp in the fill area lies on one edge, interactive Fill now
also fills the area with that edge moved just past the clamp keep-outs,
as a larger edge spacing would. It keeps whichever layout the strategy's
comparer ranks better, and a tie keeps the dropped-parts layout. Clamps
on more than one edge skip the comparison. The second fill reuses the
cached best-fit pairs. While it runs, a preview counts as the new best
only when it beats the first layout, so the preview never gets worse.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 05aac952ba feat(engine): fill clamped plates ignoring clamps, then drop clamp hits
Interactive Fill on a plate with clamps used to split the plate into
clamp-free rectangles and fill each one separately. It showed no progress,
so Accept did nothing until the end, and Stop discarded the result. Packing
around the clamps also tends to give a worse layout than losing the few
parts that land on them.

FillItem and FillGroup now fill the area as if there were no clamps. They
then drop each part that enters a clamp keep-out or sits too close to an
existing part, using the same check as before. For a multi-part group, the
whole copy is dropped when any member fails. Progress previews are filtered
by the same check, so a layout accepted early is clamp-clear. A quantity
request that loses copies asks for that many more, up to two more times.
Pack and whole-plate Nest still pack only into the clamp-free areas.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 859d10b31d feat(engine): offer a box layout before best-fit pairs in Fill
Interactive Fill ran the best-fit pair phase first. The first pair
computation for a drawing can take about a minute, and until it finished
the progress dialog showed no layout, Accept stayed disabled and the
status text did not change.

The fill now packs the part boxes (RectBestFit) before the pair phase and
reports that layout, so Accept is available at once. The layout is only a
fallback: strategies still run in their usual order, and a completed fill
picks the same winner as before. While the pairs are computed, the detail
line reads "Computing best-fit pairs (may take a minute)...". Accept or
Stop now stops the wait. The computation keeps running in the background
and is cached for the next fill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 de845a5818 feat(engine): add Circles engine for round parts
Circles packs every part as its minimum enclosing circle at centers tangent
to two of the work-area walls, placed discs and clamp keep-outs, bottom-left
and left-bottom, with hexagonal and square lattice seeds. It bids only when
every part fills at least 0.8 of its enclosing circle and otherwise returns
everything unplaced at once. Default runs it as a third candidate.

Rectangles' sheet-by-sheet stock loop moves to NestingEngines/SheetByStock
(Rectangles output unchanged) and Default's candidate scoring and commit
forwarding become shared helpers. Circles also runs the whole job preferring
each offered stock and keeps the best result. Contract tests take shapes an
engine can override.

Synthetic round jobs, salvage-credited: Circles wins or ties all six with
valid layouts; Default cost falls about 4% versus Irregular alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:48 -04:00
ajandClaude Opus 5.5 a430da89d0 feat(engine): nest round frames inside larger round frames
The cutout prepass now bundles frames smallest first, so a larger frame's
round cutout can take a ring part or an earlier bundle as one insert through
the circle packer: a flange holds a washer that holds a smaller washer that
holds a slug. Chains stop at four parts deep. Lattice and NFP proposals never
take these inserts, since they could seat a part in a ring's bore.

Expansion and released demand recurse, so placed order cuts innermost first
at every level and an unplaced outer frame returns its whole chain to demand.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 f3a6af7f09 feat(engine): pack round inserts into round cutouts as circles
Add CutoutCirclePacker, a circle-in-circle proposal for the cutout
router. When a cutout is one circle and every insert fills at least 0.8
of its enclosing circle, it packs the inserts largest first at centers
tangent to the wall or placed discs, trying a center-out pass (a single
insert sits concentric) and a wall-first pass (optimal counts for up to
nine equal discs). Every pose passes NestLayoutCheck.

The router runs it first and skips the lattice and NFP searches when it
places all demand; otherwise the higher count wins and existing
proposals keep ties. On synthetic disc jobs the prepass drops from
minutes to seconds and places as many or more inserts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 2174416dcc feat(engine): model any part as a circle for circle packing
Item.Create builds the circle packer's view of a part: the minimum
enclosing circle of its outward-flattened perimeter (padded by the
layout check's flattening allowance), its fill ratio, the offset back
to the part origin, and the largest disc clear of material inside its
cutouts. Gears and sprockets pack by their tip circle around their
bore; the fill ratio lets a future engine decide which jobs to bid on
instead of a yes/no round test.

Adds MinimumEnclosingCircle (Welzl, repeatable order) to Core geometry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 6e2e27d6fc fix(engine): stop staggered circle fills overlapping
Staggered stripes were spaced only so adjacent stripes touched
diagonally. When the in-stripe pitch stretched past sqrt(3)*D, stripes
two apart, which sit directly over each other, came closer than a
diameter. Clamp the stripe spacing to at least a radius in both fills.

FillEndOdd also divided by zero when a single circle fit per stripe;
it now stacks those stripes a diameter apart. FillEndEven now clones
the template item, so placed circles keep its radius instead of zero.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 12:49:36 -04:00
ajandClaude Opus 5.5 d87302a189 feat(cad): exclude entities and set cut/etch/display-only roles
Select entities in the CAD converter (click, or drag a window/crossing
box) and right-click to exclude/include them or set them to cut, etch or
display only, regardless of their DXF layer. Delete excludes the
selection.

Roles are stored per source entity on the drawing and persisted in the
entity set as an optional `roles` map. Display-only geometry is kept out
of the program, so posts, nesting and verification never see it; placed
parts draw it as a dashed overlay. Load-time scribe repair skips
etch-layer entities set to cut. Per-entity exclusions now survive filter
changes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 05:14:55 -04:00
ajandClaude Opus 5.5 27a03b9caf feat(engine): add FlatBar nesting engine for flat bar stock
Reads each stock as a bar and cuts parts in one row along its length, packing
part lengths with a port of the CutList saw cut-list packer (first-fit
decreasing with swap optimization, exhaustive search for small jobs) plus a
best-fill subset-sum candidate. Each part is packed at its length less its
measured self-nesting gain, and a slide-left compaction pass nests shaped ends
(turning alternate mitred parts) and refills the freed length. Every slid pose
is confirmed with NestLayoutCheck.Clears.

On five synthetic flat-bar jobs every layout is valid and complete; total cost
33696 vs Rectangles 36816 and Default 34080.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:54:48 -04:00
ajandClaude Opus 5.5 0186ccfbff feat(nest): keep parts out of tabbed cutouts
A tabbed cutout's slug stays attached while the sheet is cut, but nesting
saw a closed hole and could place parts inside it. Nesting and layout paths
now read material through NestingMaterial.ForNesting, which drops closed
contours with tab spans so the slug counts as part. That covers part
outlines and collision lines, the cutout router, fill expansion, best-fit,
NestLayoutCheck and the GPU bitmaps. Area, overlap diagnostics and cutting
keep the hole, and programs without tabs read exactly as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 01:14:22 -04:00
ajandClaude Opus 5.5 ba39c3dc55 feat(cad): add tabbed cutouts with draggable tabs
A hole can now be declared a tabbed cutout in the CAD Converter: pick a
circle or any edge of a closed hole, set the tab count and width, and drag
the tabs around the hole. The definition persists on the drawing and in the
nest file, and stays editable from the source entities.

The builder replaces the hole with open cut pieces and uncut spans on a new
Tab layer. Tabs are material, so area, nesting and overlap checks still see
a closed hole, but they are never cut. Plan Cutting and Assign Lead-ins cut
each piece from the slug with the internal lead-in and no lead-out. A lead
that would reach back over a tab is mirrored, and an arc lead onto an arc
pierces straight in. Planning accounts for each span between tabs and runs
the open-cut proof, so its own tabbed cutouts certify; tabs followed by a
lead-out are still refused. Pre-post review flags programs that still
contain tab motions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:50:11 -04:00
ajandClaude Opus 5.5 6cdda38d35 fix(verify): pass tabbed cutouts that provably retain their slug
A cutout cut in several pieces around tabs, as PEP programs often are, made
pre-post review report every piece's lead-out and the part's open fragments
as incomplete. Review now proves such open cuts release nothing: within the
part they touch other cuts only at their own ends and form no loop (each
closed contour with its leads counting as one point), and leads at open ends
stay out of the gap beyond them. Anything else stays incomplete. Plan Cutting
keeps refusing to certify its own tabs followed by a lead-out.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-18 00:15:06 -04:00
ajandClaude Opus 5.5 3672697cb2 fix(ui): fill tabbed cutouts as one hole
A cutout cut in pieces around tabs is a set of open cut figures. Filling the
cut outline closed each piece with a chord, drawing a slanted bridge across
the hole. The fill path now rejoins open figures across their tab gaps, and
parts with open cuts use it for drawing, hit-testing and the lead-in overlay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 23:40:11 -04:00
ajandClaude Opus 5.5 af65cb178b feat(ui): remember status-bar location mode as a user setting
Clicking the location label now saves the mouse-follow/click-only choice
to StatusBarLocationFollowsMouse (default true), so it survives restarts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 23:13:02 -04:00
ajandClaude Opus 5.5 4176e9d89a perf(ui): throttle status-bar location and follow the mouse by default
Mouse-follow mode set the auto-sized location label on every MouseMove,
relaying out the whole status strip and slowing the UI. Updates now run
at most every 100 ms with a trailing update so the label settles on the
final point. Mouse-follow is now the default; clicking the label still
toggles click-only mode.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 23:11:08 -04:00
ajandClaude Opus 5.5 766584633e refactor(ui): redesign Edit Drawing dialog
Rebuild the dialog as a two-column layout: a larger preview with a
color swatch, a Change Color button and read-only size, area and
source-file details on the left; Drawing (name, customer) and Nesting
(quantity, priority, cut first) groups on the right.

Quantity shows how many parts are already nested and how many remain,
priority explains that lower numbers nest first, and cut first gets a
short description. The form now uses Segoe UI with font auto-scaling,
re-renders the preview when its size changes, selects the name on
open, and is titled "Drawing Properties - <name>".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:58:50 -04:00
ajandClaude Opus 5.5 8f73704bef feat(server): migrate v4 drawing library data to schema v5
The v4 upgrade now keeps existing library data: each distinct package
blob is stored once by hash, every revision and current row is copied
with default nesting settings, and the v4 drawing tables are dropped,
all in the migration transaction. Pre-v4 databases get the v5 tables
directly.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:52:25 -04:00
ajandClaude Opus 5.5 5a374aa3f4 feat(library): content-addressed packages and editable nesting settings
Schema v5 stores each distinct drawing package once in drawing_packages,
keyed by SHA-256; revisions point at it, so details, settings, archive and
restore revisions add no blob. The v4 drawing tables are replaced outright
(no production library existed); nest tables are untouched.

Nesting settings (cut first, priority, rotation constraints, color) become
structured record fields (DrawingLibraryRecord.Settings), returned on every
read, filterable by cutFirst, editable through the metadata endpoint and
applied by LibraryDrawingInsert. Canonical packages now leave every
record-owned field at its default, so renaming or changing settings never
changes the package hash. Saving a nest drawing to the library carries its
settings into the record.

The desktop library browser gains a Cut first column and an Edit Settings
dialog that saves notes and settings as a new revision with the same package.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:47:18 -04:00
ajandClaude Opus 5.5 42d99f296c feat(sequencing): add per-drawing Cut first priority
Drawings flagged CutFirst (e.g. test squares) are sequenced ahead of
every other part: they get their own route with the chosen method, then
the remaining parts follow. Cutoffs crossing a cut-first part still
precede it. The flag is editable in Edit Drawing, persists in .nest as
`cutFirst` (omitted when false) and is kept by split pieces.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:19:03 -04:00
ajandClaude Opus 5.5 7a1a554804 fix(ui): center parts within the plate work area
Center Parts centred the parts on the whole plate, ignoring edge
spacing, so a wider clamp-side margin left the parts closer to the
clamps than the opposite edge. It now centres them in Plate.WorkArea()
via the new Plate.OffsetToCenterPartsInWorkArea, so each side keeps
the same extra room beyond its edge spacing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 22:09:07 -04:00
ajandClaude Opus 5.5 3541249441 refactor(ui): collapse MainForm menu delegators
Adds WithActive for handlers that only forward to the active nest
document and collapses 32 of them to one line. The eight align and
evenly-space items share Align_Click, reading their AlignType from Tag.
Center Parts becomes CenterParts_Click and ignores a missing plate or
an empty plate instead of throwing. The hidden, disabled Paste item
loses its empty handler. SetValueForm, OptionsForm and ShapeLibraryForm
are now disposed and owned by the main window.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:16:57 -04:00
ajandClaude Opus 5.5 93d118585f refactor(ui): extract MainForm status bar binding
MainStatusBar owns the status, location, selection and plate labels and
the click-vs-move location mode. Bind(EditNestForm)/Unbind() replace the
manual PlateView subscribe/unsubscribe pairs in OnMdiChildActivate;
MainForm keeps only its overlap-menu subscription. Applying the location
mode now detaches both mouse handlers first, which also drops the old
self-assignment of the mode flag.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:14:18 -04:00
ajandClaude Opus 5.5 9b46db4891 refactor(ui): extract MainForm startup and settings services
Moves startup and settings code out of MainForm:
- PostProcessorLoader discovers posts and registers their materials.
  Each DLL now loads in isolation; a failing one is named in a startup
  warning instead of throwing out of the MainForm constructor.
- MachineSettings owns the clamp-settings and nest-defaults entry points
  and their once-per-session warnings; BomImportForm calls it directly.
- NewNestFactory creates File > New nests and their daily names;
  GetNestName is now a pure static the characterization test calls.
- MainWindowSettings restores/saves window placement and migrates the
  legacy nest template.
- UpdaterStatus owns the updater and its status-bar item.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:11:37 -04:00
ajandClaude Opus 5.5 3cae257fb1 refactor(ui): extract MainForm Auto Nest, post and storage workflows
Moves the long workflow handlers into OpenNest/Forms/Commands:
AutoNestCommand (dialog, owned modal progress, solve, validation review,
commit and result notices), PostCommand (prepare, configure, verify,
save dialog, multi-file overwrite confirmation) and NestStorageController
(database open/save/save-as with reconciliation and storage errors).

MainForm keeps the busy guards, the nesting lockout and nestingCts, and
reacts to the controller's StateChanged to lock storage settings and
saving. The characterization test now flips the controller's IsSaving
instead of the removed databaseSaveInProgress field.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 21:07:13 -04:00
ajandClaude Opus 5.5 e6b1e0308f refactor(ui): consolidate MainForm busy guards
Moves every MainForm busy predicate into MainForm.Guards.cs, built on
IsJobRunning, ViewsOf, IsPlateWorkBusy and IsNestFillBusy. Auto Nest,
Validate and Post share TryBeginPlateCommand; Clamps, Automatic Cutoffs
and Plan Cutting reuse the shared predicates. The deliberate variants
(Expand Spacing ignores busy actions; the report guard adds database
saves) keep their names and remain pinned by characterization tests.
NavigationEnableCheck now takes the lockout flag instead of
SetNestingLockout repeating its logic.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:57:26 -04:00
ajandClaude Opus 5.5 d87d113ceb refactor(ui): split MainForm into per-menu partial files
Moves members verbatim into MainForm.File/View/Tools/Nest/Plate/Status
partials (nested under MainForm.cs in the project); MainForm.cs keeps
the shell: fields, startup, overrides and the Window menu. Each file
keeps only the usings it needs. No logic changes; private member names
used by reflection-based tests are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-17 20:57:26 -04:00