feat: use direction-specific engines in StripNestEngine
Height shrink now uses HorizontalRemnantEngine (minimizes Y-extent) and width shrink uses VerticalRemnantEngine (minimizes X-extent). IterativeShrinkFiller accepts an optional widthFillFunc so each shrink axis can use a different fill engine. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -31,7 +31,8 @@ namespace OpenNest.Engine.Fill
|
|||||||
double spacing,
|
double spacing,
|
||||||
CancellationToken token = default,
|
CancellationToken token = default,
|
||||||
IProgress<NestProgress> progress = null,
|
IProgress<NestProgress> progress = null,
|
||||||
int plateNumber = 0)
|
int plateNumber = 0,
|
||||||
|
Func<NestItem, Box, List<Part>> widthFillFunc = null)
|
||||||
{
|
{
|
||||||
if (items == null || items.Count == 0)
|
if (items == null || items.Count == 0)
|
||||||
return new IterativeShrinkResult();
|
return new IterativeShrinkResult();
|
||||||
@@ -72,6 +73,8 @@ namespace OpenNest.Engine.Fill
|
|||||||
// include them in progress reports.
|
// include them in progress reports.
|
||||||
var placedSoFar = new List<Part>();
|
var placedSoFar = new List<Part>();
|
||||||
|
|
||||||
|
var wFillFunc = widthFillFunc ?? fillFunc;
|
||||||
|
|
||||||
Func<NestItem, Box, List<Part>> shrinkWrapper = (ni, box) =>
|
Func<NestItem, Box, List<Part>> shrinkWrapper = (ni, box) =>
|
||||||
{
|
{
|
||||||
var target = ni.Quantity > 0 ? ni.Quantity : 0;
|
var target = ni.Quantity > 0 ? ni.Quantity : 0;
|
||||||
@@ -84,7 +87,7 @@ namespace OpenNest.Engine.Fill
|
|||||||
Parallel.Invoke(
|
Parallel.Invoke(
|
||||||
() => heightResult = ShrinkFiller.Shrink(fillFunc, ni, box, spacing, ShrinkAxis.Height, token,
|
() => heightResult = ShrinkFiller.Shrink(fillFunc, ni, box, spacing, ShrinkAxis.Height, token,
|
||||||
targetCount: target, progress: progress, plateNumber: plateNumber, placedParts: placedSoFar),
|
targetCount: target, progress: progress, plateNumber: plateNumber, placedParts: placedSoFar),
|
||||||
() => widthResult = ShrinkFiller.Shrink(fillFunc, ni, box, spacing, ShrinkAxis.Width, token,
|
() => widthResult = ShrinkFiller.Shrink(wFillFunc, ni, box, spacing, ShrinkAxis.Width, token,
|
||||||
targetCount: target, progress: progress, plateNumber: plateNumber, placedParts: placedSoFar)
|
targetCount: target, progress: progress, plateNumber: plateNumber, placedParts: placedSoFar)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -77,17 +77,23 @@ namespace OpenNest
|
|||||||
// Phase 1: Iterative shrink-fill for multi-quantity items.
|
// Phase 1: Iterative shrink-fill for multi-quantity items.
|
||||||
if (fillItems.Count > 0)
|
if (fillItems.Count > 0)
|
||||||
{
|
{
|
||||||
// Pass progress through so the UI shows intermediate results
|
// Use direction-specific engines: height shrink benefits from
|
||||||
// during the initial BestFitCache computation and fill phases.
|
// minimizing Y-extent, width shrink from minimizing X-extent.
|
||||||
Func<NestItem, Box, List<Part>> fillFunc = (ni, b) =>
|
Func<NestItem, Box, List<Part>> heightFillFunc = (ni, b) =>
|
||||||
{
|
{
|
||||||
var inner = new DefaultNestEngine(Plate);
|
var inner = new HorizontalRemnantEngine(Plate);
|
||||||
|
return inner.Fill(ni, b, progress, token);
|
||||||
|
};
|
||||||
|
|
||||||
|
Func<NestItem, Box, List<Part>> widthFillFunc = (ni, b) =>
|
||||||
|
{
|
||||||
|
var inner = new VerticalRemnantEngine(Plate);
|
||||||
return inner.Fill(ni, b, progress, token);
|
return inner.Fill(ni, b, progress, token);
|
||||||
};
|
};
|
||||||
|
|
||||||
var shrinkResult = IterativeShrinkFiller.Fill(
|
var shrinkResult = IterativeShrinkFiller.Fill(
|
||||||
fillItems, workArea, fillFunc, Plate.PartSpacing, token,
|
fillItems, workArea, heightFillFunc, Plate.PartSpacing, token,
|
||||||
progress, PlateNumber);
|
progress, PlateNumber, widthFillFunc);
|
||||||
|
|
||||||
allParts.AddRange(shrinkResult.Parts);
|
allParts.AddRange(shrinkResult.Parts);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user