mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-13 23:55:08 -05:00
172 lines
6.7 KiB
C#
172 lines
6.7 KiB
C#
using OpenNest.Clamps;
|
|
using OpenNest.Engine.Jobs;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Engine.Tests.Jobs;
|
|
|
|
/// <summary>
|
|
/// A committed live plate must carry exactly the clamp keep-outs its layout was solved and
|
|
/// validated against, in plate coordinates, including sheets the commit had to create.
|
|
/// </summary>
|
|
public class ClampZoneCommitTests
|
|
{
|
|
// A 1.5 x 0.625 clamp on the front edge of a 48 x 96 sheet (Length 96 runs along X).
|
|
private const double ZoneX = 5.25;
|
|
|
|
private static ClampZone Zone() => new("clamp-1", new Box(ZoneX, 0, 1.5, 0.625));
|
|
|
|
/// <summary>Two different one-part sheets so repeat grouping cannot merge them.</summary>
|
|
private sealed class TwoSheetStub : INestingEngine
|
|
{
|
|
public NestJobResult Solve(NestJob job, IProgress<NestJobProgress>? progress = null,
|
|
CancellationToken token = default)
|
|
{
|
|
var stock = job.Plates[0];
|
|
var work = stock.WorkArea;
|
|
var builder = new NestJobResultBuilder(job);
|
|
builder.AddSheet(stock, new[] { (job.Parts[0].Id, work.Left + 20, work.Bottom + 10, 0.0) });
|
|
builder.AddSheet(stock, new[] { (job.Parts[0].Id, work.Left + 40, work.Bottom + 20, 0.0) });
|
|
return builder.Build(NestJobStopReason.Completed);
|
|
}
|
|
}
|
|
|
|
private static NestPipelineResult Result(Drawing drawing, int quadrant, params ClampZone[] zones)
|
|
{
|
|
var result = NestPipeline.Run(new TwoSheetStub(), "stub", new NestPipelineRequest("stub",
|
|
new[] { new NestItem { Drawing = drawing, Quantity = 2 } },
|
|
new[]
|
|
{
|
|
new NestPlateStock("sheet", new Size(48, 96), null, 0.25, new Spacing(1, 1, 1, 1),
|
|
quadrant, cost: null, clampZones: zones),
|
|
}));
|
|
Assert.True(result.IsValid, string.Join("; ", result.Violations));
|
|
Assert.Equal(2, result.Plates.Count);
|
|
return result;
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1)]
|
|
[InlineData(2)]
|
|
[InlineData(3)]
|
|
[InlineData(4)]
|
|
public void EveryCommittedPlateCarriesTheSolvedZonesInPlateCoordinates(int quadrant)
|
|
{
|
|
var drawing = new Drawing("part", TestDrawingFactory.Rectangle());
|
|
var nest = new Nest();
|
|
nest.Drawings.Add(drawing);
|
|
nest.CreatePlate(); // empty template without zones; the second sheet is created by commit
|
|
using var manager = new PlateManager(nest);
|
|
|
|
var applied = NestPipelineCommit.ApplyToEmptyPlates(Result(drawing, quadrant, Zone()), manager);
|
|
|
|
Assert.Equal(2, applied.Count);
|
|
Assert.All(applied, plate =>
|
|
{
|
|
var zone = Assert.Single(plate.ClampZones);
|
|
Assert.Equal("clamp-1", zone.Id);
|
|
// Exact bits: the inverse of the stock's placement-frame translation.
|
|
Assert.Equal(ZoneX, zone.Bounds.X);
|
|
Assert.Equal(0, zone.Bounds.Y);
|
|
Assert.Equal(1.5, zone.Bounds.Length);
|
|
Assert.Equal(0.625, zone.Bounds.Width);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchingPlateZonesAreKeptWithoutChangeEvents()
|
|
{
|
|
var drawing = new Drawing("part", TestDrawingFactory.Rectangle());
|
|
var nest = new Nest();
|
|
nest.Drawings.Add(drawing);
|
|
var template = nest.CreatePlate();
|
|
template.Quadrant = 3;
|
|
template.Size = new Size(48, 96);
|
|
var original = Zone();
|
|
template.ClampZones.Add(original);
|
|
var changes = 0;
|
|
template.ClampZonesChanged += (_, _) => changes++;
|
|
using var manager = new PlateManager(nest);
|
|
|
|
var applied = NestPipelineCommit.ApplyToEmptyPlates(Result(drawing, 3, Zone()), manager);
|
|
|
|
Assert.Same(template, applied[0]);
|
|
Assert.Same(original, Assert.Single(template.ClampZones));
|
|
Assert.Equal(0, changes);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(1)]
|
|
[InlineData(2)]
|
|
[InlineData(3)]
|
|
[InlineData(4)]
|
|
public void SolvedZonesARailCannotRecreateStopFollowingThatRail(int quadrant)
|
|
{
|
|
// The nest rail puts a clamp at 6"; the template carries a different explicit zone,
|
|
// so the extra sheet the commit creates must not keep following the nest rail.
|
|
var drawing = new Drawing("part", TestDrawingFactory.Rectangle());
|
|
var nest = new Nest();
|
|
nest.Drawings.Add(drawing);
|
|
nest.PlateDefaults.Size = new Size(48, 96);
|
|
nest.PlateDefaults.Quadrant = quadrant;
|
|
nest.SetClampRail(new ClampRail(1.5, 0.625, new[] { 6.0 }));
|
|
var template = nest.CreatePlate();
|
|
template.SetClampRail(null!);
|
|
var manual = new ClampZone("manual", new Box(10, 0, 2, 0.5));
|
|
template.ClampZones.Add(manual);
|
|
using var manager = new PlateManager(nest);
|
|
|
|
var applied = NestPipelineCommit.ApplyToEmptyPlates(
|
|
Result(drawing, quadrant, template.ClampZones.ToArray()), manager);
|
|
|
|
Assert.Equal(2, applied.Count);
|
|
Assert.All(applied, plate =>
|
|
{
|
|
Assert.Null(plate.ClampRail);
|
|
plate.Size = plate.Size; // the Edit Plate dialog assigns Size even when unchanged
|
|
plate.Quadrant = plate.Quadrant;
|
|
Assert.Equal("manual", Assert.Single(plate.ClampZones).Id);
|
|
Assert.Equal("manual", Assert.Single(Assert.Single(
|
|
NestStockBuilder.FromTemplate(plate, [new PlateOption { Width = 48, Length = 96 }])).ClampZones).Id);
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void SolvedZonesTheRailRecreatesKeepFollowingIt()
|
|
{
|
|
var drawing = new Drawing("part", TestDrawingFactory.Rectangle());
|
|
var nest = new Nest();
|
|
nest.Drawings.Add(drawing);
|
|
nest.PlateDefaults.Size = new Size(48, 96);
|
|
var rail = new ClampRail(1.5, 0.625, new[] { 6.0 });
|
|
nest.SetClampRail(rail);
|
|
var template = nest.CreatePlate();
|
|
using var manager = new PlateManager(nest);
|
|
|
|
var applied = NestPipelineCommit.ApplyToEmptyPlates(
|
|
Result(drawing, 1, template.ClampZones.ToArray()), manager);
|
|
|
|
Assert.Equal(2, applied.Count);
|
|
Assert.All(applied, plate =>
|
|
{
|
|
Assert.Same(rail, plate.ClampRail);
|
|
plate.Size = new Size(48, 4);
|
|
Assert.Empty(plate.ClampZones); // still re-resolves: no clamp reaches a 4" sheet
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public void ZonesTheLayoutWasNotSolvedWithAreRemoved()
|
|
{
|
|
var drawing = new Drawing("part", TestDrawingFactory.Rectangle());
|
|
var nest = new Nest();
|
|
nest.Drawings.Add(drawing);
|
|
var template = nest.CreatePlate();
|
|
template.ClampZones.Add(Zone());
|
|
using var manager = new PlateManager(nest);
|
|
|
|
var applied = NestPipelineCommit.ApplyToEmptyPlates(Result(drawing, 1), manager);
|
|
|
|
Assert.All(applied, plate => Assert.Empty(plate.ClampZones));
|
|
}
|
|
}
|