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>
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>
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>
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>
- 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
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>
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>
- 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>
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>
"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>
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>
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>
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>
- 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>
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>
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>
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>
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>