Files
OpenNest/OpenNest.Benchmark/JobResult.cs
T
aj 6a0fba0fec Add OpenNest.Benchmark: generic head-to-head engine comparison harness
Loads any .nest file (or folder of them) via NestReader and nests every
drawing with quantity > 0 using each registered NestEngineBase, so it
works sight-unseen against arbitrary real jobs without any hardcoded
geometry. Optionally sweeps a fixed --sheet-sizes list instead of each
file's own plate size.

- BenchmarkJob/JobLoader build immutable job specs; a fresh Plate and
  NestItem list is created per (job, engine) run so state never leaks
  between engines or jobs.
- NestValidator rejects a layout if any part falls outside the work
  area, any two parts are closer than PartSpacing (checked via each
  part's own world-space polygon inflated by the spacing, so it holds
  for arbitrary concave/holed geometry, not just bounding boxes), or a
  drawing gets more parts than requested.
- Scoring matches Plate.Utilization() (placed area / full sheet area);
  ties among fully-placed layouts break on the smaller used bounding
  box (more usable remnant).
- Report prints a per-job ranked breakdown plus a per-engine summary
  (wins, avg utilization, time), and can write a flat CSV.

Verified end-to-end against a synthetic .nest file (not committed)
against the four built-in engines; caught a genuine out-of-work-area
bug in StripNestEngine in the process.
2026-09-15 18:31:36 -04:00

28 lines
1.0 KiB
C#

using System.Collections.Generic;
namespace OpenNest.Benchmark
{
/// <summary>
/// Outcome of running one engine against one job. An invalid or crashed run
/// always scores zero utilization for that job, per the benchmark rules.
/// </summary>
public class JobResult
{
public string EngineName { get; init; }
public string JobName { get; init; }
public bool Valid { get; init; }
public List<string> Violations { get; init; } = new();
public string Error { get; init; }
public int PartsPlaced { get; init; }
public int PartsRequested { get; init; }
public double PlacedArea { get; init; }
public double PlateArea { get; init; }
public double UsedBoundingBoxArea { get; init; }
public long ElapsedMs { get; init; }
public bool Crashed => Error != null;
public bool FullyPlaced => Valid && PartsRequested > 0 && PartsPlaced >= PartsRequested;
public double Utilization => Valid && PlateArea > 0 ? PlacedArea / PlateArea : 0;
}
}