From 1e9640d4fc5f7716b835c2b0b16ce8457c1a817d Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Thu, 19 Mar 2026 10:42:29 -0400 Subject: [PATCH] feat(engine): include rotating calipers angle in pair nesting tiling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PairEvaluator already computes OptimalRotation via RotatingCalipers on the pair's convex hull, but PairFiller.EvaluateCandidate only passed hull edge angles to FillPattern. Now includes the optimal rotation angle (and +90°) so tiling can use the mathematically tightest fit. Co-Authored-By: Claude Opus 4.6 (1M context) --- OpenNest.Engine/Fill/PairFiller.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/OpenNest.Engine/Fill/PairFiller.cs b/OpenNest.Engine/Fill/PairFiller.cs index 1a2b2fe..2fbe01e 100644 --- a/OpenNest.Engine/Fill/PairFiller.cs +++ b/OpenNest.Engine/Fill/PairFiller.cs @@ -107,7 +107,17 @@ namespace OpenNest.Engine.Fill var p90 = FillHelpers.BuildRotatedPattern(pairParts, Angle.HalfPI); engine.RemainderPatterns = new List { p0, p90 }; - return FillHelpers.FillPattern(engine, pairParts, candidate.HullAngles, workArea); + // Include the pair's rotating calipers optimal rotation angle + // alongside the hull edge angles for tiling. + var angles = new List(candidate.HullAngles); + var optAngle = -candidate.OptimalRotation; + if (!angles.Any(a => a.IsEqualTo(optAngle))) + angles.Add(optAngle); + var optAngle90 = Angle.NormalizeRad(optAngle + Angle.HalfPI); + if (!angles.Any(a => a.IsEqualTo(optAngle90))) + angles.Add(optAngle90); + + return FillHelpers.FillPattern(engine, pairParts, angles, workArea); } private List SelectPairCandidates(List bestFits, Box workArea)