mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-31 18:01:35 -04:00
Saved pairs are in the drawing's canonical frame, but loaded candidates held the source drawing, so BuildCanonicalParts/BuildSourceParts rebuilt a different pair for any drawing with a non-zero canonical angle (a 30 degree T-shape came back 16.57 x 10.39 instead of its saved 16.92 x 8). That reached the Irregular engine's pair catalog and the best-fit viewer after opening a saved nest. Import now binds every candidate to one canonical copy, as computed candidates are; fills already passed the canonical drawing explicitly. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
4.9 KiB
C#
130 lines
4.9 KiB
C#
using OpenNest.BestFit;
|
|
using OpenNest.Engine;
|
|
using OpenNest.Engine.BestFit;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.Shapes;
|
|
|
|
namespace OpenNest.Tests.BestFit;
|
|
|
|
[Collection(nameof(FillCacheCollection))]
|
|
public class BestFitCacheStoreTests
|
|
{
|
|
private const double Spacing = 0.25;
|
|
|
|
private static Drawing MakeDrawing() => new TShape { Width = 10, Height = 8 }.GetDrawing();
|
|
|
|
private static BestFitResult MakeResult(Drawing drawing, bool keep, string reason = "Valid", List<double> hullAngles = null) =>
|
|
new()
|
|
{
|
|
Candidate = new PairCandidate
|
|
{
|
|
Drawing = drawing,
|
|
Part1Rotation = 0.5,
|
|
Part2Rotation = System.Math.PI,
|
|
Part2Offset = new Vector(3.25, -1.5),
|
|
StrategyIndex = 2,
|
|
TestNumber = 7,
|
|
Spacing = Spacing,
|
|
},
|
|
RotatedArea = 90,
|
|
BoundingWidth = 12,
|
|
BoundingHeight = 7.5,
|
|
OptimalRotation = 0.1,
|
|
Keep = keep,
|
|
Reason = reason,
|
|
TrueArea = 70,
|
|
HullAngles = hullAngles,
|
|
};
|
|
|
|
[Fact]
|
|
public void Export_ReturnsOnlyRequestedPlateKeysAndKeptResults()
|
|
{
|
|
BestFitCache.Clear();
|
|
var drawing = MakeDrawing();
|
|
BestFitCache.Populate(drawing, 60, 40, Spacing, new()
|
|
{
|
|
MakeResult(drawing, keep: true, hullAngles: new() { 0.25 }),
|
|
MakeResult(drawing, keep: false, reason: "Too wide"),
|
|
});
|
|
BestFitCache.Populate(drawing, 14, 30, Spacing, new() { MakeResult(drawing, keep: true) });
|
|
|
|
var sets = BestFitCacheStore.Shared.Export(
|
|
drawing, new HashSet<(double, double, double)> { (60, 40, Spacing), (99, 99, Spacing) });
|
|
|
|
var set = Assert.Single(sets);
|
|
Assert.Equal((60.0, 40.0, Spacing), (set.PlateWidth, set.PlateHeight, set.Spacing));
|
|
var result = Assert.Single(set.Results);
|
|
Assert.Equal(
|
|
new SavedPairResult(0.5, System.Math.PI, 3.25, -1.5, 2, 7, Spacing, 90, 12, 7.5, 0.1, true, "Valid", 70, result.HullAngles),
|
|
result);
|
|
Assert.Equal(new[] { 0.25 }, result.HullAngles);
|
|
}
|
|
|
|
[Fact]
|
|
public void Export_DrawingWithoutCacheEntry_ReturnsNoSets()
|
|
{
|
|
BestFitCache.Clear();
|
|
|
|
var sets = BestFitCacheStore.Shared.Export(
|
|
MakeDrawing(), new HashSet<(double, double, double)> { (60, 40, Spacing) });
|
|
|
|
Assert.Empty(sets);
|
|
}
|
|
|
|
[Fact]
|
|
public void Import_PopulatesCacheWithCandidatesOnACanonicalCopyOfTheDrawing()
|
|
{
|
|
BestFitCache.Clear();
|
|
var drawing = MakeDrawing();
|
|
var saved = new SavedPairResult(0.5, System.Math.PI, 3.25, -1.5, 2, 7, Spacing, 90, 12, 7.5, 0.1, true, "Valid", 70, new[] { 0.25, -0.5 });
|
|
|
|
BestFitCacheStore.Shared.Import(drawing, new[] { new SavedPairSet(60, 40, Spacing, new[] { saved }) });
|
|
|
|
var restored = Assert.Single(BestFitCache.GetAllForDrawing(drawing));
|
|
Assert.Equal((60.0, 40.0, Spacing), restored.Key);
|
|
var result = Assert.Single(restored.Value);
|
|
Assert.NotSame(drawing, result.Candidate.Drawing);
|
|
Assert.Same(drawing, CanonicalFrame.SourceOf(result.Candidate.Drawing));
|
|
Assert.Equal(0.0, result.Candidate.Drawing.Source.Angle);
|
|
Assert.Equal(0.5, result.Candidate.Part1Rotation);
|
|
Assert.Equal(System.Math.PI, result.Candidate.Part2Rotation);
|
|
Assert.Equal(new Vector(3.25, -1.5), result.Candidate.Part2Offset);
|
|
Assert.Equal(2, result.Candidate.StrategyIndex);
|
|
Assert.Equal(7, result.Candidate.TestNumber);
|
|
Assert.Equal(Spacing, result.Candidate.Spacing);
|
|
Assert.Equal(90, result.RotatedArea);
|
|
Assert.Equal(12, result.BoundingWidth);
|
|
Assert.Equal(7.5, result.BoundingHeight);
|
|
Assert.Equal(0.1, result.OptimalRotation);
|
|
Assert.True(result.Keep);
|
|
Assert.Equal("Valid", result.Reason);
|
|
Assert.Equal(70, result.TrueArea);
|
|
Assert.Equal(new[] { 0.25, -0.5 }, result.HullAngles);
|
|
}
|
|
|
|
[Fact]
|
|
public void Import_ExistingSetForTheSameKey_IsKept()
|
|
{
|
|
BestFitCache.Clear();
|
|
var drawing = MakeDrawing();
|
|
var existing = new List<BestFitResult> { MakeResult(drawing, keep: true) };
|
|
BestFitCache.Populate(drawing, 60, 40, Spacing, existing);
|
|
var saved = new SavedPairResult(0, 0, 1, 1, 0, 1, Spacing, 5, 1, 5, 0, true, "Valid", 4, new double[0]);
|
|
|
|
BestFitCacheStore.Shared.Import(drawing, new[] { new SavedPairSet(60, 40, Spacing, new[] { saved }) });
|
|
|
|
Assert.Same(existing, BestFitCache.GetAllForDrawing(drawing)[(60, 40, Spacing)]);
|
|
}
|
|
|
|
[Fact]
|
|
public void Import_EmptySet_AddsNothing()
|
|
{
|
|
BestFitCache.Clear();
|
|
var drawing = MakeDrawing();
|
|
|
|
BestFitCacheStore.Shared.Import(drawing, new[] { new SavedPairSet(60, 40, Spacing, new SavedPairResult[0]) });
|
|
|
|
Assert.Empty(BestFitCache.GetAllForDrawing(drawing));
|
|
}
|
|
}
|