diff --git a/OpenNest.IO/NestFormat.cs b/OpenNest.IO/NestFormat.cs index 3c8c086..26b01af 100644 --- a/OpenNest.IO/NestFormat.cs +++ b/OpenNest.IO/NestFormat.cs @@ -50,6 +50,7 @@ namespace OpenNest.IO public ConstraintsDto Constraints { get; init; } = new(); public MaterialDto Material { get; init; } = new(); public SourceDto Source { get; init; } = new(); + public List Bends { get; init; } = new(); } public record PlateDto @@ -62,6 +63,7 @@ namespace OpenNest.IO public double PartSpacing { get; init; } public MaterialDto Material { get; init; } = new(); public SpacingDto EdgeSpacing { get; init; } = new(); + public double GrainAngle { get; init; } public List Parts { get; init; } = new(); public List CutOffs { get; init; } = new(); } @@ -137,6 +139,18 @@ namespace OpenNest.IO public double Y { get; init; } } + public record BendDto + { + public double StartX { get; init; } + public double StartY { get; init; } + public double EndX { get; init; } + public double EndY { get; init; } + public string Direction { get; init; } = "Unknown"; + public double? Angle { get; init; } + public double? Radius { get; init; } + public string NoteText { get; init; } = ""; + } + public record BestFitSetDto { public double PlateWidth { get; init; } diff --git a/OpenNest.IO/NestReader.cs b/OpenNest.IO/NestReader.cs index 805d8d9..9a35d19 100644 --- a/OpenNest.IO/NestReader.cs +++ b/OpenNest.IO/NestReader.cs @@ -1,3 +1,4 @@ +using OpenNest.Bending; using OpenNest.CNC; using OpenNest.Engine.BestFit; using OpenNest.Geometry; @@ -91,6 +92,23 @@ namespace OpenNest.IO drawing.Source.Path = d.Source.Path; drawing.Source.Offset = new Vector(d.Source.Offset.X, d.Source.Offset.Y); + if (d.Bends != null) + { + foreach (var b in d.Bends) + { + drawing.Bends.Add(new Bend + { + StartPoint = new Vector(b.StartX, b.StartY), + EndPoint = new Vector(b.EndX, b.EndY), + Direction = Enum.TryParse(b.Direction, true, out var dir) + ? dir : BendDirection.Unknown, + Angle = b.Angle, + Radius = b.Radius, + NoteText = b.NoteText + }); + } + } + if (programs.TryGetValue(d.Id, out var pgm)) drawing.Program = pgm; @@ -186,6 +204,7 @@ namespace OpenNest.IO plate.PartSpacing = p.PartSpacing; plate.Material = new Material(p.Material.Name, p.Material.Grade, p.Material.Density); plate.EdgeSpacing = new Spacing(p.EdgeSpacing.Left, p.EdgeSpacing.Bottom, p.EdgeSpacing.Right, p.EdgeSpacing.Top); + plate.GrainAngle = p.GrainAngle; foreach (var partDto in p.Parts) { diff --git a/OpenNest.IO/NestWriter.cs b/OpenNest.IO/NestWriter.cs index 2316b30..f66ecb4 100644 --- a/OpenNest.IO/NestWriter.cs +++ b/OpenNest.IO/NestWriter.cs @@ -1,3 +1,4 @@ +using OpenNest.Bending; using OpenNest.CNC; using OpenNest.Engine.BestFit; using System; @@ -140,7 +141,18 @@ namespace OpenNest.IO { Path = d.Source.Path ?? "", Offset = new OffsetDto { X = d.Source.Offset.X, Y = d.Source.Offset.Y } - } + }, + Bends = d.Bends?.Select(b => new BendDto + { + StartX = b.StartPoint.X, + StartY = b.StartPoint.Y, + EndX = b.EndPoint.X, + EndY = b.EndPoint.Y, + Direction = b.Direction.ToString(), + Angle = b.Angle, + Radius = b.Radius, + NoteText = b.NoteText ?? "" + }).ToList() ?? new List() }); } return list; @@ -200,7 +212,8 @@ namespace OpenNest.IO Bottom = plate.EdgeSpacing.Bottom }, Parts = parts, - CutOffs = cutoffs + CutOffs = cutoffs, + GrainAngle = plate.GrainAngle }); } return list; diff --git a/OpenNest.Tests/NestBendSerializationTests.cs b/OpenNest.Tests/NestBendSerializationTests.cs new file mode 100644 index 0000000..7fe2414 --- /dev/null +++ b/OpenNest.Tests/NestBendSerializationTests.cs @@ -0,0 +1,91 @@ +using OpenNest.Bending; +using OpenNest.Geometry; +using OpenNest.IO; +using System.Linq; + +namespace OpenNest.Tests; + +public class NestBendSerializationTests +{ + [Fact] + public void Bends_SurviveNestRoundtrip() + { + var drawing = TestHelpers.MakeSquareDrawing(); + drawing.Bends.Add(new Bend + { + StartPoint = new Vector(0, 5), + EndPoint = new Vector(10, 5), + Direction = BendDirection.Up, + Angle = 90, + Radius = 0.06, + NoteText = "UP 90° R0.06" + }); + drawing.Bends.Add(new Bend + { + StartPoint = new Vector(0, 3), + EndPoint = new Vector(10, 3), + Direction = BendDirection.Down, + Angle = 45.5, + Radius = 0.125, + NoteText = "DOWN 45.5° R0.125" + }); + + var nest = new Nest(); + nest.Drawings.Add(drawing); + var plate = new Plate(60, 120); + plate.GrainAngle = 0.5236; + plate.Parts.Add(new Part(drawing, new Vector(0, 0))); + nest.Plates.Add(plate); + + using var ms = new MemoryStream(); + var writer = new NestWriter(nest); + writer.Write(ms); + + ms.Position = 0; + var reader = new NestReader(ms); + var loaded = reader.Read(); + + var loadedDrawing = loaded.Drawings.First(); + Assert.Equal(2, loadedDrawing.Bends.Count); + + var bend1 = loadedDrawing.Bends[0]; + Assert.Equal(0, bend1.StartPoint.X, 0.001); + Assert.Equal(5, bend1.StartPoint.Y, 0.001); + Assert.Equal(10, bend1.EndPoint.X, 0.001); + Assert.Equal(5, bend1.EndPoint.Y, 0.001); + Assert.Equal(BendDirection.Up, bend1.Direction); + Assert.Equal(90, bend1.Angle); + Assert.Equal(0.06, bend1.Radius); + Assert.Equal("UP 90° R0.06", bend1.NoteText); + + var bend2 = loadedDrawing.Bends[1]; + Assert.Equal(BendDirection.Down, bend2.Direction); + Assert.Equal(45.5, bend2.Angle); + + var loadedPlate = loaded.Plates[0]; + Assert.Equal(0.5236, loadedPlate.GrainAngle, 0.0001); + } + + [Fact] + public void NoBends_SurviveNestRoundtrip() + { + var drawing = TestHelpers.MakeSquareDrawing(); + + var nest = new Nest(); + nest.Drawings.Add(drawing); + var plate = new Plate(60, 120); + plate.Parts.Add(new Part(drawing, new Vector(0, 0))); + nest.Plates.Add(plate); + + using var ms = new MemoryStream(); + var writer = new NestWriter(nest); + writer.Write(ms); + + ms.Position = 0; + var reader = new NestReader(ms); + var loaded = reader.Read(); + + Assert.Empty(loaded.Drawings.First().Bends); + Assert.Equal(0, loaded.Plates[0].GrainAngle); + } +}