Collision.HasOverlap (and Part.Intersects, which shares the same
underlying algorithm) was observed to return false negatives on real,
complex production geometry: a layout with a combined placed area over
7x the plate's work area passed the polygon-based spacing/overlap
check with zero flagged pairs. This is a pre-existing gap in
OpenNest.Core's Collision detection, not something introduced here,
but it let an obviously-invalid layout score as "valid".
ValidateAreaBudget adds a hard mathematical backstop that does not
depend on Collision at all: non-overlapping parts confined to the work
area can never have a combined area greater than the work area itself.
Also switch WorldPolygon from Shape.ToPolygon() (default up to 1000
segments per arc) to ToPolygonWithTolerance(0.01), matching the
convention already used elsewhere in the codebase (e.g.
BestFit.PolygonHelper) - arc-heavy real parts were producing
thousands-of-vertex polygons for a simple spacing check.
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.