Slice 3 of common-line cutting. On costly plate (N26-295: 3/16 RA310S at about $2,500 a sheet) pairing parts one kerf apart fits the part the spacing cannot: the last plate's 38 parts fit on one 48x120 with Auto Nest only with pairs. - Drawing Properties gains "Allow common line" (Drawing.AllowCommonLine, off by default because customer edge-quality needs vary). The nest's CommonLineUsage (Off / When it adds parts / Whenever available) is set in Auto Nest and seeded from Tools > Nest Defaults; both persist (nest.json, defaults.json). - NestPipeline runs the ordinary solve, then, with a level on, trials where eligible parts are offered as kerf-gap pair compounds. Placed pairs expand into parts plus explicit NestJobCommonLine groups, are validated again, and CommonLineRanking keeps a trial only by the level: count first, then sheets; "when it adds parts" keeps the plain layout on a tie, "whenever" also takes a shorter cut or less material, never at the cost of a part. Engines, FillScore and their comparers are unchanged; Off asks the engine exactly what it did. - NestLayoutCheck exempts members only through a sheet's explicit group list and only when the job allows common lines; materializing and committing create Plate.CommonLines. - Server nesting writes common-line jobs as version 3 and replays the recorded trial answers, so the desktop binds the same groups. - Fill Area honors the level through a PlateFillService overload. - The benchmark gains --common-lines <level> --kerf <k>. Benchmark (synthetic nests + N26-295, --parallel 1): with no flag and with --common-lines off every engine matches the base commit; with a level on no layout becomes invalid and three runs save a sheet at equal nested area. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
3.0 KiB
Benchmarking whole-job engines
OpenNest.Benchmark runs each registered INestingEngine against .nest files or JSON manifests of DXFs and quantities. It ranks complete jobs first, then salvage-credited sheet cost with a penalty for each unplaced part. Invalid runs (bounds, spacing, quantity, rotation, or stock mismatch) place nothing and pay the penalty.
dotnet run --project OpenNest.Benchmark -- ./benchmark-jobs \
--sheet-sizes 48x96,60x120,72x120 --engines Irregular,Rectangles --csv results.csv
Supply --sheet-sizes for an independent candidate pool; otherwise a saved nest offers only its original sheet sizes, which can bias comparisons. A saved nest's first plate also supplies spacing, quadrant and clamps: its machine clamp rail is resolved for every candidate size, as desktop Auto Nest does, and its baseline layout is checked against the clamps it was made with. Manifests have no clamps. A manifest part rotates freely (automatic rotation: any angle) unless "allowRotation": false locks it at 0°, or "rotations" lists its only angles in degrees: [0], [0, 180] or [0, 90, 180, 270]. A manifest's "offcutCut": "horizontal" (or "vertical") sets NestJobOptions.OffcutCut, so only full-width (or full-length) edge strips count as offcut; use it to match a benchmark that scores used sheet height (or length). A saved nest records its salvage rate, but salvage credit applies only with a positive --min-salvage-dimension. Without it, every complete one-sheet layout costs the same, as in desktop Auto Nest on a single plate size. The default --parallel 3 runs solves concurrently and confounds per-engine timing; use --parallel 1 for timing comparisons. --progress logs each solve's start, engine progress, and finish. --time-limit <seconds> stops each solve at that wall-clock limit and scores the best valid plan the engine had reported (see time limits); a solve with none counts as timed out. Without a limit the harness abandons a solve after five minutes; with one it waits for the limit plus a minute, so the engine's limit always fires first. Retain input hashes, exact commands, validity, fulfillment, costs, and raw results outside source control when comparing revisions; see fill performance verification.
--common-lines off|when-it-adds-parts|whenever --kerf <k> solves each job through NestPipeline (as desktop Auto Nest does) with every part allowed to share a common line at that level; compare a level with --common-lines off, not with a run without the option, which calls the engine directly. Report placed parts and absolute nested area, not only utilization.
Custom engines are DLLs implementing INestingEngine with a public parameterless constructor, loaded from Engines/ beside the benchmark executable. See nesting engines for built-ins and engine-change rules. Run dotnet run --project OpenNest.Benchmark -- --help for all options.