diff --git a/OpenNest.Core/Plate.cs b/OpenNest.Core/Plate.cs index 7c283280..e64c124d 100644 --- a/OpenNest.Core/Plate.cs +++ b/OpenNest.Core/Plate.cs @@ -1153,40 +1153,5 @@ namespace OpenNest return Parts.Where(p => !p.BaseDrawing.IsCutOff).Sum(part => part.BaseDrawing.Area) / Area(); } - - public bool HasOverlappingParts(out List pts) - { - pts = new List(); - var realParts = Parts.Where(p => !p.BaseDrawing.IsCutOff).ToList(); - - for (var i = 0; i < realParts.Count; i++) - { - var part1 = realParts[i]; - var b1 = part1.BoundingBox; - - for (var j = i + 1; j < realParts.Count; j++) - { - var part2 = realParts[j]; - var b2 = part2.BoundingBox; - - // Skip pairs whose bounding boxes don't meaningfully overlap. - // Floating-point rounding can produce sub-epsilon overlaps for - // parts that are merely edge-touching, so require the overlap - // region to exceed Epsilon in both dimensions. - var overlapX = - System.Math.Min(b1.Right, b2.Right) - System.Math.Max(b1.Left, b2.Left); - var overlapY = - System.Math.Min(b1.Top, b2.Top) - System.Math.Max(b1.Bottom, b2.Bottom); - - if (overlapX <= Math.Tolerance.Epsilon || overlapY <= Math.Tolerance.Epsilon) - continue; - - if (part1.Intersects(part2, out var pts2)) - pts.AddRange(pts2); - } - } - - return pts.Count > 0; - } } } diff --git a/OpenNest.Tests/Strategies/StrategyOverlapTests.cs b/OpenNest.Tests/Strategies/StrategyOverlapTests.cs index a5f01b17..e0151ac0 100644 --- a/OpenNest.Tests/Strategies/StrategyOverlapTests.cs +++ b/OpenNest.Tests/Strategies/StrategyOverlapTests.cs @@ -85,13 +85,14 @@ public class StrategyOverlapTests foreach (var g in rotGroups) _output.WriteLine($" Rotation {g.Key:F1}°: {g.Count()} parts"); - var hasOverlaps = plate.HasOverlappingParts(out var pts); - _output.WriteLine($" Overlaps: {hasOverlaps} ({pts.Count} collision pts)"); + var pairs = PartOverlapChecker.FindOverlappingPairs(plate.Parts); + var hasOverlaps = pairs.Count > 0; + _output.WriteLine($" Overlaps: {hasOverlaps} ({pairs.Count} overlapping pairs)"); if (hasOverlaps) { failures.Add( - $"{strategy.GetType().Name} ({strategy.Phase}): {pts.Count} collision pts, {count} parts" + $"{strategy.GetType().Name} ({strategy.Phase}): {pairs.Count} overlapping pairs, {count} parts" ); // Show overlapping pair details diff --git a/OpenNest.Tests/Strategies/StripeFillerTests.cs b/OpenNest.Tests/Strategies/StripeFillerTests.cs index 954ed64e..2f0e1069 100644 --- a/OpenNest.Tests/Strategies/StripeFillerTests.cs +++ b/OpenNest.Tests/Strategies/StripeFillerTests.cs @@ -178,7 +178,7 @@ public class StripeFillerTests if (parts.Count > 0) { plate.Parts.AddRange(parts); - var hasOverlaps = plate.HasOverlappingParts(out _); + var hasOverlaps = PartOverlapChecker.FindOverlappingPairs(plate.Parts).Count > 0; Assert.False(hasOverlaps, "Stripe fill should not produce overlapping parts"); } } @@ -211,7 +211,7 @@ public class StripeFillerTests if (parts.Count > 0) { plate.Parts.AddRange(parts); - var hasOverlaps = plate.HasOverlappingParts(out _); + var hasOverlaps = PartOverlapChecker.FindOverlappingPairs(plate.Parts).Count > 0; Assert.False(hasOverlaps, "Column fill should not produce overlapping parts"); } } @@ -244,7 +244,7 @@ public class StripeFillerTests Assert.InRange(capped.Count, 6, full.Count - 1); var plate = new Plate(60, 120) { PartSpacing = 0.5 }; plate.Parts.AddRange(capped); - Assert.False(plate.HasOverlappingParts(out _), "Capped stripe fill overlaps"); + Assert.Empty(PartOverlapChecker.FindOverlappingPairs(plate.Parts)); } [Fact]