From b7c7cecd75c47a0f339c9658f72ad08035390d3d Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Fri, 20 Mar 2026 20:09:48 -0400 Subject: [PATCH] feat: wire NfpSlideStrategy into BestFitFinder pipeline Replace RotationSlideStrategy with NfpSlideStrategy in BuildStrategies, and add integration tests covering the end-to-end FindBestFits pipeline. Co-Authored-By: Claude Sonnet 4.6 --- OpenNest.Engine/BestFit/BestFitFinder.cs | 4 +- OpenNest.Tests/NfpBestFitIntegrationTests.cs | 57 ++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 OpenNest.Tests/NfpBestFitIntegrationTests.cs diff --git a/OpenNest.Engine/BestFit/BestFitFinder.cs b/OpenNest.Engine/BestFit/BestFitFinder.cs index 95861b5..bc0c4b4 100644 --- a/OpenNest.Engine/BestFit/BestFitFinder.cs +++ b/OpenNest.Engine/BestFit/BestFitFinder.cs @@ -83,8 +83,8 @@ namespace OpenNest.Engine.BestFit foreach (var angle in angles) { - var desc = string.Format("{0:F1} deg rotated, offset slide", Angle.ToDegrees(angle)); - strategies.Add(new RotationSlideStrategy(angle, type++, desc, _slideComputer)); + var desc = $"{Angle.ToDegrees(angle):F1} deg NFP"; + strategies.Add(new NfpSlideStrategy(angle, type++, desc)); } return strategies; diff --git a/OpenNest.Tests/NfpBestFitIntegrationTests.cs b/OpenNest.Tests/NfpBestFitIntegrationTests.cs new file mode 100644 index 0000000..d47371b --- /dev/null +++ b/OpenNest.Tests/NfpBestFitIntegrationTests.cs @@ -0,0 +1,57 @@ +using OpenNest.CNC; +using OpenNest.Engine.BestFit; +using OpenNest.Geometry; + +namespace OpenNest.Tests; + +public class NfpBestFitIntegrationTests +{ + [Fact] + public void FindBestFits_ReturnsKeptResults_ForSquare() + { + var finder = new BestFitFinder(120, 60); + var drawing = TestHelpers.MakeSquareDrawing(); + var results = finder.FindBestFits(drawing); + Assert.NotEmpty(results); + Assert.NotEmpty(results.Where(r => r.Keep)); + } + + [Fact] + public void FindBestFits_ResultsHaveValidDimensions() + { + var finder = new BestFitFinder(120, 60); + var drawing = TestHelpers.MakeSquareDrawing(); + var results = finder.FindBestFits(drawing); + + foreach (var result in results.Where(r => r.Keep)) + { + Assert.True(result.BoundingWidth > 0); + Assert.True(result.BoundingHeight > 0); + Assert.True(result.RotatedArea > 0); + } + } + + [Fact] + public void FindBestFits_LShape_HasBetterUtilization_ThanBoundingBox() + { + var finder = new BestFitFinder(120, 60); + var drawing = TestHelpers.MakeLShapeDrawing(); + var results = finder.FindBestFits(drawing); + + var bestUtilization = results + .Where(r => r.Keep) + .Max(r => r.Utilization); + Assert.True(bestUtilization > 0.5); + } + + [Fact] + public void FindBestFits_NoOverlaps_InKeptResults() + { + var finder = new BestFitFinder(120, 60); + var drawing = TestHelpers.MakeSquareDrawing(); + var results = finder.FindBestFits(drawing); + + Assert.All(results.Where(r => r.Keep), r => + Assert.Equal("Valid", r.Reason)); + } +}