Commit Graph

325 Commits

Author SHA1 Message Date
9773449563 feat(ui): add FillWithProgress to PlateView, use from ActionClone
Moves async fill+progress orchestration into PlateView so ActionClone's
Ctrl+F fill shows the NestProgressForm dialog.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:39:30 -04:00
fde285484a fix(ui): cancel nesting when MDI child form is closed
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:33:43 -04:00
98c4c88fc3 feat(ui): add progress support to ActionFillArea and FillArea_Click
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:33:09 -04:00
09fef203df feat(ui): make FillPlate_Click async with progress and cancellation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:32:17 -04:00
0bf128b3e7 feat(ui): make RunAutoNest_Click async with progress and cancellation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:31:31 -04:00
af0748fb1b feat(ui): add NestProgressForm modeless dialog
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:30:22 -04:00
c545f91d28 feat(ui): add temporary parts list to PlateView with preview drawing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:29:30 -04:00
bd2b5ec1db feat(ui): add PreviewPart color to ColorScheme
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:28:18 -04:00
ca685ac8ba feat(engine): add public Fill overloads returning List<Part> with progress/cancellation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:27:31 -04:00
93fbe1a9f8 feat(engine): add FindBestFill and FillWithPairs overloads with progress and cancellation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:26:32 -04:00
a97477fcdf feat(engine): add NestPhase enum and NestProgress data model
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:24:55 -04:00
4da5e3fc89 docs: add nesting progress window implementation plan
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:20:52 -04:00
5f72f5712e docs: address spec review feedback for nesting progress window
Clarify engine return type ownership, cancellation propagation into
parallel loops, quantity decrement sequencing, conditional phase
behavior, plate navigation lockout, and MDI child close handling.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:08:14 -04:00
5f64130b9d docs: add nesting progress window design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:05:11 -04:00
09fc8b889e fix: close polygon offset shape and handle nest template load failure
Shape.OffsetEntity computed joins between consecutive offset segments
but never joined the last segment back to the first, leaving the
closing corner with a straight line instead of a proper miter/arc.
Track the first entity and apply the same join logic after the loop.

Also wrap nest template loading in try-catch so a corrupt template
file doesn't crash the app on startup — falls back to default nest.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:37:39 -04:00
2216b8553f docs: add implementation plans for best-fit viewer, pair finding, and .NET 8 migration
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:24:45 -04:00
6ed20a6a48 refactor: switch auto-nest from Pack to per-item Fill with explicit quantity tracking
Replace engine.Pack(items) with individual engine.Fill(item) calls so each
drawing is filled independently. Quantity decrements now count parts actually
placed per plate (grouped by drawing) instead of relying on the drawing's
internal remaining counter.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:24:42 -04:00
c68139e15e merge: resolve .gitignore conflict, keep both entries
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:22:45 -04:00
66b3aeafc1 fix: correct inverted quadrant-to-exit-point mapping in GetExitPoint
The exit point should be the corner farthest from the origin so the
perimeter (cut last) ends near the machine home. The mapping was
backwards — Q1 (origin bottom-left) was returning (0,0) instead of
(w,l).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:59:04 -04:00
616575e0ee feat: wire contour re-indexing into ContourCuttingStrategy.Apply()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:57:17 -04:00
2b4cb849ba feat: add Shape.ReindexAt(Vector, Entity) for contour reordering
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:54:54 -04:00
3de44a7293 feat: add Arc.SplitAt(Vector) splitting primitive 2026-03-12 23:53:25 -04:00
b2ff704b73 feat: add Line.SplitAt(Vector) splitting primitive 2026-03-12 23:53:23 -04:00
f7940efe93 docs: fix contour re-indexing spec from review feedback
- Drop Circle.ToArcFrom (zero-sweep problem), keep Circle in shape
  and handle in ConvertShapeToMoves with full-circle ArcMove
- Use point-distance tolerance for Arc.SplitAt instead of angle
  comparison to avoid wrap-around issues at 0/2pi
- Simplify SplitAt return types to non-nullable tuple
- Add ArgumentException guard in ReindexAt
- Add throw for unexpected entity types in ConvertShapeToMoves
- Document absolute coordinate convention and shared references
- Clarify variable names for both replacement sites
2026-03-12 23:45:21 -04:00
6a2f39530f docs: add contour re-indexing design spec 2026-03-12 23:41:30 -04:00
18023cb1cf docs: clarify cutting strategy runs at nest-time, not post-processing
The strategy output (lead-ins, start points, contour ordering) must be
saved in the nest file, so Apply() runs when parts are placed — not
during post-processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:24:23 -04:00
b4a740a515 Merge branch 'feature/cutting-strategy' into master 2026-03-12 23:20:02 -04:00
441628eff2 feat: add ContourCuttingStrategy orchestrator
Exit point from plate quadrant, nearest-neighbor cutout
sequencing via ShapeProfile + ClosestPointTo, contour type
detection, and normal angle computation.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:15:38 -04:00
ac7d90ae17 feat: add CuttingParameters and configuration classes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:13:36 -04:00
459738e373 feat: add Tab hierarchy (4 classes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:13:31 -04:00
b112f70f6a feat: add LeadOut hierarchy (5 classes)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 23:12:09 -04:00
f17db1d2f9 feat: add LeadIn hierarchy (7 classes)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-12 23:07:31 -04:00
9b3cf10222 docs: add cutting strategy implementation plan
20 tasks across 5 chunks: LeadIn hierarchy, LeadOut hierarchy,
Tab hierarchy, configuration classes, and ContourCuttingStrategy
orchestrator.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:56:52 -04:00
e14382f2f3 docs: update cutting strategy spec with review fixes
- Rename Angle properties to ApproachAngle (avoid shadowing Math.Angle)
- Arc rotation from contour winding, not hardcoded CW
- Add winding parameter to LeadIn/LeadOut Generate methods
- Add exit point derivation from Plate quadrant
- Add contour re-indexing section (split/reorder at closest point)
- Add ContourType.cs and AssignmentParameters.cs to file structure
- Clarify normal direction convention
- Note SequenceMethod value 6 intentionally skipped (PEP numbering)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:48:17 -04:00
cb30c20eb9 docs: add cutting strategy design spec
Lead-in, lead-out, and tab class hierarchy for CNC cutting
approach/exit geometry, using ShapeProfile + ClosestPointTo
for contour sequencing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:43:05 -04:00
e4e1d9b5a3 refactor: rename DefinedShape to ShapeProfile
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:19:49 -04:00
0c395421cd chore: add .claude/ to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:02:54 -04:00
612b540d9d refactor: rename Size.Height to Size.Length across codebase
"Length" is more natural than "height" for flat plate materials.
Renames the field on OpenNest.Geometry.Size, Box.Height property,
and all references across 38 files.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 22:01:40 -04:00
7e0edd112a refactor: use 'length' instead of 'height' in nest JSON format
Rename SizeDto.Height to SizeDto.Length so the serialized JSON
uses "width"/"length" which is more natural for plate materials.
The core Size struct still uses Height internally.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 21:50:53 -04:00
c2534ef08b feat: replace XML nest file format with JSON (v2)
Replace three separate XML metadata files (info, drawing-info,
plate-info) and per-plate G-code placement files with a single
nest.json inside the ZIP archive. Programs remain as G-code text
under a programs/ folder.

This eliminates ~400 lines of hand-written XML read/write code
and fragile ID-based dictionary linking. Now uses System.Text.Json
with DTO records for clean serialization. Also adds Priority and
Constraints fields to drawing serialization (previously omitted).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 18:44:43 -04:00
a084819889 perf: comment out Debug.WriteLine calls in FillLinear
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:44:14 -04:00
d0d334e734 fix: use chain tolerance for shape building to handle DXF endpoint gaps
DXF files can have endpoint gaps at entity junctions that fall right at
the floating-point boundary of Tolerance.Epsilon (0.00001). This caused
shapes to not close, resulting in 0 area and 0% utilization in Best-Fit.

Added ChainTolerance (0.0001) for endpoint chaining in GetConnected and
Shape.IsClosed, keeping the tighter Epsilon for geometric precision.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:37:39 -04:00
2632b3dbf7 fix: resolve infinite loop in multi-plate autonest and wire into console
- Change while(true) to bounded for-loop (max 100 plates) in MainForm
- Use Drawing.Name comparison instead of reference equality for quantity deduction
- Add Math.Max(0, ...) guard to prevent negative quantities
- Tune SA parameters for faster convergence (cooling=0.995, minTemp=0.1, maxNoImprove=500)
- Add --autonest flag to OpenNest.Console for CLI-based NFP autonesting

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:29:02 -04:00
3f3b07ef5d feat: add NFP-based mixed-part autonesting
Implement geometry-aware nesting using No-Fit Polygons and simulated
annealing optimization. Parts interlock based on true shape rather than
bounding boxes, producing tighter layouts for mixed-part scenarios.

New types in Core/Geometry:
- ConvexDecomposition: ear-clipping triangulation for concave polygons
- NoFitPolygon: Minkowski sum via convex decomposition + Clipper2 union
- InnerFitPolygon: feasible region computation for plate placement

New types in Engine:
- NfpCache: caches NFPs keyed by (drawingId, rotation) pairs
- BottomLeftFill: places parts using feasible regions from IFP - NFP union
- INestOptimizer: abstraction for future GA/parallel upgrades
- SimulatedAnnealing: optimizes part ordering and rotation

Integration:
- NestEngine.AutoNest(): new public entry point for mixed-part nesting
- MainForm.RunAutoNest_Click: uses AutoNest instead of Pack
- NestingTools.autonest_plate: new MCP tool for Claude Code integration
- Drawing.Id: auto-incrementing identifier for NFP cache keys
- Clipper2 NuGet added to OpenNest.Core for polygon boolean operations

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:08:22 -04:00
9f84357c34 chore: add .worktrees/ to .gitignore
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:48:08 -04:00
164bab4a83 docs: update NFP autonest spec with review fixes
Address spec review findings: add Clipper2 dependency, fix BLF
point selection priority (Y-first), add Drawing.Id, clarify spacing
semantics, add CancellationToken support, specify convex decomposition
approach, add error handling and polygon vertex budget sections.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:42:42 -04:00
f126bfe2ba docs: add NFP-based autonesting design spec
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 14:28:22 -04:00
ad50751250 feat: add OpenNest.Console project (renamed from TestHarness)
Console app for running the nesting engine from the command line.
Supports plate size/spacing overrides, quantity limits, overlap
checking with exit codes, and benchmark-friendly flags (--no-save,
--no-log). The MCP test_engine tool shells out to this project.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:43:02 -04:00
78ee65d946 fix: resolve grid overlap bug and parallelize fill loops
The push algorithm's copy distance formula (bboxDim - slideDistance)
produced distances smaller than the part width when inflated boundary
arc vertices interacted spuriously, causing ~0.05 unit overlaps between
all adjacent grid parts.

Two fixes applied:
- Clamp ComputeCopyDistance to bboxDim + PartSpacing minimum
- Use circumscribed polygons (R/cos(halfStep)) for PartBoundary arc
  discretization so chord segments never cut inside the true arc,
  eliminating the ChordTolerance offset workaround

Also parallelized three sequential fill loops using Parallel.ForEach:
- FindBestFill angle sweep (up to 38 angles x 2 directions)
- FillPattern angle sweep for group/pair fills
- FillRemainingStrip rotation loop

Added diagnostic logging to HasOverlaps, FindCopyDistance, and
FillRecursive for debugging fill issues.

Test result: 45 parts @ 79.6% -> 47 parts @ 83.1%, zero overlaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 00:36:48 -04:00
0e3bf3ccaa feat: try fewer rows in FillRecursive when remainder strip yields more parts
When the greedy maximum-row tiling leaves a thin remainder, tries removing
the last row and re-filling the larger strip. Picks whichever total is
higher. Fixes cases where e.g. 4 rows + 11 remainder = 47 beats 5 rows = 45.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 23:19:42 -04:00