fix: resolve grid overlap bug and parallelize fill loops

The push algorithm's copy distance formula (bboxDim - slideDistance)
produced distances smaller than the part width when inflated boundary
arc vertices interacted spuriously, causing ~0.05 unit overlaps between
all adjacent grid parts.

Two fixes applied:
- Clamp ComputeCopyDistance to bboxDim + PartSpacing minimum
- Use circumscribed polygons (R/cos(halfStep)) for PartBoundary arc
  discretization so chord segments never cut inside the true arc,
  eliminating the ChordTolerance offset workaround

Also parallelized three sequential fill loops using Parallel.ForEach:
- FindBestFill angle sweep (up to 38 angles x 2 directions)
- FillPattern angle sweep for group/pair fills
- FillRemainingStrip rotation loop

Added diagnostic logging to HasOverlaps, FindCopyDistance, and
FillRecursive for debugging fill issues.

Test result: 45 parts @ 79.6% -> 47 parts @ 83.1%, zero overlaps.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-11 00:36:48 -04:00
parent 0e3bf3ccaa
commit 78ee65d946
6 changed files with 126 additions and 39 deletions
+5 -3
View File
@@ -13,7 +13,7 @@ namespace OpenNest
/// </summary>
public class PartBoundary
{
private const double ChordTolerance = 0.01;
private const double PolygonTolerance = 0.01;
private readonly List<Polygon> _polygons;
private readonly (Vector start, Vector end)[] _leftEdges;
@@ -29,12 +29,14 @@ namespace OpenNest
foreach (var shape in shapes)
{
var offsetEntity = shape.OffsetEntity(spacing + ChordTolerance, OffsetSide.Left) as Shape;
var offsetEntity = shape.OffsetEntity(spacing, OffsetSide.Left) as Shape;
if (offsetEntity == null)
continue;
var polygon = offsetEntity.ToPolygonWithTolerance(ChordTolerance);
// Circumscribe arcs so polygon vertices are always outside
// the true arc — guarantees the boundary never under-estimates.
var polygon = offsetEntity.ToPolygonWithTolerance(PolygonTolerance, circumscribe: true);
polygon.RemoveSelfIntersections();
_polygons.Add(polygon);
}