fix: small parts use FindScrapZones not FindAllRemnants

Small parts must only go into scrap zones (both dims < minRemnantSize)
to preserve viable remnants. The implementer had inverted this, giving
small parts access to all remnants. Also fixed the test to verify
remnant preservation behavior and removed unused FindAllRemnants helper.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-06 14:11:10 -04:00
parent fd3c2462df
commit f1fd211ba5
2 changed files with 14 additions and 13 deletions
+2 -8
View File
@@ -262,9 +262,9 @@ namespace OpenNest
if (classification == PartClass.Large) if (classification == PartClass.Large)
continue; // Large parts don't go on existing plates — they create new ones. continue; // Large parts don't go on existing plates — they create new ones.
// Get all remnants and try to place in them. // Small parts only go into scrap zones; medium parts into viable remnants.
var remnants = classification == PartClass.Small var remnants = classification == PartClass.Small
? FindAllRemnants(pr.Plate) ? FindScrapZones(pr.Plate, minRemnantSize)
: FindViableRemnants(pr.Plate, minRemnantSize); : FindViableRemnants(pr.Plate, minRemnantSize);
foreach (var zone in remnants) foreach (var zone in remnants)
@@ -435,12 +435,6 @@ namespace OpenNest
return false; return false;
} }
private static List<Box> FindAllRemnants(Plate plate)
{
var finder = RemnantFinder.FromPlate(plate);
return finder.FindRemnants();
}
private static NestItem CloneItem(NestItem item) private static NestItem CloneItem(NestItem item)
{ {
return new NestItem return new NestItem
+12 -5
View File
@@ -236,8 +236,11 @@ public class MultiPlateNesterTests
} }
[Fact] [Fact]
public void Nest_SmallPartsGoIntoScrapZones() public void Nest_SmallPartsDontConsumeViableRemnants()
{ {
// 96x48 plate with 80x40 big part leaves viable remnants (strips > 12" in one dim).
// Small parts should NOT consume those viable remnants — they should go to
// a separate plate instead, preserving the remnant for future use.
var template = new Plate(96, 48) { PartSpacing = 0.25, Quadrant = 1 }; var template = new Plate(96, 48) { PartSpacing = 0.25, Quadrant = 1 };
template.EdgeSpacing = new Spacing(); template.EdgeSpacing = new Spacing();
@@ -258,10 +261,14 @@ public class MultiPlateNesterTests
progress: null, progress: null,
token: CancellationToken.None); token: CancellationToken.None);
// Small parts should be placed on the same plate as the big part // Big part on plate 1, tiny parts on plate 2 (viable remnant preserved).
// (in scrap zones), not on a new plate. Assert.Equal(2, result.Plates.Count);
Assert.Equal(1, result.Plates.Count);
Assert.True(result.Plates[0].Parts.Count > 1); // First plate should have only the big part.
var bigPlate = result.Plates.First(p => p.Parts.Any(
part => part.BaseDrawing.Name == "big"));
var tinyOnBigPlate = bigPlate.Parts.Count(p => p.BaseDrawing.Name == "tiny");
Assert.Equal(0, tinyOnBigPlate);
} }
[Fact] [Fact]