From 5afb311ac719e95b46bfcdcd306735f24fce5e24 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 24 Mar 2026 11:58:00 -0400 Subject: [PATCH] feat: add ISplitFeature interface and StraightSplit implementation Co-Authored-By: Claude Sonnet 4.6 --- OpenNest.Core/Splitting/ISplitFeature.cs | 22 ++++++++ OpenNest.Core/Splitting/StraightSplit.cs | 22 ++++++++ OpenNest.Tests/Splitting/SplitFeatureTests.cs | 52 +++++++++++++++++++ 3 files changed, 96 insertions(+) create mode 100644 OpenNest.Core/Splitting/ISplitFeature.cs create mode 100644 OpenNest.Core/Splitting/StraightSplit.cs create mode 100644 OpenNest.Tests/Splitting/SplitFeatureTests.cs diff --git a/OpenNest.Core/Splitting/ISplitFeature.cs b/OpenNest.Core/Splitting/ISplitFeature.cs new file mode 100644 index 0000000..055d73d --- /dev/null +++ b/OpenNest.Core/Splitting/ISplitFeature.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using OpenNest.Geometry; + +namespace OpenNest; + +public class SplitFeatureResult +{ + public List NegativeSideEdge { get; } + public List PositiveSideEdge { get; } + + public SplitFeatureResult(List negativeSideEdge, List positiveSideEdge) + { + NegativeSideEdge = negativeSideEdge; + PositiveSideEdge = positiveSideEdge; + } +} + +public interface ISplitFeature +{ + string Name { get; } + SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters); +} diff --git a/OpenNest.Core/Splitting/StraightSplit.cs b/OpenNest.Core/Splitting/StraightSplit.cs new file mode 100644 index 0000000..5ef039d --- /dev/null +++ b/OpenNest.Core/Splitting/StraightSplit.cs @@ -0,0 +1,22 @@ +using System.Collections.Generic; +using OpenNest.Geometry; + +namespace OpenNest; + +public class StraightSplit : ISplitFeature +{ + public string Name => "Straight"; + + public SplitFeatureResult GenerateFeatures(SplitLine line, double extentStart, double extentEnd, SplitParameters parameters) + { + var (negEdge, posEdge) = line.Axis == CutOffAxis.Vertical + ? (new Line(new Vector(line.Position, extentStart), new Vector(line.Position, extentEnd)), + new Line(new Vector(line.Position, extentEnd), new Vector(line.Position, extentStart))) + : (new Line(new Vector(extentStart, line.Position), new Vector(extentEnd, line.Position)), + new Line(new Vector(extentEnd, line.Position), new Vector(extentStart, line.Position))); + + return new SplitFeatureResult( + new List { negEdge }, + new List { posEdge }); + } +} diff --git a/OpenNest.Tests/Splitting/SplitFeatureTests.cs b/OpenNest.Tests/Splitting/SplitFeatureTests.cs new file mode 100644 index 0000000..5818744 --- /dev/null +++ b/OpenNest.Tests/Splitting/SplitFeatureTests.cs @@ -0,0 +1,52 @@ +using OpenNest.Geometry; + +namespace OpenNest.Tests.Splitting; + +public class SplitFeatureTests +{ + [Fact] + public void StraightSplit_Vertical_ProducesSingleLineEachSide() + { + var feature = new StraightSplit(); + var line = new SplitLine(50.0, CutOffAxis.Vertical); + var parameters = new SplitParameters { Type = SplitType.Straight }; + + var result = feature.GenerateFeatures(line, 10.0, 90.0, parameters); + + Assert.Single(result.NegativeSideEdge); + var negLine = Assert.IsType(result.NegativeSideEdge[0]); + Assert.Equal(50.0, negLine.StartPoint.X, 6); + Assert.Equal(10.0, negLine.StartPoint.Y, 6); + Assert.Equal(50.0, negLine.EndPoint.X, 6); + Assert.Equal(90.0, negLine.EndPoint.Y, 6); + + Assert.Single(result.PositiveSideEdge); + var posLine = Assert.IsType(result.PositiveSideEdge[0]); + Assert.Equal(50.0, posLine.StartPoint.X, 6); + Assert.Equal(90.0, posLine.StartPoint.Y, 6); + Assert.Equal(50.0, posLine.EndPoint.X, 6); + Assert.Equal(10.0, posLine.EndPoint.Y, 6); + } + + [Fact] + public void StraightSplit_Horizontal_ProducesSingleLineEachSide() + { + var feature = new StraightSplit(); + var line = new SplitLine(40.0, CutOffAxis.Horizontal); + var parameters = new SplitParameters { Type = SplitType.Straight }; + + var result = feature.GenerateFeatures(line, 5.0, 95.0, parameters); + + var negLine = Assert.IsType(result.NegativeSideEdge[0]); + Assert.Equal(5.0, negLine.StartPoint.X, 6); + Assert.Equal(40.0, negLine.StartPoint.Y, 6); + Assert.Equal(95.0, negLine.EndPoint.X, 6); + Assert.Equal(40.0, negLine.EndPoint.Y, 6); + } + + [Fact] + public void StraightSplit_Name() + { + Assert.Equal("Straight", new StraightSplit().Name); + } +}