mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-27 07:11:06 -04:00
Without salvage credit (desktop Auto Nest on a single plate size) every complete one-sheet layout costs the same, so engines kept whichever layout came first. N26-23S nested 27.86" long when turning two parts fits it in 21.3". NestJobCost.CompactnessOffcut measures the largest full-width/full-length edge offcut as salvage does, whatever the salvage rate. Default and Circles (CandidateScore), Rectangles and Circles sheet choice (SheetByStock) and Irregular sheet and plan ranking use it only after cost, so no cost changes. Sheet-level keys round to 1e-6 to keep ties platform-independent. Rectangles layout digests are re-captured: each changed fixture keeps its sheets, parts and cost and leaves a larger offcut. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
43 lines
1.8 KiB
C#
43 lines
1.8 KiB
C#
using OpenNest.Engine.Jobs;
|
|
using OpenNest.Engine.Tests.Jobs;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Engine.Tests.NestingEngines;
|
|
|
|
/// <summary>
|
|
/// Without salvage credit (desktop Auto Nest on one plate size) every complete one-sheet layout
|
|
/// costs the same, so engines must break the tie toward the larger free offcut. Shaped after
|
|
/// N26-23S: four 7.083 x 22.577 and four 6.236 x 18.688 boxes on a clamped 60 x 120 sheet,
|
|
/// which once nested 27.86" long when turning two of the smaller boxes fits it in 21.3".
|
|
/// </summary>
|
|
public class CompactTieBreakTests
|
|
{
|
|
[Theory]
|
|
[InlineData("Rectangles")]
|
|
[InlineData("Irregular")]
|
|
[InlineData("Default")]
|
|
public void EqualCostOneSheetLayoutsPreferTheLargestOffcut(string engine)
|
|
{
|
|
var template = new Plate(60, 120)
|
|
{
|
|
PartSpacing = 0.3,
|
|
EdgeSpacing = new Spacing(0.3, 0.75, 0.3, 0.25),
|
|
};
|
|
template.SetClampRail(new ClampRail(1.5, 0.625, new double[] { 20, 40, 60, 80, 100, 120, 140 }));
|
|
var items = new[]
|
|
{
|
|
new NestItem { Drawing = new Drawing("leg-bottom", TestDrawingFactory.Rectangle(7.083, 22.577)), Quantity = 4 },
|
|
new NestItem { Drawing = new Drawing("leg-top", TestDrawingFactory.Rectangle(6.236, 18.688)), Quantity = 4 },
|
|
};
|
|
|
|
var result = NestPipeline.Run(new NestPipelineRequest(engine, items,
|
|
NestStockBuilder.FromTemplate(template, null),
|
|
new NestJobOptions(maxPlates: 100, salvageRate: 0, minimumSalvageDimension: 0)));
|
|
|
|
Assert.True(result.IsValid, string.Join("; ", result.Violations));
|
|
var parts = Assert.Single(result.Plates).Parts;
|
|
Assert.Equal(8, parts.Count);
|
|
Assert.True(parts.Max(p => p.BoundingBox.Right) < 21.5, $"used length {parts.Max(p => p.BoundingBox.Right):0.###}");
|
|
}
|
|
}
|