diff --git a/OpenNest.Core/Shapes/OctagonShape.cs b/OpenNest.Core/Shapes/NgonShape.cs similarity index 63% rename from OpenNest.Core/Shapes/OctagonShape.cs rename to OpenNest.Core/Shapes/NgonShape.cs index d0539fb..ee631c7 100644 --- a/OpenNest.Core/Shapes/OctagonShape.cs +++ b/OpenNest.Core/Shapes/NgonShape.cs @@ -3,33 +3,38 @@ using System.Collections.Generic; namespace OpenNest.Shapes { - public class OctagonShape : ShapeDefinition + public class NgonShape : ShapeDefinition { + public int Sides { get; set; } public double Width { get; set; } public override void SetPreviewDefaults() { + Sides = 8; Width = 8; } public override Drawing GetDrawing() { + var n = Sides < 3 ? 3 : Sides; var center = Width / 2.0; - var circumRadius = Width / (2.0 * System.Math.Cos(System.Math.PI / 8.0)); + var circumRadius = Width / (2.0 * System.Math.Cos(System.Math.PI / n)); + var step = 2.0 * System.Math.PI / n; + var start = System.Math.PI / n; - var vertices = new Vector[8]; - for (var i = 0; i < 8; i++) + var vertices = new Vector[n]; + for (var i = 0; i < n; i++) { - var angle = System.Math.PI / 8.0 + i * System.Math.PI / 4.0; + var angle = start + i * step; vertices[i] = new Vector( center + circumRadius * System.Math.Cos(angle), center + circumRadius * System.Math.Sin(angle)); } var entities = new List(); - for (var i = 0; i < 8; i++) + for (var i = 0; i < n; i++) { - var next = (i + 1) % 8; + var next = (i + 1) % n; entities.Add(new Line(vertices[i], vertices[next])); } diff --git a/OpenNest.Tests/Shapes/NgonShapeTests.cs b/OpenNest.Tests/Shapes/NgonShapeTests.cs new file mode 100644 index 0000000..1610198 --- /dev/null +++ b/OpenNest.Tests/Shapes/NgonShapeTests.cs @@ -0,0 +1,51 @@ +using OpenNest.Shapes; + +namespace OpenNest.Tests.Shapes; + +public class NgonShapeTests +{ + [Fact] + public void GetDrawing_Octagon_BoundingBoxFitsWithinExpectedSize() + { + var shape = new NgonShape { Sides = 8, Width = 20 }; + var drawing = shape.GetDrawing(); + + var bbox = drawing.Program.BoundingBox(); + // Corner-to-corner is larger than flat-to-flat + Assert.True(bbox.Width >= 20 - 0.01); + Assert.True(bbox.Length >= 20 - 0.01); + // But should not be wildly larger (corner-to-corner ~ width / cos(22.5deg) ~ width * 1.0824) + Assert.True(bbox.Width < 22); + Assert.True(bbox.Length < 22); + } + + [Theory] + [InlineData(3)] + [InlineData(4)] + [InlineData(5)] + [InlineData(6)] + [InlineData(8)] + [InlineData(12)] + public void GetDrawing_HasOneLinearMovePerSide(int sides) + { + var shape = new NgonShape { Sides = sides, Width = 20 }; + var drawing = shape.GetDrawing(); + + var moves = drawing.Program.Codes + .OfType() + .Count(); + Assert.Equal(sides, moves); + } + + [Fact] + public void GetDrawing_ClampsSidesBelowThreeToTriangle() + { + var shape = new NgonShape { Sides = 2, Width = 20 }; + var drawing = shape.GetDrawing(); + + var moves = drawing.Program.Codes + .OfType() + .Count(); + Assert.Equal(3, moves); + } +} diff --git a/OpenNest.Tests/Shapes/OctagonShapeTests.cs b/OpenNest.Tests/Shapes/OctagonShapeTests.cs deleted file mode 100644 index fe73d1b..0000000 --- a/OpenNest.Tests/Shapes/OctagonShapeTests.cs +++ /dev/null @@ -1,34 +0,0 @@ -using OpenNest.Shapes; - -namespace OpenNest.Tests.Shapes; - -public class OctagonShapeTests -{ - [Fact] - public void GetDrawing_BoundingBoxFitsWithinExpectedSize() - { - var shape = new OctagonShape { Width = 20 }; - var drawing = shape.GetDrawing(); - - var bbox = drawing.Program.BoundingBox(); - // Corner-to-corner is larger than flat-to-flat - Assert.True(bbox.Width >= 20 - 0.01); - Assert.True(bbox.Length >= 20 - 0.01); - // But should not be wildly larger (corner-to-corner ~ width / cos(22.5deg) ~ width * 1.0824) - Assert.True(bbox.Width < 22); - Assert.True(bbox.Length < 22); - } - - [Fact] - public void GetDrawing_HasEightEdges() - { - var shape = new OctagonShape { Width = 20 }; - var drawing = shape.GetDrawing(); - - // An octagon program should have 8 linear moves (one per edge) - var moves = drawing.Program.Codes - .OfType() - .Count(); - Assert.Equal(8, moves); - } -}