mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-10 07:34:14 -04:00
test(cutouts): trace accepted lattice and NFP poses in one run
This commit is contained in:
1 parent
1d50c6ce60
commit
71bd964344
2 files changed
+28
-8
No files matched your search
@@ -24,10 +24,14 @@ public class CutoutRouterTests
|
||||
var frame = JobBuilder.Part("frame", TestShapes.Ring(20, 10), 1);
|
||||
var small = JobBuilder.Part("small", TestShapes.Rectangle(1, 1), 3);
|
||||
var large = JobBuilder.Rectangle("large", 3, 3, 1, RotationPolicy.Fixed(0));
|
||||
Assert.Equal(3, CutoutLatticeFill.Fill(frame, 0, small, 3, 0.25).Count);
|
||||
var poses = CutoutRouter.Fill(frame, 0, new[] { small, large }, 0.25);
|
||||
var origins = new List<(NestJobPlacement Pose, bool Lattice)>();
|
||||
var poses = CutoutRouter.Fill(frame, 0, new[] { small, large }, 0.25,
|
||||
(pose, lattice) => origins.Add((pose, lattice)));
|
||||
Assert.Equal(3, poses.Count(p => p.PartId == small.Id));
|
||||
Assert.Single(poses, p => p.PartId == large.Id);
|
||||
Assert.Contains(origins, row => row.Pose.PartId == small.Id && row.Lattice);
|
||||
Assert.Contains(origins, row => row.Pose.PartId == large.Id && !row.Lattice);
|
||||
Assert.Equal(poses, origins.Select(row => row.Pose));
|
||||
Assert.Equal(new[] { 0, 1, 2 }, poses.Where(p => p.PartId == small.Id).Select(p => p.InstanceIndex));
|
||||
AssertPhysical(frame, new[] { small, large }, poses);
|
||||
}
|
||||
@@ -38,10 +42,10 @@ public class CutoutRouterTests
|
||||
var frame = Frame();
|
||||
var small = JobBuilder.Rectangle("small", 1, 1, 3, RotationPolicy.Fixed(0));
|
||||
var impossible = JobBuilder.Rectangle("impossible", 9.6, 9.6, 1, RotationPolicy.Fixed(0));
|
||||
var alone = CutoutRouter.Fill(frame, 0, new[] { small }, 0.25);
|
||||
var together = CutoutRouter.Fill(frame, 0, new[] { small, impossible }, 0.25);
|
||||
Assert.Equal(alone, together);
|
||||
Assert.Equal(3, together.Count);
|
||||
Assert.All(together, p => Assert.Equal(small.Id, p.PartId));
|
||||
Assert.Equal(Enumerable.Range(0, 3), together.Select(p => p.InstanceIndex));
|
||||
AssertPhysical(frame, new[] { small, impossible }, together);
|
||||
}
|
||||
|
||||
@@ -74,10 +78,13 @@ public class CutoutRouterTests
|
||||
// lattice keeps 11; an independently certified NFP pose occupies its leftover.
|
||||
var frame = JobBuilder.Part("frame", TestShapes.Ring(18, 8), 1);
|
||||
var insert = JobBuilder.Part("insert", TestShapes.Rectangle(2, 1), 12);
|
||||
var lattice = CutoutLatticeFill.Fill(frame, 0, insert, 12, 0.25);
|
||||
Assert.Equal(11, lattice.Count);
|
||||
var poses = CutoutRouter.Fill(frame, 0, new[] { insert }, 0.25);
|
||||
var origins = new List<(NestJobPlacement Pose, bool Lattice)>();
|
||||
var poses = CutoutRouter.Fill(frame, 0, new[] { insert }, 0.25,
|
||||
(pose, lattice) => origins.Add((pose, lattice)));
|
||||
Assert.Equal(12, poses.Count);
|
||||
Assert.Equal(11, origins.Count(row => row.Lattice));
|
||||
Assert.Single(origins, row => !row.Lattice);
|
||||
Assert.Equal(poses, origins.Select(row => row.Pose));
|
||||
Assert.Equal(Enumerable.Range(0, 12), poses.Select(p => p.InstanceIndex));
|
||||
AssertPhysical(frame, new[] { insert }, poses);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,14 @@ internal static class CutoutRouter
|
||||
internal const double LargeRatio = 0.35;
|
||||
|
||||
internal static IReadOnlyList<NestJobPlacement> Fill(NestJobPart frame, int cutoutIndex,
|
||||
IReadOnlyList<NestJobPart> inserts, double spacing, CancellationToken token = default)
|
||||
IReadOnlyList<NestJobPart> inserts, double spacing, CancellationToken token = default) =>
|
||||
Fill(frame, cutoutIndex, inserts, spacing, null, token);
|
||||
|
||||
/// <summary>Optional internal diagnostic receives only poses from the chosen proposal,
|
||||
/// after indexing; true marks a retained lattice seed, false a residual NFP pose.</summary>
|
||||
internal static IReadOnlyList<NestJobPlacement> Fill(NestJobPart frame, int cutoutIndex,
|
||||
IReadOnlyList<NestJobPart> inserts, double spacing,
|
||||
Action<NestJobPlacement, bool>? observeAccepted, CancellationToken token = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(frame);
|
||||
ArgumentNullException.ThrowIfNull(inserts);
|
||||
@@ -61,11 +68,14 @@ internal static class CutoutRouter
|
||||
CutoutLatticeFill.DefaultShiftSteps, occupied, token)
|
||||
: Array.Empty<NestJobPlacement>();
|
||||
IReadOnlyList<NestJobPlacement> chosen;
|
||||
var retainedLattice = 0;
|
||||
if (compareBoth || (nfpFirst && lattice.Count > 0))
|
||||
{
|
||||
nfp ??= Nfp(Array.Empty<NestJobPlacement>());
|
||||
var fromLattice = Complete(lattice);
|
||||
chosen = fromLattice.Count > nfp.Count ? fromLattice : nfp;
|
||||
if (ReferenceEquals(chosen, fromLattice))
|
||||
retainedLattice = lattice.Count;
|
||||
}
|
||||
else if (nfpFirst)
|
||||
chosen = nfp!;
|
||||
@@ -77,14 +87,17 @@ internal static class CutoutRouter
|
||||
chosen = Complete(seed);
|
||||
if (chosen.Count == 0 && lattice.Count == 1)
|
||||
chosen = lattice;
|
||||
retainedLattice = ReferenceEquals(chosen, lattice) ? lattice.Count : seed.Count;
|
||||
}
|
||||
|
||||
var localIndex = 0;
|
||||
foreach (var pose in chosen)
|
||||
{
|
||||
token.ThrowIfCancellationRequested();
|
||||
var indexed = pose with { InstanceIndex = accepted.Count(p => p.PartId == part.Id) };
|
||||
accepted.Add(indexed);
|
||||
occupied.Add((geometry, indexed));
|
||||
observeAccepted?.Invoke(indexed, localIndex++ < retainedLattice);
|
||||
}
|
||||
|
||||
IReadOnlyList<NestJobPlacement> Complete(IReadOnlyList<NestJobPlacement> seed)
|
||||
|
||||
Reference in new issue
Block a user