Commit Graph

110 Commits

Author SHA1 Message Date
7d198f837c feat: add PlateProcessor orchestrator 2026-03-16 00:44:25 -04:00
5948dc9cae feat: add PlateResult and ProcessedPart 2026-03-16 00:43:17 -04:00
6dffd8f5ad feat: add DirectRapidPlanner with line-shape intersection check 2026-03-16 00:43:06 -04:00
29b2572f9a feat: add IRapidPlanner, RapidPath, and SafeHeightRapidPlanner 2026-03-16 00:39:34 -04:00
c1e21abd45 feat: add PartSequencerFactory
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:36:41 -04:00
edc81ae45e feat: add AdvancedSequencer with row grouping and serpentine
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:36:07 -04:00
7edf6ee843 feat: add LeastCodeSequencer with nearest-neighbor and 2-opt
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:35:19 -04:00
f568308d1a feat: add EdgeStartSequencer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:32:35 -04:00
d0351ab765 feat: add directional part sequencers (RightSide, LeftSide, BottomSide)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:27:57 -04:00
4f8febde23 feat: add IPartSequencer interface and SequencedPart
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 00:27:02 -04:00
5e346270c6 fix: delegate Fill(groupParts) and PackArea to DefaultNestEngine
StripNestEngine only overrode Fill(NestItem), so ActionClone.Fill
and Pack operations fell through to the empty base class defaults.
Now all virtual methods delegate to DefaultNestEngine.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:43:42 -04:00
4e747a8e6c fix: show strip + remnant parts together during progress updates
Wrap IProgress with AccumulatingProgress so remnant fills prepend
previously placed strip parts to each report. The UI now shows the
full picture (red + purple) instead of replacing strip parts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:31:11 -04:00
310165db02 fix: add quantity deduction and progress reporting to StripNestEngine
Nest() now deducts placed counts from input NestItem.Quantity so the
UI loop doesn't create extra plates. All inner DefaultNestEngine.Fill
calls forward the IProgress parameter for live progress updates.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:26:29 -04:00
48be4d5d46 feat: add virtual Nest method to NestEngineBase for polymorphic auto-nest
The auto-nest code paths (MainForm, MCP, Console) now call
engine.Nest(items, progress, token) instead of manually orchestrating
sequential fill+pack. The default implementation in NestEngineBase
does sequential FillExact+PackArea. StripNestEngine overrides with
its strip strategy. This makes the engine dropdown actually work.

Also consolidates ComputeRemainderWithin into NestEngineBase,
removing duplicates from MainForm and StripNestEngine.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:16:08 -04:00
4d80710b48 feat: register StripNestEngine in NestEngineRegistry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:39:25 -04:00
42d404577b feat: add StripNestEngine with strip-based multi-drawing nesting
New NestEngineBase subclass that dedicates a tight strip to the
largest-area drawing and fills the remnant with remaining drawings.
Tries both bottom and left orientations, uses a shrink loop to find
the tightest strip, and picks the denser result.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:39:01 -04:00
4baeb57e84 feat: add NestEngineInfo and NestEngineRegistry with plugin loading
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:07:59 -04:00
1bcfe5d031 feat: add NestEngineBase abstract class, rename NestEngine to DefaultNestEngine
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 21:06:28 -04:00
13b01240b1 refactor: extract SpatialQuery from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:46:14 -04:00
2881815c7a refactor: extract PartGeometry from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:44:17 -04:00
7c4eac5460 refactor: extract ShapeBuilder from Helper
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:41:40 -04:00
823320e982 fix(engine): use reverse-gap check in Compactor to handle irregular shapes
The forward bounding-box gap check (gap < 0) incorrectly skipped obstacles
for irregular shapes like SULLYS-003 whose narrow handle extends past an
adjacent part's BB edge while the wide body still needs contact detection.
Replaced with a reverse-direction gap check that only skips obstacles the
moving part has entirely cleared. Also fixed edge distance check to prevent
overshooting the work area boundary when already at the limit.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 17:29:29 -04:00
7508fbf715 refactor(engine): delegate PlateView.PushSelected to Compactor and add iterative compaction
PushSelected now calls Compactor.Push instead of duplicating the push
logic. Compactor.Push moves parts as a group (single min distance) to
preserve grid layouts. Compact tries both left-first and down-first
orderings, iterating up to 20 times until movement drops below
threshold, and keeps whichever ordering traveled further.

Also includes a cancellation check in FillWithProgress to avoid
accepting parts after the user stops a nest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:16:35 -04:00
2042c7d3f2 perf(engine): cap strip-mode pair candidates at 100 (sorted by utilization)
Strip mode was adding thousands of candidates (7600+) when the work area
was narrow. Now caps at 100 total, sorted by utilization descending so
the best candidates are tried first.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:35:30 -04:00
2af02096e0 fix(engine): pass progress through FillExact binary search iterations
The binary search was passing null for progress, so the NestProgressForm
showed all dashes during the entire search (potentially minutes). Now
each iteration reports progress — the user sees phases, part counts, and
density updating as the search runs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:30:39 -04:00
744062152e feat(engine): optimize FillExact with angle pruning and tight search range
- Track productive angles across Fill calls; subsequent fills skip
  angles that never produced results (knownGoodAngles)
- Binary search uses utilization-based range estimates (70%-25%)
  instead of starting from the full work area dimension
- Quick bounding-box capacity check skips binary search entirely
  when the plate can't fit more than the requested quantity
- Use full Fill (not rect-only) for binary search iterations so
  the search benefits from pairs/linear strategies

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:21:28 -04:00
ef12cf2966 fix(engine): Compactor treats pushed parts as obstacles for subsequent pushes
Previously each moving part only checked against the original stationary
set. Parts pushed earlier in the loop were invisible to later parts,
causing overlaps (utilization > 100%). Now each pushed part is added to
the obstacle set so subsequent parts collide correctly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:54:25 -04:00
00ee205b44 feat(engine): add Compactor for post-fill gravity compaction
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:41:29 -04:00
28fb1a1a67 feat(engine): add FillExact method for exact-quantity nesting
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:41:21 -04:00
9a17fe97d3 feat(engine): add BinarySearchFill helper for exact-quantity search
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:40:56 -04:00
45509cfd3f feat(ui): add nested dimensions and area to progress window
Show width x length and total part area on the "Nested:" row
in the nesting progress dialog, using the existing GetBoundingBox
extension to compute the extents.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 01:42:34 -04:00
3c59da17c2 fix(engine): fix pair candidate filtering for narrow plates and strips
The BestFitFilter's aspect ratio cap of 5.0 was rejecting valid pair
candidates needed for narrow plates (e.g. 60x6.5, aspect 9.2) and
remainder strips on normal plates. Three fixes:

- BestFitFinder: derive MaxAspectRatio from the plate's own aspect
  ratio so narrow plates don't reject all elongated pairs
- SelectPairCandidates: search the full unfiltered candidate list
  (not just Keep=true) in strip mode, so pairs rejected by aspect
  ratio for the main plate can still be used for narrow remainder
  strips
- BestFitCache.Populate: skip caching empty result lists so stale
  pre-computed data from nest files doesn't prevent recomputation

Also fixes console --size parsing to use LxW format matching
Size.Parse convention, and includes prior engine refactoring
(sequential fill loops, parallel FillPattern, pre-sorted edge
arrays in RotationSlideStrategy).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 01:14:07 -04:00
ae010212ac refactor(engine): extract AutoNester and reorganize NestEngine
Move NFP-based AutoNest logic (polygon extraction, rotation computation,
simulated annealing) into dedicated AutoNester class. Consolidate duplicate
FillWithPairs overloads, extract BuildCandidateAngles and BuildProgressSummary,
reorganize NestEngine into logical sections. Update callers in Console,
MCP tools, and MainForm to use AutoNester.Nest.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:51:57 -04:00
ce6b25c12a refactor(engine): simplify FillLinear with iterative grid fill
Replace recursive FillRecursive with flat FillGrid that tiles along primary
axis, then perpendicular. Extract FindPlacedEdge, BuildRemainingStrip,
BuildRotationSet, FindBestFill helpers. Use array-based DirectionalDistance
to eliminate allocations in FindCopyDistance and FindPatternCopyDistance.
Simplify FindSinglePartPatternCopyDistance to delegate to FindCopyDistance.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:51:50 -04:00
6993d169e4 perf(core): optimize geometry with edge pruning and vertex dedup
Vector implements IEquatable<Vector> with proper GetHashCode for HashSet usage.
Polygon.FindCrossing uses bounding-box pruning to skip non-overlapping edge pairs.
Helper.DirectionalDistance deduplicates vertices via HashSet, sorts edges for
early-exit pruning, and adds a new array-based overload that avoids allocations.
PartBoundary sorts directional edges and exposes GetEdges for zero-alloc access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 22:51:44 -04:00
9783d417bd feat(engine): show running ledger in progress descriptions
Linear phase shows "Linear: 12/36 angles, 45° = 48 parts" with a
running count. Pairs phase shows "Pairs: 8/50 candidates, best = 252
parts" tracking the best result seen so far. Reports on every
completion so the UI always reflects current state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:57:01 -04:00
91281c8813 fix(engine): throttle progress reports to 150ms intervals
Parallel loops were flooding the UI with per-angle/per-candidate reports
faster than WinForms could render them. Use Interlocked timestamp checks
to report at most every 150ms, keeping descriptions readable.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:51:29 -04:00
c2f775258d fix(ui): show live per-angle/per-candidate detail during nesting
Don't overwrite the Detail label with phase-level reports — let the
per-angle and per-candidate descriptions from the parallel loops remain
visible. Only clear the label on completion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:48:58 -04:00
930dd59213 fix(ui): set Description in phase-level progress reports
ReportProgress was not setting Description, so the Detail row always
showed the default em-dash. Now each phase report includes a meaningful
description, and UpdateProgress always updates the label (resetting to
em-dash when null).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:40:25 -04:00
9cc6cfa1b1 fix(engine): add volatile to AnglePredictor lock field and Models content copy
- Mark _loadAttempted as volatile for correct double-checked locking
- Add Content item to copy Models/ directory to output for ONNX inference

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:33:07 -04:00
e33b5ba063 feat(engine): integrate AnglePredictor into FindBestFill angle selection
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:28:50 -04:00
8cc14997af feat(engine): add AnglePredictor ONNX inference class
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:27:44 -04:00
eee2d0e3fe feat(training): add training notebook skeleton and requirements
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:27:41 -04:00
c466a24486 chore(engine): add Microsoft.ML.OnnxRuntime package
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:26:26 -04:00
71fc1e61ef feat(training): enable forced full angle sweep and store per-angle results
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:25:33 -04:00
8e46ed1175 feat(engine): pass per-angle results through BruteForceResult
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 20:22:38 -04:00
09ed9c228f feat(engine): add ForceFullAngleSweep flag and per-angle result collection
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 20:21:14 -04:00
eb21f76ef4 feat(engine): add AngleResult class and Description to NestProgress 2026-03-14 20:18:38 -04:00
74272bea80 feat(engine): add perimeter-to-area ratio to part features
Adds PerimeterToAreaRatio (perimeter / area) as a spacing sensitivity
indicator for ML feature extraction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 14:41:30 -04:00
321c476b8b feat(engine): add ML feature extraction and brute-force runner
Add FeatureExtractor for computing geometric part features (convexity,
aspect ratio, circularity, bitmask) and BruteForceRunner for generating
training data by running the fill engine and recording results.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-14 12:41:20 -04:00