Files
OpenNest/OpenNest.Tests/PairFillerTests.cs
AJ Isaacs 00e7866506 feat: add remnant filling to PairFiller for better part density
PairFiller previously only filled the main grid with pair patterns,
leaving narrow waste strips unfilled. Row/Column strategies filled
their remnants, winning on count despite worse base grids.

Now PairFiller evaluates grid+remnant together for each angle/direction
combination, picking the best total. Uses a two-phase approach: fast
grid evaluation first, then remnant filling only for grids within
striking distance of the current best. Remnant results are cached
via FillResultCache.

Constructor now takes Plate (needed to create remnant engine).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-21 15:19:19 -04:00

65 lines
2.0 KiB
C#

using OpenNest.Engine.Fill;
using OpenNest.Geometry;
namespace OpenNest.Tests;
public class PairFillerTests
{
private static Drawing MakeRectDrawing(double w, double h)
{
var pgm = new OpenNest.CNC.Program();
pgm.Codes.Add(new OpenNest.CNC.RapidMove(new Vector(0, 0)));
pgm.Codes.Add(new OpenNest.CNC.LinearMove(new Vector(w, 0)));
pgm.Codes.Add(new OpenNest.CNC.LinearMove(new Vector(w, h)));
pgm.Codes.Add(new OpenNest.CNC.LinearMove(new Vector(0, h)));
pgm.Codes.Add(new OpenNest.CNC.LinearMove(new Vector(0, 0)));
return new Drawing("rect", pgm);
}
private static Plate MakePlate(double width, double length, double spacing = 0.5)
{
return new Plate { Size = new Size(width, length), PartSpacing = spacing };
}
[Fact]
public void Fill_ReturnsPartsForSimpleDrawing()
{
var filler = new PairFiller(MakePlate(120, 60));
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
var workArea = new Box(0, 0, 120, 60);
var result = filler.Fill(item, workArea);
Assert.NotNull(result.Parts);
Assert.NotNull(result.BestFits);
}
[Fact]
public void Fill_EmptyResult_WhenPartTooLarge()
{
var filler = new PairFiller(MakePlate(10, 10));
var item = new NestItem { Drawing = MakeRectDrawing(20, 20) };
var workArea = new Box(0, 0, 10, 10);
var result = filler.Fill(item, workArea);
Assert.NotNull(result.Parts);
Assert.Empty(result.Parts);
}
[Fact]
public void Fill_RespectsCancellation()
{
var cts = new System.Threading.CancellationTokenSource();
cts.Cancel();
var filler = new PairFiller(MakePlate(120, 60));
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
var workArea = new Box(0, 0, 120, 60);
var result = filler.Fill(item, workArea, token: cts.Token);
Assert.NotNull(result.Parts);
}
}