feat(engine): BestFitCache operates in canonical frame; TryPlaceBestFitPair builds from canonical drawing
This commit is contained in:
@@ -24,6 +24,9 @@ namespace OpenNest.Engine.BestFit
|
||||
if (_cache.TryGetValue(key, out var cached))
|
||||
return cached;
|
||||
|
||||
// Operate on the canonical frame so cached pair positions are orientation-invariant.
|
||||
var canonical = CanonicalFrame.AsCanonicalCopy(drawing);
|
||||
|
||||
IPairEvaluator evaluator = null;
|
||||
ISlideComputer slideComputer = null;
|
||||
|
||||
@@ -31,7 +34,7 @@ namespace OpenNest.Engine.BestFit
|
||||
{
|
||||
if (CreateEvaluator != null)
|
||||
{
|
||||
try { evaluator = CreateEvaluator(drawing, spacing); }
|
||||
try { evaluator = CreateEvaluator(canonical, spacing); }
|
||||
catch { /* fall back to default evaluator */ }
|
||||
}
|
||||
|
||||
@@ -42,7 +45,7 @@ namespace OpenNest.Engine.BestFit
|
||||
}
|
||||
|
||||
var finder = new BestFitFinder(plateWidth, plateHeight, evaluator, slideComputer);
|
||||
var results = finder.FindBestFits(drawing, spacing, StepSize);
|
||||
var results = finder.FindBestFits(canonical, spacing, StepSize);
|
||||
|
||||
_cache.TryAdd(key, results);
|
||||
return results;
|
||||
@@ -86,9 +89,12 @@ namespace OpenNest.Engine.BestFit
|
||||
|
||||
try
|
||||
{
|
||||
// Operate on the canonical frame so cached pair positions are orientation-invariant.
|
||||
var canonical = CanonicalFrame.AsCanonicalCopy(drawing);
|
||||
|
||||
if (CreateEvaluator != null)
|
||||
{
|
||||
try { evaluator = CreateEvaluator(drawing, spacing); }
|
||||
try { evaluator = CreateEvaluator(canonical, spacing); }
|
||||
catch { /* fall back to default evaluator */ }
|
||||
}
|
||||
|
||||
@@ -100,7 +106,7 @@ namespace OpenNest.Engine.BestFit
|
||||
|
||||
// Compute candidates and evaluate once with the largest plate.
|
||||
var finder = new BestFitFinder(maxWidth, maxHeight, evaluator, slideComputer);
|
||||
var baseResults = finder.FindBestFits(drawing, spacing, StepSize);
|
||||
var baseResults = finder.FindBestFits(canonical, spacing, StepSize);
|
||||
|
||||
// Cache a filtered copy for each plate size.
|
||||
foreach (var size in needed)
|
||||
|
||||
@@ -139,6 +139,10 @@ namespace OpenNest
|
||||
var bestFits = BestFitCache.GetOrCompute(
|
||||
drawing, Plate.Size.Length, Plate.Size.Width, Plate.PartSpacing);
|
||||
|
||||
// Build pair candidates with a canonical drawing so their geometry matches
|
||||
// the coordinate frame of the cached fit results.
|
||||
var canonicalDrawing = CanonicalFrame.AsCanonicalCopy(drawing);
|
||||
|
||||
List<Part> bestPlacement = null;
|
||||
|
||||
foreach (var fit in bestFits)
|
||||
@@ -152,7 +156,7 @@ namespace OpenNest
|
||||
if (fit.LongestSide > System.Math.Max(workArea.Width, workArea.Length) + Tolerance.Epsilon)
|
||||
continue;
|
||||
|
||||
var landscape = fit.BuildParts(drawing);
|
||||
var landscape = fit.BuildParts(canonicalDrawing);
|
||||
var portrait = RotatePair90(landscape);
|
||||
|
||||
var lFits = TryOffsetToWorkArea(landscape, workArea);
|
||||
@@ -174,6 +178,8 @@ namespace OpenNest
|
||||
bestPlacement = candidate;
|
||||
}
|
||||
|
||||
// Parts are returned in canonical frame, bound to the canonical drawing.
|
||||
// The outer Fill wrapper (Task 7) rebinds to `drawing` and composes sourceAngle onto rotation.
|
||||
return bestPlacement;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user