mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-06 09:32:11 -04:00
fix(cutting): give a new part order the plate's expansion budget
The desktop batch searched for a new part order with the flat 20000 default and kept the current order with 400 expansions per part. A new order now also plans contour order and entries for every part (about 260 expansions per part on a dense grid), so a 100-part plate ran out of budget and fell back to the current order. Both attempts now get PlateBudget: 400 per part, at least 20000. The constants are renamed MinimumExpansionBudget and ExpansionsPerPart to match.
This commit is contained in:
1 parent
b8f3d3bf0a
commit
2419a9e2e3
3 files changed
+34
-16
No files matched your search
@@ -33,14 +33,15 @@ public sealed record CuttingPlanProgress(int PlateIndex, int PlateCount, int Pla
|
||||
/// </summary>
|
||||
public sealed class CuttingPlanBatch
|
||||
{
|
||||
/// <summary>Budget of a free-order search, the service default.</summary>
|
||||
public const int ReorderExpansionBudget = 20000;
|
||||
/// <summary>The smallest budget a plate gets, the service default.</summary>
|
||||
public const int MinimumExpansionBudget = 20000;
|
||||
|
||||
/// <summary>
|
||||
/// Expansions allowed per part when the order is kept. Measured near 210 per part on a dense
|
||||
/// grid; the margin keeps 100-150 part plates inside the budget.
|
||||
/// Expansions allowed per part, whether or not the order is kept: both still choose contour
|
||||
/// order and entries for every part. Dense grids measured near 260 per part with a new order
|
||||
/// and 210 when kept; the margin keeps 100-150 part plates inside the budget.
|
||||
/// </summary>
|
||||
public const int KeepOrderExpansionsPerPart = 400;
|
||||
public const int ExpansionsPerPart = 400;
|
||||
|
||||
private readonly Entry[] entries;
|
||||
private readonly CuttingParameters ownedParameters;
|
||||
@@ -61,10 +62,11 @@ public sealed class CuttingPlanBatch
|
||||
/// </summary>
|
||||
public static CuttingPlanBatch Capture(IReadOnlyList<Plate> plates, CuttingParameters confirmedParameters,
|
||||
bool preservePartOrder, IReadOnlyList<int> plateNumbers = null, CancellationToken token = default) =>
|
||||
Capture(plates, confirmedParameters, preservePartOrder, plateNumbers, ReorderExpansionBudget, token);
|
||||
Capture(plates, confirmedParameters, preservePartOrder, plateNumbers, null, token);
|
||||
|
||||
/// <param name="reorderBudget">Overrides the new-order budget (tests); null gives <see cref="PlateBudget"/>.</param>
|
||||
internal static CuttingPlanBatch Capture(IReadOnlyList<Plate> plates, CuttingParameters confirmedParameters,
|
||||
bool preservePartOrder, IReadOnlyList<int> plateNumbers, int reorderBudget, CancellationToken token)
|
||||
bool preservePartOrder, IReadOnlyList<int> plateNumbers, int? reorderBudget, CancellationToken token)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(plates);
|
||||
ArgumentNullException.ThrowIfNull(confirmedParameters);
|
||||
@@ -90,21 +92,21 @@ public sealed class CuttingPlanBatch
|
||||
for (var index = 0; index < plates.Count; index++)
|
||||
{
|
||||
var plate = plates[index];
|
||||
var keepOrderBudget = KeepOrderBudget(plate.Parts.Count);
|
||||
var budget = PlateBudget(plate.Parts.Count);
|
||||
var keepOrder = CuttingPlanService.Capture(CuttingPlanRequest.ForPlate(plate,
|
||||
expansionBudget: keepOrderBudget, confirmedParameters: confirmedParameters,
|
||||
expansionBudget: budget, confirmedParameters: confirmedParameters,
|
||||
preservePartOrder: true), token);
|
||||
var reorder = preservePartOrder ? null : CuttingPlanService.Capture(CuttingPlanRequest.ForPlate(plate,
|
||||
expansionBudget: reorderBudget, confirmedParameters: confirmedParameters), token);
|
||||
expansionBudget: reorderBudget ?? budget, confirmedParameters: confirmedParameters), token);
|
||||
var overlap = PlateOverlapAnalyzer.Capture(plate.Parts.ToArray(), token);
|
||||
entries[index] = new(plate, plateNumbers?[index] ?? index + 1, reorder, keepOrder, overlap);
|
||||
}
|
||||
return new(entries, owned);
|
||||
}
|
||||
|
||||
internal static int KeepOrderBudget(int partCount) =>
|
||||
internal static int PlateBudget(int partCount) =>
|
||||
(int)System.Math.Min(int.MaxValue,
|
||||
System.Math.Max((long)ReorderExpansionBudget, (long)partCount * KeepOrderExpansionsPerPart));
|
||||
System.Math.Max((long)MinimumExpansionBudget, (long)partCount * ExpansionsPerPart));
|
||||
|
||||
/// <summary>
|
||||
/// Checks and plans every plate from its captured snapshots. Safe on a worker: live plates are
|
||||
|
||||
@@ -273,8 +273,24 @@ public class CuttingPlanBatchTests
|
||||
[InlineData(10, 20000)]
|
||||
[InlineData(100, 40000)]
|
||||
[InlineData(6_000_000, int.MaxValue)]
|
||||
public void KeepOrderBudget_ScalesWithPartCountFromTheDefault(int parts, int expected) =>
|
||||
Assert.Equal(expected, CuttingPlanBatch.KeepOrderBudget(parts));
|
||||
public void PlateBudget_ScalesWithPartCountFromTheDefault(int parts, int expected) =>
|
||||
Assert.Equal(expected, CuttingPlanBatch.PlateBudget(parts));
|
||||
|
||||
[Fact]
|
||||
public void Plan_LargeGrid_FindsANewOrderWithinThePlateBudget()
|
||||
{
|
||||
// Row-major 10 x 10 needs more than the 20000 default to reorder (about 26000).
|
||||
var nest = new Nest();
|
||||
var plate = Plate(nest, Grid(100));
|
||||
plate.Size = new Size(120, 120);
|
||||
|
||||
var proposal = CuttingPlanBatch.Capture([plate], ExplicitContourTests.Parameters(), false).Plan();
|
||||
|
||||
var planned = Assert.Single(proposal.Plates);
|
||||
Assert.True(planned.IsReady, string.Join("\n", proposal.Describe("in")));
|
||||
Assert.False(planned.KeptCurrentOrder);
|
||||
Assert.Equal(100, planned.PartCount);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Capture_RejectsMissingDuplicateOrMisnumberedPlates()
|
||||
|
||||
@@ -219,8 +219,8 @@ plans every plate that has parts. Both open one dialog built on
|
||||
an incomplete check (see [pre-post verification](post-verification.md)) block that plate
|
||||
whatever its route. A free-order search that ends
|
||||
`NoSolutionWithinBudget` is retried once with the current part order, and the summary
|
||||
says the order was kept. A kept order is allowed 400 expansions per part (at
|
||||
least the default 20000), because it still searches contour order and entries.
|
||||
says the order was kept. Both are allowed 400 expansions per part (at least the
|
||||
default 20000), because both still plan contour order and entries for every part.
|
||||
- The summary lists every plate: ready plates with part counts and rapid travel, others
|
||||
with their status and findings. Finding part numbers are the plate's current order, as the
|
||||
editor numbers them. The preview shows the active plate detached from the nest (quantity
|
||||
|
||||
Reference in new issue
Block a user