fix(diagnostics): report parts covering a tiny clamp in the overlap check

Collision.Check finds no overlap region for a clamp smaller than its
tolerance, so Check Overlaps reported a part covering a 1e-5 clamp as clear.
Clamps below 0.001 are judged with KeepOutOverlap and reported as a finding
whose fragment is the whole clamp rectangle; flush and clear parts stay clear.

PM aa995123-295f-479c-adc4-b0cbcb7cf838
This commit is contained in:
aj committed 2026-10-13 18:15:49 -04:00
1 parent 9b5885e5a2
commit d24e660286
2 files changed
+40

No files matched your search

@@ -275,6 +275,15 @@ public static class PlateOverlapAnalyzer
continue;
try
{
// A clamp below the polygon tolerance collapses in Collision.Check and would
// read as clear (PM aa995123): judge it tolerance-free and report the whole
// (negligibly small) clamp rectangle as the overlap fragment.
if (KeepOutOverlap.NeedsToleranceFreeTest(zone))
{
if (KeepOutOverlap.MaterialEnters(part.Material.Outer, part.Material.Holes, zone))
findings.Add(TinyClampFinding(part, clamp));
continue;
}
var origin = part.Material.Outer.Vertices[0];
var local = part.Material.Transform(0, origin * -1);
var rect = RectanglePolygon(zone, origin * -1);
@@ -311,6 +320,19 @@ public static class PlateOverlapAnalyzer
return findings;
}
private static PlateOverlapPair TinyClampFinding(PreparedPart part, CapturedClamp clamp)
{
var zone = clamp.Bounds;
var corners = new[]
{
new Vector(zone.Left, zone.Bottom), new Vector(zone.Right, zone.Bottom),
new Vector(zone.Right, zone.Top), new Vector(zone.Left, zone.Top),
};
var centre = new Vector((zone.Left + zone.Right) / 2, (zone.Bottom + zone.Top) / 2);
return new PlateOverlapPair(part.Input.Id, ClampFindingSlot.IdFor(clamp.Ordinal), part.Input.Name,
$"Clamp '{clamp.Id}'", new List<PlateOverlapRegion> { new(corners, zone.Length * zone.Width) }, centre);
}
private static Polygon RectanglePolygon(Box box, Vector offset)
{
var polygon = new Polygon();
@@ -196,6 +196,24 @@ public class PlateOverlapAnalyzerClampZoneTests
Assert.NotEqual(OverlapCheckStatus.Current, state.Status);
}
// C16 (PM 6859db53): a 1e-5 square zone, far below the outline tolerance. A part covering
// it is still reported (never silently clear); flush or clear parts are not.
[Theory]
[InlineData(7.5, true)]
[InlineData(6.0, false)]
[InlineData(8.00001, false)]
[InlineData(3.0, false)]
public void TinyClampZoneIsJudgedWithoutOutlineCollapse(double x, bool overlaps)
{
var tiny = new ClampZone("tiny", new Box(8, 0, 1e-5, 1e-5));
var parts = new List<Part> { new(Square("p", 2), new Vector(x, 0)) };
var report = PlateOverlapAnalyzer.Analyze(PlateOverlapAnalyzer.Capture(parts, new[] { tiny }));
Assert.True(report.IsComplete, string.Join("; ", report.Issues.Select(issue => issue.Message)));
Assert.Equal(overlaps, report.ClampFindings.Any(f => f.PartBName.Contains("tiny")));
}
private static string Describe(PlateOverlapReport report) =>
string.Join(";", report.Pairs.Select(p => $"{p.PartAId}/{p.PartBId}:{p.Area:R}"))
+ "|"