Files
OpenNest/OpenNest.Tests/PlateManagerDefaultsTests.cs
T
2026-11-12 19:38:20 -05:00

238 lines
8.7 KiB
C#

using OpenNest.Clamps;
using OpenNest.CNC;
using OpenNest.Geometry;
namespace OpenNest.Tests;
public class PlateManagerDefaultsTests
{
private static Nest CreateNest(bool withRail = true)
{
var nest = new Nest();
nest.PlateDefaults.Size = new Size(48, 96);
nest.PlateDefaults.Quadrant = 1;
nest.PlateDefaults.EdgeSpacing = new Spacing(1, 2, 3, 4);
nest.PlateDefaults.PartSpacing = 0.25;
if (withRail)
nest.SetClampRail(new ClampRail(1.5, 0.625, new[] { 6.0, 81.0 }));
return nest;
}
private static void ChangeDefaults(Nest nest)
{
nest.PlateDefaults.Size = new Size(48, 60);
nest.PlateDefaults.Quadrant = 3;
nest.PlateDefaults.EdgeSpacing = new Spacing(5, 6, 7, 8);
nest.PlateDefaults.PartSpacing = 0.5;
}
private static void AssertMatchesDefaults(Nest nest, Plate plate)
{
Assert.Equal(nest.PlateDefaults.Size, plate.Size);
Assert.Equal(nest.PlateDefaults.Quadrant, plate.Quadrant);
Assert.Equal(nest.PlateDefaults.EdgeSpacing, plate.EdgeSpacing);
Assert.Equal(nest.PlateDefaults.PartSpacing, plate.PartSpacing);
Assert.Same(nest.PlateDefaults.ClampRail, plate.ClampRail);
Assert.Empty(plate.RemovedClamps);
if (plate.ClampRail == null)
Assert.Empty(plate.ClampZones);
else
Assert.True(plate.ClampRail.Matches(plate));
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void ChangePlateDefaults_MovesUntouchedTrailingSheet(bool withRail)
{
var nest = CreateNest(withRail);
using var manager = new PlateManager(nest);
manager.EnsureSentinel();
var sentinel = Assert.Single(nest.Plates);
var listChanges = 0;
var currentChanges = 0;
manager.PlateListChanged += (_, _) => listChanges++;
manager.CurrentPlateChanged += (_, e) =>
{
Assert.Same(sentinel, e.Plate);
currentChanges++;
};
manager.ChangePlateDefaults(() => ChangeDefaults(nest));
Assert.Same(sentinel, Assert.Single(nest.Plates));
AssertMatchesDefaults(nest, sentinel);
Assert.Equal(0, manager.CurrentIndex);
Assert.Equal(1, listChanges);
Assert.Equal(1, currentChanges);
if (withRail)
{
// Independent physical oracle: Q3 origin clamp is at the sheet's upper right.
var zone = Assert.Single(sentinel.ClampZones);
Assert.Equal("clamp-1", zone.Id);
Assert.Equal(53.25, zone.Bounds.X);
Assert.Equal(47.375, zone.Bounds.Y);
Assert.Equal(1.5, zone.Bounds.Length);
Assert.Equal(0.625, zone.Bounds.Width);
}
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public void ChangePlateDefaults_ReappliesTheNewRail(bool removeRail)
{
var nest = CreateNest();
var sentinel = nest.CreatePlate();
using var manager = new PlateManager(nest);
var newRail = removeRail ? null : new ClampRail(2, 1, new[] { 10.0 });
manager.ChangePlateDefaults(() =>
{
ChangeDefaults(nest);
nest.PlateDefaults.ClampRail = newRail;
});
AssertMatchesDefaults(nest, sentinel);
}
[Theory]
[InlineData("width")]
[InlineData("length")]
[InlineData("quadrant")]
[InlineData("left")]
[InlineData("bottom")]
[InlineData("right")]
[InlineData("top")]
[InlineData("partSpacing")]
[InlineData("removed")]
[InlineData("explicit")]
[InlineData("detachedMatchingZones")]
[InlineData("differentRail")]
[InlineData("editedRailZones")]
[InlineData("cutOff")]
[InlineData("part")]
public void ChangePlateDefaults_PreservesEditedOrUsedTrailingSheet(string edit)
{
var nest = CreateNest();
var plate = nest.CreatePlate();
switch (edit)
{
// Even sub-tolerance changes are edits, not untouched defaults.
case "width": plate.Size = new Size(48 + 1e-9, 96); break;
case "length": plate.Size = new Size(48, 96 + 1e-9); break;
case "quadrant": plate.Quadrant = 2; break;
case "left": plate.EdgeSpacing.Left += 1e-9; break;
case "bottom": plate.EdgeSpacing.Bottom += 1e-9; break;
case "right": plate.EdgeSpacing.Right += 1e-9; break;
case "top": plate.EdgeSpacing.Top += 1e-9; break;
case "partSpacing": plate.PartSpacing += 1e-9; break;
case "removed": plate.SetClampRail(nest.PlateDefaults.ClampRail, new[] { "clamp-1" }); break;
case "explicit":
plate.SetClampRail(null!);
plate.ClampZones.Add(new ClampZone("manual", new Box(10, 0, 2, 1)));
break;
case "detachedMatchingZones":
var zones = plate.ClampZones.ToArray();
plate.SetClampRail(null!);
foreach (var zone in zones)
plate.ClampZones.Add(zone);
break;
case "differentRail":
plate.SetClampRail(new ClampRail(1.5, 0.625, new[] { 6.0, 81.0 }, removalMinutes: 8));
break;
case "editedRailZones":
plate.ClampZones.Clear();
plate.ClampZones.Add(new ClampZone("manual", new Box(10, 0, 2, 1)));
break;
case "cutOff": plate.CutOffs.Add(new CutOff(new Vector(40, 0), CutOffAxis.Vertical)); break;
case "part": plate.Parts.Add(new Part(new Drawing("block", new Program()))); break;
}
var size = plate.Size;
var quadrant = plate.Quadrant;
var spacing = plate.EdgeSpacing;
var partSpacing = plate.PartSpacing;
var rail = plate.ClampRail;
var removed = plate.RemovedClamps.ToArray();
var savedZones = plate.ClampZones.ToArray();
var parts = plate.Parts.ToArray();
var cutOffs = plate.CutOffs.ToArray();
using var manager = new PlateManager(nest);
var notifications = 0;
manager.CurrentPlateChanged += (_, _) => notifications++;
manager.PlateListChanged += (_, _) => notifications++;
manager.ChangePlateDefaults(() => ChangeDefaults(nest));
Assert.Equal(new Size(48, 60), nest.PlateDefaults.Size);
Assert.Same(plate, Assert.Single(nest.Plates));
Assert.Equal(size, plate.Size);
Assert.Equal(quadrant, plate.Quadrant);
Assert.Equal(spacing, plate.EdgeSpacing);
Assert.Equal(partSpacing, plate.PartSpacing);
Assert.Same(rail, plate.ClampRail);
Assert.Equal(removed, plate.RemovedClamps);
Assert.Equal(savedZones, plate.ClampZones);
Assert.Equal(parts, plate.Parts);
Assert.Equal(cutOffs, plate.CutOffs);
Assert.Equal(0, notifications);
}
[Fact]
public void ChangePlateDefaults_PreservesMiddleEmptySheetAndCurrentSelection()
{
var nest = CreateNest();
var middle = nest.CreatePlate();
var sentinel = nest.CreatePlate();
using var manager = new PlateManager(nest);
manager.LoadFirst();
var currentChanges = 0;
manager.CurrentPlateChanged += (_, _) => currentChanges++;
manager.ChangePlateDefaults(() => ChangeDefaults(nest));
Assert.Equal(2, nest.Plates.Count);
Assert.Equal(new Size(48, 96), middle.Size);
Assert.Equal(1, middle.Quadrant);
Assert.Equal(new Spacing(1, 2, 3, 4), middle.EdgeSpacing);
Assert.Equal(0.25, middle.PartSpacing);
Assert.Equal(2, middle.ClampZones.Count);
AssertMatchesDefaults(nest, sentinel);
Assert.Same(middle, manager.CurrentPlate);
Assert.Equal(0, currentChanges);
}
[Fact]
public void ChangePlateDefaults_SetFromExistingMovesOnlyTheSentinel()
{
var nest = CreateNest();
var selected = nest.CreatePlate();
selected.Size = new Size(48, 60);
selected.Quadrant = 3;
selected.EdgeSpacing = new Spacing(5, 6, 7, 8);
selected.PartSpacing = 0.5;
var sentinel = nest.CreatePlate();
using var manager = new PlateManager(nest);
manager.ChangePlateDefaults(() => nest.PlateDefaults.SetFromExisting(selected));
AssertMatchesDefaults(nest, sentinel);
AssertMatchesDefaults(nest, selected);
Assert.Equal(2, nest.Plates.Count);
Assert.Same(selected, manager.CurrentPlate);
}
[Fact]
public void ChangePlateDefaults_WithoutPlatesStillAppliesDefaults()
{
var nest = CreateNest();
using var manager = new PlateManager(nest);
manager.ChangePlateDefaults(() => ChangeDefaults(nest));
Assert.Empty(nest.Plates);
manager.EnsureSentinel();
AssertMatchesDefaults(nest, Assert.Single(nest.Plates));
}
}