fix(engine): don't drop the topmost part when no other drawing is waiting

RemnantFiller removes the topmost placed part to keep a clean rectangular
obstacle for the next drawing, but the envelope then walls that slot off,
so the part was lost for nothing (4 squares on a 9x9 plate became 3).
Only remove it while another drawing still has demand.

Fixes the mixed-stock NestRunner tests.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
aj
2026-09-21 11:07:45 -04:00
co-authored by Claude Sonnet 5
parent a764a70e52
commit 630d514b0e
2 changed files with 47 additions and 1 deletions
+21 -1
View File
@@ -114,7 +114,10 @@ namespace OpenNest.Engine.Fill
// rectangular obstacle boundary. Without this, gaps between
// individual bounding boxes cause the next drawing to fill
// into inter-row spaces, producing an interleaved layout.
if (placed.Count > 2)
// Only worthwhile while another drawing is still waiting for
// space; otherwise the removed part's slot is walled off by the
// envelope below and the part is lost for nothing.
if (placed.Count > 2 && HasOtherDemand(items, item, localQty))
RemoveTopmostPart(placed);
allParts.AddRange(placed);
@@ -132,6 +135,23 @@ namespace OpenNest.Engine.Fill
return false;
}
private static bool HasOtherDemand(
List<NestItem> items,
NestItem current,
Dictionary<Drawing, int> localQty
)
{
foreach (var other in items)
{
if (ReferenceEquals(other.Drawing, current.Drawing))
continue;
if (localQty[other.Drawing] > 0)
return true;
}
return false;
}
private static void RemoveTopmostPart(List<Part> parts)
{
var topIdx = 0;