diff --git a/OpenNest.Core/Geometry/Entity.cs b/OpenNest.Core/Geometry/Entity.cs index d32702d..ef80316 100644 --- a/OpenNest.Core/Geometry/Entity.cs +++ b/OpenNest.Core/Geometry/Entity.cs @@ -247,7 +247,7 @@ namespace OpenNest.Geometry public static class EntityExtensions { - public static BoundingRectangleResult FindBestRotation(this List entities, double startAngle = 0, double endAngle = Angle.TwoPI) + public static List CollectPoints(this IEnumerable entities) { var points = new List(); @@ -286,17 +286,35 @@ namespace OpenNest.Geometry case EntityType.Shape: var shape = (Shape)entity; - var subResult = shape.Entities.FindBestRotation(startAngle, endAngle); - return subResult; + points.AddRange(shape.Entities.CollectPoints()); + break; } } + return points; + } + + public static BoundingRectangleResult FindBestRotation(this List entities, double startAngle = 0, double endAngle = Angle.TwoPI) + { + // Check for Shape entity first (recursive case returns early) + foreach (var entity in entities) + { + if (entity.Type == EntityType.Shape) + { + var shape = (Shape)entity; + var subResult = shape.Entities.FindBestRotation(startAngle, endAngle); + return subResult; + } + } + + var points = entities.CollectPoints(); + if (points.Count == 0) return new BoundingRectangleResult(startAngle, 0, 0); var hull = ConvexHull.Compute(points); - bool constrained = !startAngle.IsEqualTo(0) || !endAngle.IsEqualTo(Angle.TwoPI); + var constrained = !startAngle.IsEqualTo(0) || !endAngle.IsEqualTo(Angle.TwoPI); return constrained ? RotatingCalipers.MinimumBoundingRectangle(hull, startAngle, endAngle) diff --git a/OpenNest.Tests/CutOffGeometryTests.cs b/OpenNest.Tests/CutOffGeometryTests.cs index a938a1f..5e1315f 100644 --- a/OpenNest.Tests/CutOffGeometryTests.cs +++ b/OpenNest.Tests/CutOffGeometryTests.cs @@ -321,6 +321,21 @@ public class CutOffGeometryTests Assert.Equal(6, cutoff.Drawing.Program.Codes.Count); } + [Fact] + public void CollectPoints_LinesAndArcs_ReturnsAllPoints() + { + var entities = new List + { + new Line(new Vector(0, 0), new Vector(10, 0)), + new Arc(new Vector(5, 5), 5, 0, System.Math.PI) + }; + + var points = entities.CollectPoints(); + + // Line: 2 points. Arc: 2 endpoints + 4 cardinals = 6. Total = 8. + Assert.Equal(8, points.Count); + } + [Fact] public void ShapeProfile_SelectsLargestShapeAsPerimeter() {