Console --engine now names a jobs engine for --autonest (solved once
through NestingEngineRegistry.Create and committed onto the plate) or a
built-in fill strategy for single-plate fill through the public
PlateFillService; unknown names exit with the valid choices instead of
consulting the process-global legacy registry. MCP nesting tools take an
explicit engine argument per call with the session default, never read
process-global active-engine state, and reject whole-job engine names on
single-plate fill tools. NestingEngineRegistry gains an explicit Create
(name) resolution; PlateFillService gains a public ResolveStrategy and a
plate-number Nest overload used by interactive callers.
Pin committed fulfillment and exact placement poses for Default, Strip,
Vertical Remnant, and Horizontal Remnant through the production
PlateNesterFactory + NestJobRunner path, plus deterministic poses for
OrderedPlateNester via its StockLadder wiring (no legacy counterpart) and
authoritative progress-stage sequences for StockLadder and
FixedStrategyNestingEngine. Captured at 42bbde7 (post ShrinkFiller axis
fix); these fixtures are the regression net for the legacy-engine removal.
Note: Strip is pinned on a rectangle-variety job. On dense mixed-shape
jobs the iterative shrink path intermittently proposes overlapping
candidates (pre-existing scheduling nondeterminism), so its mixed-geometry
layout is deliberately not pinned.
Repo-wide sweep with the pinned CSharpier 1.3.0 tool. Whitespace and
line-wrapping only; OpenNest.Engine.Tests (109) and OpenNest.IO.Tests
pass after reformat, full solution builds 0 errors.
Added .csharpierignore so csproj/config XML keeps its existing layout
(CSharpier's XML wrapping churns attributes with zero benefit).
Formatting is now enforceable: dotnet csharpier check . passes.
The witness-probe overlap test missed small corner intersections: its
candidate points (crossing-edge midpoints and vertex-centroid midpoints)
can all land on a part boundary or outside the intersection, so two 10x10
parts at (0,0) and (9,9) with zero spacing were accepted despite sharing
a 1x1 unit of material.
Route the overlap decision through Collision, which clips triangulated
polygons and keeps only positive-area regions, catching corner overlaps,
containment, and coincident poses while legal edge/corner contact stays
legal. Collision's hole subtraction was conservative (partially-clipped
triangles were kept whole), so a part inside another part's cutout could
false-positive depending on triangulation alignment; subtract holes
exactly instead: a piece outside a convex hole triangle is the union of
its clips against each edge's outside half-space.
Implements a sealed adapter class that forces a fixed IPlateNester strategy onto
any NestJob, overriding the job's own PlacementStrategy while preserving MaxPlates.
Delegates all multi-plate allocation and stock selection to NestJobRunner.
This allows single-plate nesting strategies to compete as full whole-job
INestingEngine solvers in benchmarks, enabling comparative performance testing
of placement algorithms across various job configurations.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Task 5 of the whole-job engine API: add a geometry safety gate that
validates every candidate trial before the runner commits accounting.
- NestJobPlacementValidator: closed-contour validity, rotation-policy
compliance, work-area containment per quadrant, hole-aware material
overlap, and required part spacing. Overlap is interior-only, so
zero-clearance edge/corner contact remains a valid placement.
- NestJobValidator: route candidate validation through the geometry
gate; reject unusable/unclosed/degenerate contours up front.
- NestJobRunner: wrap candidate evaluation in a progress bridge that
tags legacy engine detail with the current candidate context.
- LegacyPlateNesterAdapter: forward IProgress to the legacy engine so
its progress surfaces under the active candidate.
- Tests: geometry (quadrants, rotations, touching, containment, holes,
empty stock, real Default/Strip smoke), validation, and cancellation
suites; repaired test fakes that emitted out-of-bounds or overlapping
placements the gate now correctly rejects.
Engine.Tests: 70 passed, 0 failed, 0 skipped in Debug and Release.
Windows-only OpenNest.Tests not run on Linux.
Replace name-based quantity deduction with reference-based drawing
identity in the engine paths the whole-job runner reaches
(NestEngineBase fill/pack, StripNestEngine deduction, RemnantFiller
ledger, IterativeShrinkFiller leftovers). Add instance-scoped
PlateNesterFactory that resolves built-in strategies without touching
the global NestEngineRegistry. Add identity and engine-selection tests.
44 net8.0 tests pass in Debug and Release; no new warnings.