using OpenNest.Converters; using OpenNest.Geometry; namespace OpenNest.Tests.Splitting; public class DrawingSplitterTests { /// /// Helper: creates a Drawing from a rectangular perimeter. /// private static Drawing MakeRectangleDrawing(string name, double width, double height) { var entities = new List { new Line(new Vector(0, 0), new Vector(width, 0)), new Line(new Vector(width, 0), new Vector(width, height)), new Line(new Vector(width, height), new Vector(0, height)), new Line(new Vector(0, height), new Vector(0, 0)) }; var pgm = ConvertGeometry.ToProgram(entities); return new Drawing(name, pgm); } [Fact] public void Split_Rectangle_Vertical_ProducesTwoPieces() { var drawing = MakeRectangleDrawing("RECT", 100, 50); var splitLines = new List { new SplitLine(50.0, CutOffAxis.Vertical) }; var parameters = new SplitParameters { Type = SplitType.Straight }; var results = DrawingSplitter.Split(drawing, splitLines, parameters); Assert.Equal(2, results.Count); Assert.Equal("RECT-1", results[0].Name); Assert.Equal("RECT-2", results[1].Name); // Each piece should have area close to half the original var totalArea = results.Sum(d => d.Area); Assert.Equal(drawing.Area, totalArea, 1); } [Fact] public void Split_Rectangle_Horizontal_ProducesTwoPieces() { var drawing = MakeRectangleDrawing("RECT", 100, 60); var splitLines = new List { new SplitLine(30.0, CutOffAxis.Horizontal) }; var parameters = new SplitParameters { Type = SplitType.Straight }; var results = DrawingSplitter.Split(drawing, splitLines, parameters); Assert.Equal(2, results.Count); Assert.Equal("RECT-1", results[0].Name); Assert.Equal("RECT-2", results[1].Name); } [Fact] public void Split_ThreePieces_NamesSequentially() { var drawing = MakeRectangleDrawing("PART", 150, 50); var splitLines = new List { new SplitLine(50.0, CutOffAxis.Vertical), new SplitLine(100.0, CutOffAxis.Vertical) }; var parameters = new SplitParameters { Type = SplitType.Straight }; var results = DrawingSplitter.Split(drawing, splitLines, parameters); Assert.Equal(3, results.Count); Assert.Equal("PART-1", results[0].Name); Assert.Equal("PART-2", results[1].Name); Assert.Equal("PART-3", results[2].Name); } [Fact] public void Split_CopiesDrawingProperties() { var drawing = MakeRectangleDrawing("PART", 100, 50); drawing.Color = System.Drawing.Color.Red; drawing.Priority = 5; var results = DrawingSplitter.Split(drawing, new List { new SplitLine(50.0, CutOffAxis.Vertical) }, new SplitParameters()); Assert.All(results, d => { Assert.Equal(System.Drawing.Color.Red, d.Color); Assert.Equal(5, d.Priority); }); } [Fact] public void Split_PiecesNormalizedToOrigin() { var drawing = MakeRectangleDrawing("PART", 100, 50); var results = DrawingSplitter.Split(drawing, new List { new SplitLine(50.0, CutOffAxis.Vertical) }, new SplitParameters()); // Each piece's program bounding box should start near (0,0) foreach (var d in results) { var bb = d.Program.BoundingBox(); Assert.True(bb.X < 1.0, $"Piece {d.Name} not normalized: X={bb.X}"); Assert.True(bb.Y < 1.0, $"Piece {d.Name} not normalized: Y={bb.Y}"); } } [Fact] public void Split_WithCutout_AssignsCutoutToCorrectPiece() { // Rectangle 100x50 with a small square cutout at (20,20)-(30,30) var perimeterEntities = new List { new Line(new Vector(0, 0), new Vector(100, 0)), new Line(new Vector(100, 0), new Vector(100, 50)), new Line(new Vector(100, 50), new Vector(0, 50)), new Line(new Vector(0, 50), new Vector(0, 0)) }; var cutoutEntities = new List { new Line(new Vector(20, 20), new Vector(30, 20)), new Line(new Vector(30, 20), new Vector(30, 30)), new Line(new Vector(30, 30), new Vector(20, 30)), new Line(new Vector(20, 30), new Vector(20, 20)) }; var allEntities = new List(); allEntities.AddRange(perimeterEntities); allEntities.AddRange(cutoutEntities); var pgm = ConvertGeometry.ToProgram(allEntities); var drawing = new Drawing("HOLE", pgm); // Split at X=50 — cutout is in the left half var results = DrawingSplitter.Split(drawing, new List { new SplitLine(50.0, CutOffAxis.Vertical) }, new SplitParameters()); Assert.Equal(2, results.Count); // Left piece should have smaller area (has the cutout) Assert.True(results[0].Area < results[1].Area, "Left piece should have less area due to cutout"); } [Fact] public void Split_GridSplit_ProducesFourPieces() { var drawing = MakeRectangleDrawing("GRID", 100, 100); var splitLines = new List { new SplitLine(50.0, CutOffAxis.Vertical), new SplitLine(50.0, CutOffAxis.Horizontal) }; var results = DrawingSplitter.Split(drawing, splitLines, new SplitParameters()); Assert.Equal(4, results.Count); Assert.Equal("GRID-1", results[0].Name); Assert.Equal("GRID-2", results[1].Name); Assert.Equal("GRID-3", results[2].Name); Assert.Equal("GRID-4", results[3].Name); } }