feat: integrate GPU slide computation into best-fit pipeline

Thread ISlideComputer through BestFitCache → BestFitFinder →
RotationSlideStrategy. RotationSlideStrategy now collects all offsets
across 4 push directions and dispatches them in a single batch (GPU or
CPU fallback). Also improves rotation angle extraction: uses raw geometry
(line endpoints + arc cardinal extremes) instead of tessellation to avoid
flooding the hull with near-duplicate edge angles, and adds a 5-degree
deduplication threshold.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 20:29:51 -04:00
parent 97dfe27953
commit 183d169cc1
4 changed files with 175 additions and 74 deletions
+10 -1
View File
@@ -13,6 +13,7 @@ namespace OpenNest.Engine.BestFit
new ConcurrentDictionary<CacheKey, List<BestFitResult>>();
public static Func<Drawing, double, IPairEvaluator> CreateEvaluator { get; set; }
public static Func<ISlideComputer> CreateSlideComputer { get; set; }
public static List<BestFitResult> GetOrCompute(
Drawing drawing, double plateWidth, double plateHeight,
@@ -24,6 +25,7 @@ namespace OpenNest.Engine.BestFit
return cached;
IPairEvaluator evaluator = null;
ISlideComputer slideComputer = null;
try
{
@@ -33,7 +35,13 @@ namespace OpenNest.Engine.BestFit
catch { /* fall back to default evaluator */ }
}
var finder = new BestFitFinder(plateWidth, plateHeight, evaluator);
if (CreateSlideComputer != null)
{
try { slideComputer = CreateSlideComputer(); }
catch { /* fall back to CPU slide computation */ }
}
var finder = new BestFitFinder(plateWidth, plateHeight, evaluator, slideComputer);
var results = finder.FindBestFits(drawing, spacing, StepSize);
_cache.TryAdd(key, results);
@@ -42,6 +50,7 @@ namespace OpenNest.Engine.BestFit
finally
{
(evaluator as IDisposable)?.Dispose();
// Slide computer is managed by the factory as a singleton — don't dispose here
}
}