From 8c57e432210127d79fca02423545487f234e0e85 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Fri, 20 Mar 2026 20:59:53 -0400 Subject: [PATCH] fix: use NoFitPolygon.Compute with hull inputs instead of direct ConvexMinkowskiSum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling ConvexMinkowskiSum directly with manual reflection produced wrong winding/reference-point handling, causing all pairs to overlap. Route through Compute which handles reflection correctly. Hull inputs keep it fast — few triangles means trivial Clipper union. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Engine/BestFit/NfpSlideStrategy.cs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/OpenNest.Engine/BestFit/NfpSlideStrategy.cs b/OpenNest.Engine/BestFit/NfpSlideStrategy.cs index 589d746..9211f22 100644 --- a/OpenNest.Engine/BestFit/NfpSlideStrategy.cs +++ b/OpenNest.Engine/BestFit/NfpSlideStrategy.cs @@ -32,23 +32,17 @@ namespace OpenNest.Engine.BestFit if (stationaryResult.Polygon == null) return candidates; - // Use convex hulls for NFP computation — avoids expensive - // triangulation + Clipper2 union for concave parts. - // Convex-convex Minkowski sum is O(n+m) with no boolean ops. + // Use convex hulls for NFP — avoids expensive triangulation of + // concave parts. Hull inputs produce few triangles, so the + // Minkowski sum + Clipper union inside Compute stays fast. var stationaryPoly = ConvexHull.Compute(stationaryResult.Polygon.Vertices); // Orbiting polygon: same shape rotated to Part2's angle, then hulled. var rotated = PolygonHelper.RotatePolygon(stationaryResult.Polygon, _part2Rotation); var orbitingPoly = ConvexHull.Compute(rotated.Vertices); - // Compute NFP directly via convex Minkowski sum — O(n+m), no Clipper union. - // NFP(A, B) = MinkowskiSum(A, -B) for convex polygons. - var reflected = new Polygon(); - foreach (var v in orbitingPoly.Vertices) - reflected.Vertices.Add(new Vector(-v.X, -v.Y)); - reflected.Vertices.Reverse(); // maintain CCW winding - - var nfp = NoFitPolygon.ConvexMinkowskiSum(stationaryPoly, reflected); + // Let Compute handle reflection, winding, and Minkowski sum correctly. + var nfp = NoFitPolygon.Compute(stationaryPoly, orbitingPoly); if (nfp == null || nfp.Vertices.Count < 3) return candidates;