From 0651f185e3ddd4e2d84c72b1996b99d2ce12d3ba Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 17 Mar 2026 08:06:21 -0400 Subject: [PATCH] feat(core): add OctagonShape Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Core/Shapes/OctagonShape.cs | 34 ++++++++++++++++++++++ OpenNest.Tests/Shapes/OctagonShapeTests.cs | 34 ++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 OpenNest.Core/Shapes/OctagonShape.cs create mode 100644 OpenNest.Tests/Shapes/OctagonShapeTests.cs diff --git a/OpenNest.Core/Shapes/OctagonShape.cs b/OpenNest.Core/Shapes/OctagonShape.cs new file mode 100644 index 0000000..66a99ed --- /dev/null +++ b/OpenNest.Core/Shapes/OctagonShape.cs @@ -0,0 +1,34 @@ +using System.Collections.Generic; +using OpenNest.Geometry; + +namespace OpenNest.Shapes +{ + public class OctagonShape : ShapeDefinition + { + public double Width { get; set; } + + public override Drawing GetDrawing() + { + var center = Width / 2.0; + var circumRadius = Width / (2.0 * System.Math.Cos(System.Math.PI / 8.0)); + + var vertices = new Vector[8]; + for (var i = 0; i < 8; i++) + { + var angle = System.Math.PI / 8.0 + i * System.Math.PI / 4.0; + 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++) + { + var next = (i + 1) % 8; + entities.Add(new Line(vertices[i], vertices[next])); + } + + return CreateDrawing(entities); + } + } +} diff --git a/OpenNest.Tests/Shapes/OctagonShapeTests.cs b/OpenNest.Tests/Shapes/OctagonShapeTests.cs new file mode 100644 index 0000000..fe73d1b --- /dev/null +++ b/OpenNest.Tests/Shapes/OctagonShapeTests.cs @@ -0,0 +1,34 @@ +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); + } +}