feat: integrate NFP optimization into nest engines and fill UI

Add Compactor.Settle and AutoNester.Optimize post-passes to
NestEngineBase.Nest, StripNestEngine, and PlateView.FillWithProgress
so all fill paths benefit from geometry-aware compaction.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-20 14:43:24 -04:00
parent a04586f7df
commit cf1c5fe120
3 changed files with 19 additions and 7 deletions

View File

@@ -1,4 +1,5 @@
using OpenNest.Engine.Fill;
using OpenNest.Engine.Nfp;
using OpenNest.Geometry;
using System;
using System.Collections.Generic;
@@ -126,6 +127,12 @@ namespace OpenNest
}
}
// Compact placed parts toward the origin to close gaps.
Compactor.Settle(allParts, Plate.WorkArea(), Plate.PartSpacing);
// NFP optimization pass — re-place parts using geometry-aware BLF.
allParts = AutoNester.Optimize(allParts, Plate);
return allParts;
}

View File

@@ -1,4 +1,5 @@
using OpenNest.Engine.Fill;
using OpenNest.Engine.Nfp;
using OpenNest.Geometry;
using System;
using System.Collections.Generic;
@@ -92,12 +93,7 @@ namespace OpenNest
allParts.AddRange(shrinkResult.Parts);
// Compact placed parts toward the origin to close gaps.
if (allParts.Count > 1)
{
var noObstacles = new List<Part>();
Compactor.Push(allParts, noObstacles, workArea, Plate.PartSpacing, PushDirection.Left);
Compactor.Push(allParts, noObstacles, workArea, Plate.PartSpacing, PushDirection.Down);
}
Compactor.Settle(allParts, workArea, Plate.PartSpacing);
// Add unfilled items to pack list.
packItems.AddRange(shrinkResult.Leftovers);
@@ -127,6 +123,9 @@ namespace OpenNest
}
}
// NFP optimization pass — re-place parts using geometry-aware BLF.
allParts = AutoNester.Optimize(allParts, Plate);
// Deduct placed quantities from original items.
foreach (var item in items)
{

View File

@@ -2,6 +2,7 @@
using OpenNest.CNC;
using OpenNest.Collections;
using OpenNest.Engine.Fill;
using OpenNest.Engine.Nfp;
using OpenNest.Forms;
using OpenNest.Geometry;
using OpenNest.Math;
@@ -955,8 +956,13 @@ namespace OpenNest.Controls
try
{
var engine = NestEngineRegistry.Create(Plate);
var spacing = Plate.PartSpacing;
var parts = await Task.Run(() =>
engine.Fill(groupParts, workArea, progress, cts.Token));
{
var result = engine.Fill(groupParts, workArea, progress, cts.Token);
Compactor.Settle(result, workArea, spacing);
return AutoNester.Optimize(result, workArea, spacing);
});
if (parts.Count > 0 && (!cts.IsCancellationRequested || progressForm.Accepted))
{