using OpenNest.Bending;
using OpenNest.CNC;
using OpenNest.Geometry;
using OpenNest.TabbedCutouts;
namespace OpenNest.IO.Tests;
/// A supplied blank's display perimeter must survive save/reload as never-cut geometry.
public class DisplayPerimeterPersistenceTests
{
private static Drawing Door()
{
var outline = new List
{
new Line(0, 0, 30, 0), new Line(30, 0, 30, 20), new Line(30, 20, 0, 20), new Line(0, 20, 0, 0),
};
foreach (var line in outline)
line.Layer = SpecialLayers.DisplayPerimeter;
var entities = new List(outline)
{
new Line(5, 5, 10, 5), new Line(10, 5, 10, 10), new Line(10, 10, 5, 10), new Line(5, 10, 5, 5),
};
return CadImporter.BuildDrawing(new CadImportResult { Entities = entities, Name = "door" },
entities, new List(), 1, null, null, null, new List());
}
private static int DisplayPerimeterMoves(Program program) =>
program.Codes.Count(code => code is LinearMove { Layer: LayerType.DisplayPerimeter } or ArcMove { Layer: LayerType.DisplayPerimeter });
[Fact]
public void RoundDisplayPerimeter_SurvivesSaveAndReloadAsAnArc()
{
var outline = new Circle(new Vector(10, 10), 10) { Layer = SpecialLayers.DisplayPerimeter };
var entities = new List
{
outline, new Line(8, 8, 12, 8), new Line(12, 8, 12, 12), new Line(12, 12, 8, 12), new Line(8, 12, 8, 8),
};
var drawing = CadImporter.BuildDrawing(new CadImportResult { Entities = entities, Name = "round" },
entities, new List(), 1, null, null, null, new List());
Assert.Contains(drawing.Program.Codes, c => c is ArcMove { Layer: LayerType.DisplayPerimeter });
var nest = new Nest("round") { Units = Units.Inches };
nest.Drawings.Add(drawing);
using var stream = new MemoryStream();
Assert.True(new NestWriter(nest).Write(stream));
var reread = Assert.Single(new NestReader(new MemoryStream(stream.ToArray())).Read().Drawings);
Assert.Contains(reread.Program.Codes, c => c is ArcMove { Layer: LayerType.DisplayPerimeter });
Assert.DoesNotContain(reread.Program.Codes, c => c is ArcMove { Layer: LayerType.Cut });
}
[Fact]
public void AppliedProgramTail_SurvivesSaveAndReload()
{
var drawing = Door();
var nest = new Nest("door") { Units = Units.Inches };
nest.Drawings.Add(drawing);
var plate = new Plate(new Size(20, 30));
var part = new Part(drawing, Vector.Zero);
plate.Parts.Add(part);
nest.Plates.Add(plate);
// An applied program as the planner installs it: the cut hole, then the never-cut tail.
var applied = new Program();
applied.Codes.Add(new RapidMove(5, 5));
foreach (var (x, y) in new[] { (5.0, 10.0), (10.0, 10.0), (10.0, 5.0), (5.0, 5.0) })
applied.Codes.Add(new LinearMove(x, y));
applied.Codes.Add(new Comment(DisplayPerimeterTail.Marker));
applied.Codes.Add(new RapidMove(0, 0));
foreach (var (x, arcY) in new[] { (30.0, 0.0), (30.0, 20.0), (0.0, 20.0), (0.0, 0.0) })
applied.Codes.Add(new LinearMove(x, arcY) { Layer = LayerType.DisplayPerimeter });
applied.Mode = Mode.Incremental;
Assert.True(part.RestoreLeadInProgram(applied, locked: true));
using var stream = new MemoryStream();
Assert.True(new NestWriter(nest).Write(stream));
var reader = new NestReader(new MemoryStream(stream.ToArray()));
var restored = Assert.Single(reader.Read().Plates.SelectMany(p => p.Parts));
Assert.Empty(reader.Warnings);
Assert.True(DisplayPerimeterTail.HasTail(restored.Program));
Assert.Equal(4, DisplayPerimeterMoves(restored.Program));
Assert.Equal(30, restored.BoundingBox.Length, 6);
Assert.False(DisplayPerimeterTail.HasDisplayPerimeterMotion(
DisplayPerimeterTail.ForPosting(restored.Program, "Part 1")));
}
[Fact]
public void DisplayPerimeter_SurvivesSaveAndReloadOnTheDrawingAndItsPlacements()
{
var drawing = Door();
Assert.Equal(4, DisplayPerimeterMoves(drawing.Program));
var nest = new Nest("door") { Units = Units.Inches };
nest.Drawings.Add(drawing);
var plate = new Plate(new Size(20, 30));
plate.Parts.Add(new Part(drawing, Vector.Zero));
nest.Plates.Add(plate);
using var stream = new MemoryStream();
Assert.True(new NestWriter(nest).Write(stream));
var reader = new NestReader(new MemoryStream(stream.ToArray()));
var restored = reader.Read();
Assert.Empty(reader.Warnings);
var reread = Assert.Single(restored.Drawings);
Assert.Equal(4, DisplayPerimeterMoves(reread.Program));
var outline = CadImporter.EditableEntities(reread).Where(e => e.Length > 19.9).ToList();
Assert.Equal(4, outline.Count);
Assert.All(outline, e => Assert.Same(SpecialLayers.DisplayPerimeter, e.Layer));
var part = Assert.Single(restored.Plates.SelectMany(p => p.Parts));
Assert.Equal(4, DisplayPerimeterMoves(part.Program));
}
}