From c57e0ded83b7fc4815711a6dfdd8ed7bf6bebc08 Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 13 Oct 2026 18:15:16 -0400 Subject: [PATCH] fix(diagnostics): keep tiny clamps beyond coarse chords in the overlap check Check Overlaps dismissed a tiny clamp by the part's coarse material bounds before the fine tolerance-free test ran, but that material is inscribed at the 0.001 chord tolerance: real material in the sliver beyond a convex arc (a short arc cap, a rotated crescent) lay outside those bounds and the clamp read as clear. For clamps below the tolerance the bounds are widened by the chord tolerance before rejecting. PM 407f5eb7-329f-41e4-947e-64ad52aa4034 (review s6-delta3-review.md) --- .../Diagnostics/PlateOverlapAnalyzer.cs | 7 +++-- .../PlateOverlapAnalyzerClampZoneTests.cs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/OpenNest.Core/Diagnostics/PlateOverlapAnalyzer.cs b/OpenNest.Core/Diagnostics/PlateOverlapAnalyzer.cs index 7accabc..a602a97 100644 --- a/OpenNest.Core/Diagnostics/PlateOverlapAnalyzer.cs +++ b/OpenNest.Core/Diagnostics/PlateOverlapAnalyzer.cs @@ -270,8 +270,11 @@ public static class PlateOverlapAnalyzer { cancellationToken.ThrowIfCancellationRequested(); var zone = clamp.Bounds; - if (partBounds.Right <= zone.Left || zone.Right <= partBounds.Left - || partBounds.Top <= zone.Bottom || zone.Top <= partBounds.Bottom) + // The prepared material is inscribed at ChordTolerance, so real material can + // reach that far past its bounds; a tiny clamp there must still be checked. + var reach = KeepOutOverlap.NeedsToleranceFreeTest(zone) ? ChordTolerance : 0; + if (partBounds.Right + reach <= zone.Left || zone.Right <= partBounds.Left - reach + || partBounds.Top + reach <= zone.Bottom || zone.Top <= partBounds.Bottom - reach) continue; try { diff --git a/OpenNest.Tests/Diagnostics/PlateOverlapAnalyzerClampZoneTests.cs b/OpenNest.Tests/Diagnostics/PlateOverlapAnalyzerClampZoneTests.cs index fab500f..673e3ef 100644 --- a/OpenNest.Tests/Diagnostics/PlateOverlapAnalyzerClampZoneTests.cs +++ b/OpenNest.Tests/Diagnostics/PlateOverlapAnalyzerClampZoneTests.cs @@ -282,6 +282,32 @@ public class PlateOverlapAnalyzerClampZoneTests Assert.NotEmpty(report.ClampFindings); } + // Delta review 3: a tiny clamp in the sliver beyond a convex arc's 0.001 chords must not + // be dismissed by the coarse material bounds before the fine check runs. + [Fact] + public void TinyClampBeyondCoarseChordsIsReported() + { + const double r = 0.01, half = 0.04; + var dx = r * System.Math.Sin(half); + var cy = 20 - r * System.Math.Cos(half); + var program = new Program(); + program.MoveTo(0, 0); + program.LineTo(20, 0); + program.LineTo(20, 20); + program.LineTo(10 + dx, 20); + program.ArcTo(10 - dx, 20, 10, cy, RotationType.CCW); + program.LineTo(0, 20); + program.LineTo(0, 0); + // Witness (10, 20.000002) is inside the arc (radius 0.009994 < 0.01) and the zone. + var zone = new ClampZone("tiny", new Box(9.999995, 20.000001199840007, 1e-5, 1e-5)); + + var report = PlateOverlapAnalyzer.Analyze(PlateOverlapAnalyzer.Capture( + new List { new(new Drawing("cap", program), new Vector(0, 0)) }, new[] { zone })); + + Assert.True(report.IsComplete, string.Join("; ", report.Issues.Select(issue => issue.Message))); + Assert.NotEmpty(report.ClampFindings); + } + private static string Describe(PlateOverlapReport report) => string.Join(";", report.Pairs.Select(p => $"{p.PartAId}/{p.PartBId}:{p.Area:R}")) + "|"