From c2a470f79cf7db8127a23891b6ca60c0355a07f8 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 24 Mar 2026 20:18:52 -0400 Subject: [PATCH] feat: add Bend domain model and BendDirection enum to OpenNest.Core Introduces OpenNest.Core/Bending/ with Bend and BendDirection types as the foundation for bend line detection. Includes 6 passing unit tests. Co-Authored-By: Claude Sonnet 4.6 --- OpenNest.Core/Bending/Bend.cs | 37 ++++++++++ OpenNest.Core/Bending/BendDirection.cs | 9 +++ OpenNest.Tests/Bending/BendModelTests.cs | 90 ++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 OpenNest.Core/Bending/Bend.cs create mode 100644 OpenNest.Core/Bending/BendDirection.cs create mode 100644 OpenNest.Tests/Bending/BendModelTests.cs diff --git a/OpenNest.Core/Bending/Bend.cs b/OpenNest.Core/Bending/Bend.cs new file mode 100644 index 0000000..cb3776e --- /dev/null +++ b/OpenNest.Core/Bending/Bend.cs @@ -0,0 +1,37 @@ +using OpenNest.Geometry; +using OpenNest.Math; + +namespace OpenNest.Bending +{ + public class Bend + { + public Vector StartPoint { get; set; } + public Vector EndPoint { get; set; } + public BendDirection Direction { get; set; } + public double? Angle { get; set; } + public double? Radius { get; set; } + public string NoteText { get; set; } + + public double Length => StartPoint.DistanceTo(EndPoint); + + public double AngleRadians => Angle.HasValue + ? OpenNest.Math.Angle.ToRadians(Angle.Value) + : 0; + + public Line ToLine() => new Line(StartPoint, EndPoint); + + /// + /// Returns the angle of the bend line itself (not the bend angle). + /// Used for grain direction comparison. + /// + public double LineAngle => StartPoint.AngleTo(EndPoint); + + public override string ToString() + { + var dir = Direction.ToString(); + var angle = Angle?.ToString("0.##") ?? "?"; + var radius = Radius?.ToString("0.###") ?? "?"; + return $"{dir} {angle}° R{radius}"; + } + } +} diff --git a/OpenNest.Core/Bending/BendDirection.cs b/OpenNest.Core/Bending/BendDirection.cs new file mode 100644 index 0000000..2ac60d7 --- /dev/null +++ b/OpenNest.Core/Bending/BendDirection.cs @@ -0,0 +1,9 @@ +namespace OpenNest.Bending +{ + public enum BendDirection + { + Unknown, + Up, + Down + } +} diff --git a/OpenNest.Tests/Bending/BendModelTests.cs b/OpenNest.Tests/Bending/BendModelTests.cs new file mode 100644 index 0000000..021ff59 --- /dev/null +++ b/OpenNest.Tests/Bending/BendModelTests.cs @@ -0,0 +1,90 @@ +using OpenNest.Bending; +using OpenNest.Geometry; + +namespace OpenNest.Tests.Bending; + +public class BendModelTests +{ + [Fact] + public void Bend_StoresStartAndEndPoints() + { + var bend = 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" + }; + + Assert.Equal(0, bend.StartPoint.X); + Assert.Equal(10, bend.EndPoint.X); + Assert.Equal(BendDirection.Up, bend.Direction); + Assert.Equal(90, bend.Angle); + Assert.Equal(0.06, bend.Radius); + Assert.Equal("UP 90° R0.06", bend.NoteText); + } + + [Fact] + public void Bend_ToLine_ReturnsGeometryLine() + { + var bend = new Bend + { + StartPoint = new Vector(0, 5), + EndPoint = new Vector(10, 5) + }; + + var line = bend.ToLine(); + + Assert.Equal(0, line.StartPoint.X); + Assert.Equal(5, line.StartPoint.Y); + Assert.Equal(10, line.EndPoint.X); + Assert.Equal(5, line.EndPoint.Y); + } + + [Fact] + public void Bend_Length_ComputesCorrectly() + { + var bend = new Bend + { + StartPoint = new Vector(0, 0), + EndPoint = new Vector(3, 4) + }; + + Assert.Equal(5.0, bend.Length, 0.001); + } + + [Fact] + public void Bend_BendAngleRadians_ConvertsDegreesToRadians() + { + var bend = new Bend { Angle = 90 }; + + Assert.Equal(System.Math.PI / 2, bend.AngleRadians, 0.001); + } + + [Fact] + public void Bend_DefaultDirection_IsUnknown() + { + var bend = new Bend(); + + Assert.Equal(BendDirection.Unknown, bend.Direction); + } + + [Fact] + public void Bend_ToString_FormatsNicely() + { + var bend = new Bend + { + Direction = BendDirection.Up, + Angle = 90, + Radius = 0.06 + }; + + var str = bend.ToString(); + + Assert.Contains("Up", str); + Assert.Contains("90", str); + Assert.Contains("0.06", str); + } +}