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>
This commit is contained in:
@@ -680,26 +680,32 @@ namespace OpenNest.Forms
|
||||
return;
|
||||
|
||||
var items = form.GetNestItems();
|
||||
var qty = new int[items.Count];
|
||||
|
||||
while (true)
|
||||
{
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
qty[i] = items[i].Drawing.Quantity.Remaining;
|
||||
var remaining = items.Where(i => i.Quantity > 0).ToList();
|
||||
|
||||
if (remaining.Count == 0)
|
||||
break;
|
||||
|
||||
var plate = activeForm.PlateView.Plate.Parts.Count > 0
|
||||
? activeForm.Nest.CreatePlate()
|
||||
: activeForm.PlateView.Plate;
|
||||
|
||||
var engine = new NestEngine(plate);
|
||||
var parts = NestEngine.AutoNest(remaining, plate);
|
||||
|
||||
if (!engine.Pack(items))
|
||||
if (parts.Count == 0)
|
||||
break;
|
||||
|
||||
plate.Parts.AddRange(parts);
|
||||
activeForm.Nest.UpdateDrawingQuantities();
|
||||
|
||||
for (int i = 0; i < items.Count; i++)
|
||||
items[i].Quantity -= qty[i] - items[i].Drawing.Quantity.Remaining;
|
||||
// Reduce remaining quantities by how many were placed per drawing.
|
||||
foreach (var item in remaining)
|
||||
{
|
||||
var placed = parts.Count(p => p.BaseDrawing == item.Drawing);
|
||||
item.Quantity -= placed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user