diff --git a/OpenNest.Engine/StripNestEngine.cs b/OpenNest.Engine/StripNestEngine.cs
index 6ad04ca..283a145 100644
--- a/OpenNest.Engine/StripNestEngine.cs
+++ b/OpenNest.Engine/StripNestEngine.cs
@@ -292,8 +292,7 @@ namespace OpenNest
if (System.Math.Min(box.Width, box.Length) < minItemDim)
continue;
- var remnantInner = new DefaultNestEngine(Plate);
- var remnantParts = remnantInner.Fill(
+ var remnantParts = ShrinkFill(
new NestItem { Drawing = item.Drawing, Quantity = qty },
box, remnantProgress, token);
@@ -326,6 +325,73 @@ namespace OpenNest
return result;
}
+ ///
+ /// Fill a box and then shrink it to the tightest area that still fits
+ /// the same number of parts. This maximizes leftover space for subsequent fills.
+ ///
+ private List ShrinkFill(NestItem item, Box box,
+ IProgress progress, CancellationToken token)
+ {
+ var inner = new DefaultNestEngine(Plate);
+ var parts = inner.Fill(item, box, progress, token);
+
+ if (parts == null || parts.Count < 2)
+ return parts;
+
+ var targetCount = parts.Count;
+ var placedBox = parts.Cast().GetBoundingBox();
+
+ // Try shrinking horizontally
+ var bestParts = parts;
+ var shrunkWidth = placedBox.Right - box.X;
+ var shrunkHeight = placedBox.Top - box.Y;
+
+ for (var i = 0; i < MaxShrinkIterations; i++)
+ {
+ if (token.IsCancellationRequested)
+ break;
+
+ var trialWidth = shrunkWidth - Plate.PartSpacing;
+ if (trialWidth <= 0)
+ break;
+
+ var trialBox = new Box(box.X, box.Y, trialWidth, box.Length);
+ var trialInner = new DefaultNestEngine(Plate);
+ var trialParts = trialInner.Fill(item, trialBox, null, token);
+
+ if (trialParts == null || trialParts.Count < targetCount)
+ break;
+
+ bestParts = trialParts;
+ var trialPlacedBox = trialParts.Cast().GetBoundingBox();
+ shrunkWidth = trialPlacedBox.Right - box.X;
+ }
+
+ // Try shrinking vertically
+ for (var i = 0; i < MaxShrinkIterations; i++)
+ {
+ if (token.IsCancellationRequested)
+ break;
+
+ var trialHeight = shrunkHeight - Plate.PartSpacing;
+ if (trialHeight <= 0)
+ break;
+
+ var trialBox = new Box(box.X, box.Y, box.Width, trialHeight);
+ var trialInner = new DefaultNestEngine(Plate);
+ var trialParts = trialInner.Fill(item, trialBox, null, token);
+
+ if (trialParts == null || trialParts.Count < targetCount)
+ break;
+
+ bestParts = trialParts;
+ var trialPlacedBox = trialParts.Cast().GetBoundingBox();
+ shrunkHeight = trialPlacedBox.Top - box.Y;
+ }
+
+ return bestParts;
+ }
+
///
/// Wraps an IProgress to prepend previously placed parts to each report,
/// so the UI shows the full picture (strip + remnant) during remnant fills.