BlockCatalog's PrepareBlocks pre-pass ran a full independent NFP-based
pack (PrivatePlateFill.Run) for up to 8 attempts per part type, but that
cost never touched the engine's WorkCounter/WorkBudget. For jobs with
several part types at double-digit quantities, these uncounted nested
solves could burn the entire 5-minute timeout inside the first sheet of
the first strategy variant, so Solve() never returned and nothing was
ever committed.
Charge quantity^2 * outline vertex count against the shared counter
before each nested fill, and stop issuing new block proposals once the
budget is exhausted, so the existing effort governor actually sees and
bounds this cost.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Move BlockCatalog's private-drawing Fill invocation (BestFitCache stabilization plus
the Default FillItem call) into PrivatePlateFill so the cutout fill can reuse it
without duplicating the cache handling. Behavior unchanged; Irregular filter 96/96.
Orientation bounds were padded by the arc chord tolerance even when the outline has no arcs, so a part that exactly fills the work area after rotation was rejected before packing. Pad only outlines with flattened arcs; footprints and NFPs still use the chord tolerance.
Moves the two production plug-in engines into OpenNest.Engine under names
that describe the jobs they suit:
- Rectangles: plain and near-rectangular plates, maximal-rectangles box
packing (was the RectanglesNestingEngine plug-in)
- Irregular: irregular profiles, no-fit-polygon frontier packing (was the
Opus55NestingEngine plug-in)
Their tests and the shared engine contract/layout test kit move into
OpenNest.Engine.Tests/NestingEngines.
The registry maps the old plug-in names to the new engines, so saved desktop
selections, scripts and API requests keep working, and a leftover plug-in DLL
under an old name cannot shadow its replacement. Desktop startup passes the
registry's lookup when restoring the saved Auto Nest engine.