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:
@@ -1,4 +1,5 @@
|
|||||||
using OpenNest.Engine.Fill;
|
using OpenNest.Engine.Fill;
|
||||||
|
using OpenNest.Engine.Nfp;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
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;
|
return allParts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using OpenNest.Engine.Fill;
|
using OpenNest.Engine.Fill;
|
||||||
|
using OpenNest.Engine.Nfp;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -92,12 +93,7 @@ namespace OpenNest
|
|||||||
allParts.AddRange(shrinkResult.Parts);
|
allParts.AddRange(shrinkResult.Parts);
|
||||||
|
|
||||||
// Compact placed parts toward the origin to close gaps.
|
// Compact placed parts toward the origin to close gaps.
|
||||||
if (allParts.Count > 1)
|
Compactor.Settle(allParts, workArea, Plate.PartSpacing);
|
||||||
{
|
|
||||||
var noObstacles = new List<Part>();
|
|
||||||
Compactor.Push(allParts, noObstacles, workArea, Plate.PartSpacing, PushDirection.Left);
|
|
||||||
Compactor.Push(allParts, noObstacles, workArea, Plate.PartSpacing, PushDirection.Down);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add unfilled items to pack list.
|
// Add unfilled items to pack list.
|
||||||
packItems.AddRange(shrinkResult.Leftovers);
|
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.
|
// Deduct placed quantities from original items.
|
||||||
foreach (var item in items)
|
foreach (var item in items)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using OpenNest.CNC;
|
using OpenNest.CNC;
|
||||||
using OpenNest.Collections;
|
using OpenNest.Collections;
|
||||||
using OpenNest.Engine.Fill;
|
using OpenNest.Engine.Fill;
|
||||||
|
using OpenNest.Engine.Nfp;
|
||||||
using OpenNest.Forms;
|
using OpenNest.Forms;
|
||||||
using OpenNest.Geometry;
|
using OpenNest.Geometry;
|
||||||
using OpenNest.Math;
|
using OpenNest.Math;
|
||||||
@@ -955,8 +956,13 @@ namespace OpenNest.Controls
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var engine = NestEngineRegistry.Create(Plate);
|
var engine = NestEngineRegistry.Create(Plate);
|
||||||
|
var spacing = Plate.PartSpacing;
|
||||||
var parts = await Task.Run(() =>
|
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))
|
if (parts.Count > 0 && (!cts.IsCancellationRequested || progressForm.Accepted))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user