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:
2026-03-12 08:08:22 -04:00
parent 9f84357c34
commit 3f3b07ef5d
12 changed files with 1447 additions and 7 deletions

View File

@@ -1,5 +1,6 @@
using System.Drawing;
using System.Linq;
using System.Threading;
using OpenNest.CNC;
using OpenNest.Converters;
using OpenNest.Geometry;
@@ -8,6 +9,7 @@ namespace OpenNest
{
public class Drawing
{
private static int nextId;
private Program program;
public Drawing()
@@ -22,6 +24,7 @@ namespace OpenNest
public Drawing(string name, Program pgm)
{
Id = Interlocked.Increment(ref nextId);
Name = name;
Material = new Material();
Program = pgm;
@@ -29,6 +32,8 @@ namespace OpenNest
Source = new SourceInfo();
}
public int Id { get; }
public string Name { get; set; }
public string Customer { get; set; }