Files
OpenNest/OpenNest.Tests/Fill/FillExtentsTests.cs
T
aj aec0523062 style: apply CSharpier formatting to all C# sources
Repo-wide sweep with the pinned CSharpier 1.3.0 tool. Whitespace and
line-wrapping only; OpenNest.Engine.Tests (109) and OpenNest.IO.Tests
pass after reformat, full solution builds 0 errors.

Added .csharpierignore so csproj/config XML keeps its existing layout
(CSharpier's XML wrapping churns attributes with zero benefit).

Formatting is now enforceable: dotnet csharpier check . passes.
2026-09-20 16:41:50 -04:00

175 lines
5.4 KiB
C#

using OpenNest.CNC;
using OpenNest.Engine.Fill;
using OpenNest.Geometry;
namespace OpenNest.Tests.Fill;
public class FillExtentsTests
{
private static Drawing MakeRightTriangle(double w, double h)
{
var pgm = new Program();
pgm.Codes.Add(new RapidMove(new Vector(0, 0)));
pgm.Codes.Add(new LinearMove(new Vector(w, 0)));
pgm.Codes.Add(new LinearMove(new Vector(0, h)));
pgm.Codes.Add(new LinearMove(new Vector(0, 0)));
return new Drawing("triangle", pgm);
}
private static Drawing MakeRect(double w, double h)
{
var pgm = new Program();
pgm.Codes.Add(new RapidMove(new Vector(0, 0)));
pgm.Codes.Add(new LinearMove(new Vector(w, 0)));
pgm.Codes.Add(new LinearMove(new Vector(w, h)));
pgm.Codes.Add(new LinearMove(new Vector(0, h)));
pgm.Codes.Add(new LinearMove(new Vector(0, 0)));
return new Drawing("rect", pgm);
}
[Fact]
public void Fill_Triangle_ReturnsPartsWithinWorkArea()
{
var workArea = new Box(0, 0, 120, 60);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRightTriangle(10, 8);
var parts = filler.Fill(drawing);
Assert.NotNull(parts);
Assert.True(parts.Count > 0, "Should place at least one part");
foreach (var part in parts)
{
Assert.True(
part.BoundingBox.Right <= workArea.Right + 0.01,
$"Part right edge {part.BoundingBox.Right} exceeds work area {workArea.Right}"
);
Assert.True(
part.BoundingBox.Top <= workArea.Top + 0.01,
$"Part top edge {part.BoundingBox.Top} exceeds work area {workArea.Top}"
);
}
}
[Fact]
public void Fill_PartTooLarge_ReturnsEmpty()
{
var workArea = new Box(0, 0, 5, 5);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRect(10, 10);
var parts = filler.Fill(drawing);
Assert.NotNull(parts);
Assert.Empty(parts);
}
[Fact]
public void Fill_Triangle_ColumnFillsHeight()
{
var workArea = new Box(0, 0, 120, 60);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRightTriangle(10, 8);
var parts = filler.Fill(drawing);
Assert.True(parts.Count > 0);
// The topmost part should be close to the work area top edge.
var topEdge = 0.0;
foreach (var part in parts)
{
if (part.BoundingBox.Top > topEdge)
topEdge = part.BoundingBox.Top;
}
// After adjustment, the gap should be small (within one part spacing).
var gap = workArea.Top - topEdge;
Assert.True(
gap < 1.0,
$"Gap of {gap:F2} is too large — adjustment should fill close to the top"
);
}
[Fact]
public void Fill_Triangle_FillsWidthWithMultipleColumns()
{
var workArea = new Box(0, 0, 120, 60);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRightTriangle(10, 8);
var parts = filler.Fill(drawing);
// With a 120-wide sheet and ~10-wide parts, we should get multiple columns.
Assert.True(
parts.Count >= 8,
$"Expected multiple columns but got only {parts.Count} parts"
);
// Verify all parts are within bounds.
foreach (var part in parts)
{
Assert.True(part.BoundingBox.Right <= workArea.Right + 0.01);
Assert.True(part.BoundingBox.Top <= workArea.Top + 0.01);
Assert.True(part.BoundingBox.Left >= workArea.Left - 0.01);
Assert.True(part.BoundingBox.Bottom >= workArea.Bottom - 0.01);
}
}
[Fact]
public void Fill_Rect_ReturnsNonEmpty()
{
var workArea = new Box(0, 0, 120, 60);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRect(15, 10);
var parts = filler.Fill(drawing);
Assert.NotNull(parts);
Assert.True(parts.Count > 0, "Rectangle should produce results");
}
[Fact]
public void Fill_NonZeroOriginWorkArea_PartsWithinBounds()
{
// Simulate a remnant sub-region with non-zero origin.
var workArea = new Box(30, 10, 80, 40);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRightTriangle(10, 8);
var parts = filler.Fill(drawing);
Assert.True(parts.Count > 0);
foreach (var part in parts)
{
Assert.True(
part.BoundingBox.Left >= workArea.Left - 0.01,
$"Part left {part.BoundingBox.Left} below work area left {workArea.Left}"
);
Assert.True(
part.BoundingBox.Bottom >= workArea.Bottom - 0.01,
$"Part bottom {part.BoundingBox.Bottom} below work area bottom {workArea.Bottom}"
);
Assert.True(part.BoundingBox.Right <= workArea.Right + 0.01);
Assert.True(part.BoundingBox.Top <= workArea.Top + 0.01);
}
}
[Fact]
public void Fill_RespectsCancellation()
{
var cts = new System.Threading.CancellationTokenSource();
cts.Cancel();
var workArea = new Box(0, 0, 120, 60);
var filler = new FillExtents(workArea, 0.5);
var drawing = MakeRightTriangle(10, 8);
var parts = filler.Fill(drawing, token: cts.Token);
Assert.NotNull(parts);
}
}