perf: parallelize PairFiller candidates and add GridDedup

- Evaluate pair candidates in parallel batches instead of sequentially
- Add GridDedup to skip duplicate pattern/direction/workArea combos
  across PairFiller and StripeFiller strategies
- Replace crude 30% remnant area estimate with L-shaped geometry
  calculation using actual grid extents and max utilization
- Move FillStrategyRegistry.SetEnabled to outer evaluation loop
  to avoid repeated enable/disable per remnant fill

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-21 23:08:55 -04:00
parent b6ee04f038
commit 92b17b2963
4 changed files with 184 additions and 52 deletions
+6
View File
@@ -20,6 +20,7 @@ public class StripeFiller
private readonly FillContext _context;
private readonly NestDirection _primaryAxis;
private readonly IFillComparer _comparer;
private readonly GridDedup _dedup;
/// <summary>
/// When true, only complete stripes are placed — no partial rows/columns.
@@ -38,6 +39,7 @@ public class StripeFiller
_context = context;
_primaryAxis = primaryAxis;
_comparer = context.Policy?.Comparer ?? new DefaultFillComparer();
_dedup = GridDedup.GetOrCreate(context.SharedState);
}
public List<Part> Fill()
@@ -115,6 +117,10 @@ public class StripeFiller
var rotatedPattern = FillHelpers.BuildRotatedPattern(pairParts, angle);
var perpDim = GetDimension(rotatedPattern.BoundingBox, perpAxis);
var stripeBox = MakeStripeBox(workArea, perpDim, primaryAxis);
if (!_dedup.TryAdd(rotatedPattern.BoundingBox, workArea, primaryAxis))
return null;
var stripeEngine = new FillLinear(stripeBox, spacing);
var stripeParts = stripeEngine.Fill(rotatedPattern, primaryAxis);