Rework OpenNest.Benchmark into a full multi-plate, multi-size nest
Previously each job fixed one plate size and ran a single Nest() call, which doesn't reflect the actual problem: a real job is fulfilled across however many plates are needed, drawn from a pool of standard sheet sizes, not forced onto one fixed sheet. NestEngineBase.Nest() has no way to pick its own plate's size - it fills whatever Plate it's given - so size selection now lives in the harness itself, applied identically to every engine: - BenchmarkJob carries the full candidate size pool (CandidateSizes) instead of one fixed PlateSize; one job per file, not one per size. - BenchmarkRunner drives a loop: while items remain, pick the smallest candidate size that fits the largest still-unplaced drawing (reusing the codebase's own MultiPlateNester.CreatePlate/FitsBounds), build a fresh plate of that size, and run one Nest() call to fill it. Repeat until everything is placed, no candidate size fits what's left, or a safety cap (40 plates) is hit. - NestValidator now validates bounds/spacing per plate but the quantity cap once globally across all plates, since that limit belongs to the whole order, not any one sheet. - JobResult/Report report PlatesUsed and a per-size breakdown instead of a single-plate bounding-box compactness metric; utilization is now aggregated across every plate the engine used. Ranking keeps the same rule (utilization first), with fewer plates as the tie-break when both are fully placed and tied - the natural multi-plate analogue of the old single-plate compactness tie-break. Smoke-tested against the synthetic sample across 5 candidate sizes: correctly builds one job, picks the smallest fitting size, uses however many plates each engine needs (1-2 here), and still catches StripNestEngine's pre-existing out-of-bounds bug.
This commit is contained in:
@@ -57,6 +57,13 @@ static class BenchmarkConsole
|
||||
}
|
||||
|
||||
Console.WriteLine($"Loaded {jobs.Count} job(s) from '{options.InputPath}'");
|
||||
|
||||
foreach (var job in jobs)
|
||||
{
|
||||
var sizes = string.Join(", ", job.CandidateSizes.Select(s => s.ToString(1)));
|
||||
Console.WriteLine($" {job.Name}: {job.Requests.Count} drawing(s), {job.TotalRequestedQuantity} part(s) requested, candidate sizes: {sizes}");
|
||||
}
|
||||
|
||||
Console.WriteLine($"Engines: {string.Join(", ", engines.Select(e => e.Name))}");
|
||||
|
||||
var results = BenchmarkRunner.Run(jobs, engines);
|
||||
@@ -133,17 +140,21 @@ static class BenchmarkConsole
|
||||
{
|
||||
Console.Error.WriteLine("OpenNest.Benchmark - compare registered nesting engines on a set of .nest files");
|
||||
Console.Error.WriteLine();
|
||||
Console.Error.WriteLine("For each .nest file, every drawing with quantity > 0 is nested (mixed together)");
|
||||
Console.Error.WriteLine("onto a fresh plate per sheet size, once per registered engine. Scoring: material");
|
||||
Console.Error.WriteLine("utilization first, then (if everything requested was placed) a smaller used");
|
||||
Console.Error.WriteLine("bounding box as the tie-break. An invalid layout (out of bounds, overlapping,");
|
||||
Console.Error.WriteLine("or over-quantity) scores zero for that job.");
|
||||
Console.Error.WriteLine("For each .nest file, every drawing with quantity > 0 is nested (mixed together),");
|
||||
Console.Error.WriteLine("once per registered engine. This is a full nest, not a single fixed-size plate:");
|
||||
Console.Error.WriteLine("as many plates as needed are created, one at a time, each sized by picking the");
|
||||
Console.Error.WriteLine("smallest candidate sheet size that fits the largest still-unplaced drawing -");
|
||||
Console.Error.WriteLine("applied identically to every engine, since Nest() itself has no say over its");
|
||||
Console.Error.WriteLine("own plate's size. Scoring: aggregate material utilization across every plate");
|
||||
Console.Error.WriteLine("used, then (if everything requested was placed) fewer plates as the tie-break.");
|
||||
Console.Error.WriteLine("An invalid layout (out of bounds, overlapping, or over-quantity) scores zero.");
|
||||
Console.Error.WriteLine();
|
||||
Console.Error.WriteLine("Usage:");
|
||||
Console.Error.WriteLine(" OpenNest.Benchmark <file.nest | folder> [options]");
|
||||
Console.Error.WriteLine();
|
||||
Console.Error.WriteLine("Options:");
|
||||
Console.Error.WriteLine(" --sheet-sizes W1xL1,W2xL2,... Sweep these plate sizes instead of each file's own");
|
||||
Console.Error.WriteLine(" --sheet-sizes W1xL1,W2xL2,... Candidate sheet-size pool for the whole nest");
|
||||
Console.Error.WriteLine(" (default: the distinct sizes already in each file)");
|
||||
Console.Error.WriteLine(" --spacing <value> Override part spacing for every job");
|
||||
Console.Error.WriteLine(" --engines Name1,Name2,... Only benchmark these registered engines (default: all)");
|
||||
Console.Error.WriteLine(" --csv <path> Write a flat CSV of all results");
|
||||
|
||||
Reference in New Issue
Block a user