fix(bestfit): drop saved pair sets whose canonical frame changed

Saved best-fit pairs are in the drawing's canonical frame, but the canonical
angle is recomputed on load and was not saved with the set. When that
computation changes (RotatingCalipers checking every hull edge, marks no
longer counted as material), old pairs were replayed in a turned frame and
could overlap.

Each saved set now records canonicalAngle, and BestFitCacheStore.Import
skips sets whose angle no longer matches the recomputed one (1e-9 rad,
modulo a full turn). Sets from older files have no angle and are dropped;
their pairs are recomputed when next needed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ajandClaude Opus 5.5 committed 2026-10-20 22:04:23 -04:00
1 parent f901840ed0
commit 0ca4e64189
9 files changed
+213 -17

No files matched your search

+11 -3
View File
@@ -21,12 +21,17 @@ namespace OpenNest.BestFit
IReadOnlyList<double> HullAngles
);
/// <summary>The saved best-fit results for one drawing at one plate size and spacing.</summary>
/// <summary>
/// The saved best-fit results for one drawing at one plate size and spacing.
/// <paramref name="CanonicalAngle"/> is the drawing's canonical angle (radians) when the
/// set was saved: the frame its pair geometry is in. Null means the frame is unknown.
/// </summary>
public sealed record SavedPairSet(
double PlateWidth,
double PlateHeight,
double Spacing,
IReadOnlyList<SavedPairResult> Results
IReadOnlyList<SavedPairResult> Results,
double? CanonicalAngle = null
);
/// <summary>
@@ -45,7 +50,10 @@ namespace OpenNest.BestFit
IReadOnlySet<(double Width, double Length, double Spacing)> plateKeys
);
/// <summary>Restores saved sets for <paramref name="drawing"/>.</summary>
/// <summary>
/// Restores saved sets for <paramref name="drawing"/>. Sets saved in a frame other
/// than the drawing's current canonical frame, or in an unknown one, are stale.
/// </summary>
void Import(Drawing drawing, IReadOnlyList<SavedPairSet> sets);
}
}