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:
@@ -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
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
Reference in New Issue
Block a user