The console overlap check and the MCP check_overlaps tool counted
crossing points, so a part contained in or stacked on another reported
no overlap. Both now list pairs from PartOverlapChecker.FindOverlappingPairs,
which uses the Intersects verdict and skips cut-off parts.
Plate.HasOverlappingParts stays for now: two test files outside this
change still call it.
Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
After 1b, triangulating both polygons on every pair was the largest
remaining overlap cost (27% of main-thread samples on the corpus job).
PartOverlapChecker now triangulates each part at most once per check,
lazily after the bounding-box gate, and passes the triangles to a new
internal Collision.HasOverlap overload that runs the unchanged
OverlapRegions body. Triangles are only read by clipping and hole
subtraction, so reuse gives identical verdicts.
Verification:
- 49,000 seeded decisions with reused triangles match LegacyCollision;
triangles stay bit-identical to a fresh triangulation afterwards.
- Debug PolygonTriangulations: 246 -> 40 and 64 -> 36 per grid check;
sharing triangles per Program instead fails 23 tests.
- Corpus job (169 parts, --engines Default --parallel 1): median
13,398 -> 12,702 ms over 4+4 alternating runs vs 1b, identical
outcomes; serialized layout byte-identical to the base.
Also records the Follow-up B' (Slices 1a, 1b, 2a) measurements in
docs/performance/fill-performance.md.
Both HasOverlappingParts loops rebuilt each part's polygon from its
Program on every pair. PartOverlapChecker prepares each distinct Program
(reference identity) once and each part's world polygon once per call,
then uses the overlap-only Collision.HasOverlap. Loop order, bounding-box
prefilter, early exit and returned indices are unchanged; Part.Intersects
shares the material/polygon recipe and still returns crossing points.
Verification:
- Frozen LegacyPartOverlap differential (original Intersects and both
loops): verdicts, indices and world polygons bit-identical across fill
grids, patterns, touching/epsilon gaps, scribe/rapid/empty programs.
- Debug OverlapPolygonPreparations: 246 -> 1 and 64 -> 2 per check.
- Corpus job (169 parts, --engines Default --parallel 1, with 1a):
median 18,885 -> 13,464 ms over 4+4 alternating runs, identical
outcomes; serialized layout byte-identical to the base.