From 07012033c76ab1c2523ce5be12592b62649cbe68 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Sat, 21 Mar 2026 23:09:02 -0400 Subject: [PATCH] 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) --- OpenNest.Engine/Fill/IterativeShrinkFiller.cs | 7 +++++-- OpenNest.Engine/StripNestEngine.cs | 18 ++++++++++++------ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/OpenNest.Engine/Fill/IterativeShrinkFiller.cs b/OpenNest.Engine/Fill/IterativeShrinkFiller.cs index 7b0722e..50f9bd7 100644 --- a/OpenNest.Engine/Fill/IterativeShrinkFiller.cs +++ b/OpenNest.Engine/Fill/IterativeShrinkFiller.cs @@ -31,7 +31,8 @@ namespace OpenNest.Engine.Fill double spacing, CancellationToken token = default, IProgress progress = null, - int plateNumber = 0) + int plateNumber = 0, + Func> widthFillFunc = null) { if (items == null || items.Count == 0) return new IterativeShrinkResult(); @@ -72,6 +73,8 @@ namespace OpenNest.Engine.Fill // include them in progress reports. var placedSoFar = new List(); + var wFillFunc = widthFillFunc ?? fillFunc; + Func> shrinkWrapper = (ni, box) => { var target = ni.Quantity > 0 ? ni.Quantity : 0; @@ -84,7 +87,7 @@ namespace OpenNest.Engine.Fill Parallel.Invoke( () => heightResult = ShrinkFiller.Shrink(fillFunc, ni, box, spacing, ShrinkAxis.Height, token, 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) ); diff --git a/OpenNest.Engine/StripNestEngine.cs b/OpenNest.Engine/StripNestEngine.cs index f580c4c..cec9ed0 100644 --- a/OpenNest.Engine/StripNestEngine.cs +++ b/OpenNest.Engine/StripNestEngine.cs @@ -77,17 +77,23 @@ namespace OpenNest // Phase 1: Iterative shrink-fill for multi-quantity items. if (fillItems.Count > 0) { - // Pass progress through so the UI shows intermediate results - // during the initial BestFitCache computation and fill phases. - Func> fillFunc = (ni, b) => + // Use direction-specific engines: height shrink benefits from + // minimizing Y-extent, width shrink from minimizing X-extent. + Func> heightFillFunc = (ni, b) => { - var inner = new DefaultNestEngine(Plate); + var inner = new HorizontalRemnantEngine(Plate); + return inner.Fill(ni, b, progress, token); + }; + + Func> widthFillFunc = (ni, b) => + { + var inner = new VerticalRemnantEngine(Plate); return inner.Fill(ni, b, progress, token); }; var shrinkResult = IterativeShrinkFiller.Fill( - fillItems, workArea, fillFunc, Plate.PartSpacing, token, - progress, PlateNumber); + fillItems, workArea, heightFillFunc, Plate.PartSpacing, token, + progress, PlateNumber, widthFillFunc); allParts.AddRange(shrinkResult.Parts);