docs(engines): document built-in engines, renames and change rules
Adds docs/nesting-engines.md: which engine suits which jobs, the old plug-in names the registry maps, retired engines, and the rule that an engine change lands only when it beats that engine's current benchmark result with every layout valid. README, release and automatic-nesting docs drop the bundled plug-in wording; AGENTS.md now places built-in engines in OpenNest.Engine/NestingEngines and keeps only external plug-ins out of the solution.
This commit is contained in:
@@ -34,7 +34,7 @@ Releases: follow [the release procedure](docs/releasing.md) and `scripts/Publish
|
|||||||
|
|
||||||
- `OpenNest.Core`: domain (`Nest -> Plate -> Part -> Drawing -> CNC.Program`), geometry, cutting strategies and diagnostics. Angles are radians; use `Tolerance.Epsilon` for geometry comparisons. `OpenNest.Math` shadows `System.Math`, so qualify the latter.
|
- `OpenNest.Core`: domain (`Nest -> Plate -> Part -> Drawing -> CNC.Program`), geometry, cutting strategies and diagnostics. Angles are radians; use `Tolerance.Epsilon` for geometry comparisons. `OpenNest.Math` shadows `System.Math`, so qualify the latter.
|
||||||
- `OpenNest.Engine`: whole-job API in `Jobs/`, interactive proposals via `PlateFillService`, fill strategies, best-fit pairs, packing, sequencing and rapid planning. `INestingEngine.Solve(NestJob)` returns stock IDs/poses; boundary adapters map drawings and materialize results. `NestJobRunner` validates its candidates before committing demand/stock accounting. Do not assume arbitrary plug-in output or interactive paths received that validation. Job identity is reference-based, not drawing-name-based.
|
- `OpenNest.Engine`: whole-job API in `Jobs/`, interactive proposals via `PlateFillService`, fill strategies, best-fit pairs, packing, sequencing and rapid planning. `INestingEngine.Solve(NestJob)` returns stock IDs/poses; boundary adapters map drawings and materialize results. `NestJobRunner` validates its candidates before committing demand/stock accounting. Do not assume arbitrary plug-in output or interactive paths received that validation. Job identity is reference-based, not drawing-name-based.
|
||||||
- Engine plug-ins implement `INestingEngine` with a public parameterless constructor, reference Engine and load from `Engines/` beside the host. Build them outside this repository/solution; do not add their projects here.
|
- Built-in whole-job engines live in `OpenNest.Engine/NestingEngines/<Name>/`, named for the jobs they suit; see [nesting engines](docs/nesting-engines.md). A change must beat that engine's current benchmark result with every layout valid. External plug-ins implement `INestingEngine` with a public parameterless constructor and load from `Engines/` beside the host; keep their projects out of this solution.
|
||||||
- `OpenNest.IO`: ACadSharp import/export and ZIP-based `.nest` persistence. All DXF-to-Drawing conversion goes through `CadImporter`: `Import` + `BuildDrawing` for editable/reporting flows, `ImportDrawing` for headless callers. Preserve source offsets, entity IDs, suppressed entities and bends. Bend repair is opt-in, requires explicit source units and may not alter cut geometry or unrelated marks.
|
- `OpenNest.IO`: ACadSharp import/export and ZIP-based `.nest` persistence. All DXF-to-Drawing conversion goes through `CadImporter`: `Import` + `BuildDrawing` for editable/reporting flows, `ImportDrawing` for headless callers. Preserve source offsets, entity IDs, suppressed entities and bends. Bend repair is opt-in, requires explicit source units and may not alter cut geometry or unrelated marks.
|
||||||
- `OpenNest`: WinForms UI (`Forms/`, `Controls/PlateView`, `Actions/`). `OpenNest.Data` holds cross-platform persistence; new-nest defaults live in `%APPDATA%\OpenNest\defaults.json`. Posts live in `Posts/OpenNest.Posts.<Name>/` and deploy to the desktop output's `Posts/` directory.
|
- `OpenNest`: WinForms UI (`Forms/`, `Controls/PlateView`, `Actions/`). `OpenNest.Data` holds cross-platform persistence; new-nest defaults live in `%APPDATA%\OpenNest\defaults.json`. Posts live in `Posts/OpenNest.Posts.<Name>/` and deploy to the desktop output's `Posts/` directory.
|
||||||
- `OpenNest.Console`, `OpenNest.Mcp`, `OpenNest.Api`: front ends; `OpenNest.Benchmark`: whole-job engine comparisons; `OpenNest.Gpu`: GPU evaluators; `OpenNest.Training`: ML data collection. Benchmark timing comparisons require `--parallel 1`; validate layouts and fulfillment, not just elapsed time.
|
- `OpenNest.Console`, `OpenNest.Mcp`, `OpenNest.Api`: front ends; `OpenNest.Benchmark`: whole-job engine comparisons; `OpenNest.Gpu`: GPU evaluators; `OpenNest.Training`: ML data collection. Benchmark timing comparisons require `--parallel 1`; validate layouts and fulfillment, not just elapsed time.
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ A Windows desktop application for CNC nesting — imports DXF drawings, arranges
|
|||||||
- Windows 10+ for the desktop app; the console, API, and most test projects build on Linux/macOS too.
|
- Windows 10+ for the desktop app; the console, API, and most test projects build on Linux/macOS too.
|
||||||
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) to build from source.
|
- [.NET 8 SDK](https://dotnet.microsoft.com/download/dotnet/8.0) to build from source.
|
||||||
|
|
||||||
Windows release ZIPs are self-contained: extract the entire archive into a new folder and run `OpenNest.exe`; no separate .NET installation is needed. The package includes the Gpt6Astra, Opus55, and Qwen38FlashNext engine plug-ins. Use the ZIP and SHA-256 checksum from [GitHub Releases](https://github.com/ajisaacs/OpenNest/releases), not the source-code archives.
|
Windows release ZIPs are self-contained: extract the entire archive into a new folder and run `OpenNest.exe`; no separate .NET installation is needed. The Rectangles and Irregular nesting engines are built in; see [nesting engines](docs/nesting-engines.md). Use the ZIP and SHA-256 checksum from [GitHub Releases](https://github.com/ajisaacs/OpenNest/releases), not the source-code archives.
|
||||||
|
|
||||||
## Build, Test, Run
|
## Build, Test, Run
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ dotnet run --project OpenNest.Benchmark -- ./benchmark-jobs \
|
|||||||
--sheet-sizes 48x96,60x120,72x120 --engines Default,StockLadder --csv results.csv
|
--sheet-sizes 48x96,60x120,72x120 --engines Default,StockLadder --csv results.csv
|
||||||
```
|
```
|
||||||
|
|
||||||
Layouts are validated (bounds, spacing, quantity, rotation, stock match); invalid runs place nothing and pay the penalty. `--parallel` (default 3) speeds up scoring but inflates `Time(ms)` — use `--parallel 1` when comparing speed. Pass `--sheet-sizes` for an unbiased run; otherwise only each file's original sizes are offered. `--progress` logs each solve's start, the engine's `NestJobProgress` (plate evaluations throttled to one line per 2 s, every plate commit) and its finish. Custom engines drop in as DLLs implementing `INestingEngine` (public parameterless constructor) in an `Engines/` folder next to the benchmark. Community engines live in [OpenNest-Engines](https://git.thecozycat.net/aj/OpenNest-Engines).
|
Layouts are validated (bounds, spacing, quantity, rotation, stock match); invalid runs place nothing and pay the penalty. `--parallel` (default 3) speeds up scoring but inflates `Time(ms)` — use `--parallel 1` when comparing speed. Pass `--sheet-sizes` for an unbiased run; otherwise only each file's original sizes are offered. `--progress` logs each solve's start, the engine's `NestJobProgress` (plate evaluations throttled to one line per 2 s, every plate commit) and its finish. Custom engines drop in as DLLs implementing `INestingEngine` (public parameterless constructor) in an `Engines/` folder next to the benchmark. Built-in engines and how to change them: [nesting engines](docs/nesting-engines.md).
|
||||||
|
|
||||||
## Project Structure
|
## Project Structure
|
||||||
|
|
||||||
@@ -91,11 +91,15 @@ Engines implement `INestingEngine.Solve(NestJob)`. Desktop Auto Nest, console au
|
|||||||
|
|
||||||
| Engine | Description |
|
| Engine | Description |
|
||||||
|--------|-------------|
|
|--------|-------------|
|
||||||
|
| **Rectangles** | Plain and near-rectangular plates: maximal-rectangles box packing |
|
||||||
|
| **Irregular** | Irregular profiles: no-fit-polygon frontier packing |
|
||||||
| **Default** | Multi-phase: linear fill → pairs → rect best-fit → extents |
|
| **Default** | Multi-phase: linear fill → pairs → rect best-fit → extents |
|
||||||
| **Strip** | Iterative shrink-fill for mixed-drawing layouts |
|
| **Strip** | Iterative shrink-fill for mixed-drawing layouts |
|
||||||
| **Vertical / Horizontal Remnant** | Optimizes a clean remnant drop on one edge |
|
| **Vertical / Horizontal Remnant** | Optimizes a clean remnant drop on one edge |
|
||||||
| **StockLadder** | Whole-job, stock-constrained baseline with salvage-credit ranking |
|
| **StockLadder** | Whole-job, stock-constrained baseline with salvage-credit ranking |
|
||||||
|
|
||||||
|
Which engine suits which jobs, renamed engine names, and the rules for changing an engine: [nesting engines](docs/nesting-engines.md).
|
||||||
|
|
||||||
## File Format
|
## File Format
|
||||||
|
|
||||||
`.nest` files are ZIP archives containing drawing programs, metadata, plates, and placements. Saved nests retain each part's lead-ins, lead-outs, tab gaps, and locks, plus the plate's cutting settings. Changing a drawing's geometry removes obsolete cutting paths from its parts; name, quantity, and color edits preserve them. See the [file-format reference](docs/nest-file-format.md) for compatibility and recovery behavior.
|
`.nest` files are ZIP archives containing drawing programs, metadata, plates, and placements. Saved nests retain each part's lead-ins, lead-outs, tab gaps, and locks, plus the plate's cutting settings. Changing a drawing's geometry removes obsolete cutting paths from its parts; name, quantity, and color edits preserve them. See the [file-format reference](docs/nest-file-format.md) for compatibility and recovery behavior.
|
||||||
|
|||||||
@@ -27,9 +27,10 @@ Every invalid result shows the validation report before any plates are changed:
|
|||||||
Overlap Check displays material overlaps, not every spacing/stock/rotation failure in the report. A layout passing validation may still be incomplete; completeness and stop reason are separate from geometric validity. This check does not replace pre-post CNC verification.
|
Overlap Check displays material overlaps, not every spacing/stock/rotation failure in the report. A layout passing validation may still be incomplete; completeness and stop reason are separate from geometric validity. This check does not replace pre-post CNC verification.
|
||||||
|
|
||||||
The selected engine is saved in `%APPDATA%\OpenNest\engine-selection.json`.
|
The selected engine is saved in `%APPDATA%\OpenNest\engine-selection.json`.
|
||||||
Selection is restored after plug-ins load. If the saved engine is unavailable,
|
Selection is restored after plug-ins load. A saved name from an earlier release
|
||||||
Default is selected and the status bar reports the fallback; startup does not
|
maps to the engine that replaced it (see [nesting engines](nesting-engines.md)).
|
||||||
replace the saved missing-engine preference.
|
If the saved engine is unavailable, Default is selected and the status bar
|
||||||
|
reports the fallback; startup does not replace the saved missing-engine preference.
|
||||||
|
|
||||||
## Integration constraints
|
## Integration constraints
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# Nesting engines
|
||||||
|
|
||||||
|
Whole-job engines implement `INestingEngine.Solve(NestJob)` and are selected by name through
|
||||||
|
`NestingEngineRegistry`. Every automatic nesting front end validates engine output the same way;
|
||||||
|
see [automatic nesting and validation](automatic-nesting.md).
|
||||||
|
|
||||||
|
## Built-in engines
|
||||||
|
|
||||||
|
Engines are named for the jobs they suit, not for how or by whom they were built. Engine code lives
|
||||||
|
in `OpenNest.Engine/NestingEngines/<Name>/`, its tests in `OpenNest.Engine.Tests/NestingEngines/`.
|
||||||
|
|
||||||
|
| Engine | Best for | Method |
|
||||||
|
|---|---|---|
|
||||||
|
| Rectangles | Plain and near-rectangular plates | Each part packed as the box of its material at its minimum-area rotation, using a maximal-rectangles free list; stock chosen sheet by sheet by salvage-credited look-ahead cost |
|
||||||
|
| Irregular | Irregular profiles | No-fit-polygon frontier packing with gap filling, six whole-job strategy variants and a tail re-plan |
|
||||||
|
| StockLadder | Caller-supplied stock ladders | Constrained-first fill with equivalent-demand area repacking |
|
||||||
|
| Default, Strip, Vertical Remnant, Horizontal Remnant | Single-strategy fills | The fixed placement strategies behind interactive fill |
|
||||||
|
|
||||||
|
Rectangles places irregular parts validly, but only as their bounding boxes; it never nests into a
|
||||||
|
notch or hole. Box sides account for how the layout check flattens arcs, so round-edged parts stay
|
||||||
|
valid at box contact.
|
||||||
|
|
||||||
|
## Renamed engines
|
||||||
|
|
||||||
|
Earlier releases shipped these as plug-ins under other names. The registry maps the old names so
|
||||||
|
saved desktop selections, scripts and API requests keep working:
|
||||||
|
|
||||||
|
| Old name | Now |
|
||||||
|
|---|---|
|
||||||
|
| `Opus55NestingEngine` | Irregular |
|
||||||
|
| `RectanglesNestingEngine` | Rectangles |
|
||||||
|
|
||||||
|
Gpt6Astra and Qwen38FlashNext are no longer shipped and have no alias. A saved selection of either
|
||||||
|
falls back to Default with the usual status-bar warning.
|
||||||
|
|
||||||
|
## Changing an engine
|
||||||
|
|
||||||
|
- A change lands only when it beats the engine's current result on `OpenNest.Benchmark` for the
|
||||||
|
jobs that engine targets, with every layout valid. Report cost, validity, unplaced parts and time.
|
||||||
|
- Placement must be deterministic: no clocks, unseeded randomness or environment variables. Budget
|
||||||
|
work by counting it; wall time may stop work only through the cancellation token.
|
||||||
|
- Keep each engine's tests passing, including `EngineContractTests<TEngine>` (quadrants, overflow,
|
||||||
|
priority, cancellation, stock and plate limits, determinism). Every layout in those tests is
|
||||||
|
checked with `NestLayoutCheck`, the benchmark's validator.
|
||||||
|
- Engines may share code. Move a helper into shared Engine code when a second engine needs it,
|
||||||
|
rather than copying it.
|
||||||
|
|
||||||
|
## Plug-ins
|
||||||
|
|
||||||
|
External engines still load from an `Engines/` folder beside the desktop, console, MCP or benchmark
|
||||||
|
executable. A plug-in implements `INestingEngine` with a public parameterless constructor and
|
||||||
|
registers under its CLR type name. A plug-in whose name matches a built-in engine, or a renamed
|
||||||
|
engine's old name, is skipped: a leftover `OpenNest.Engine.Opus55.dll` cannot shadow Irregular.
|
||||||
|
Leftover Gpt6Astra or Qwen38FlashNext DLLs still load as ordinary plug-ins until deleted.
|
||||||
+6
-7
@@ -19,13 +19,12 @@ Git refs are owned by Gitea (`aj/OpenNest`) and push-mirrored to GitHub
|
|||||||
4. Download the `OpenNest-X.Y.Z-win-x64` artifact and verify its `.sha256`.
|
4. Download the `OpenNest-X.Y.Z-win-x64` artifact and verify its `.sha256`.
|
||||||
It contains `OpenNest.vX.Y.Z.win-x64.zip`, with the .NET runtime, native
|
It contains `OpenNest.vX.Y.Z.win-x64.zip`, with the .NET runtime, native
|
||||||
dependencies, shipped configurations, all three post-processors, license,
|
dependencies, shipped configurations, all three post-processors, license,
|
||||||
and `build-info.json` identifying the exact source commit. Gpt6Astra, Opus55,
|
and `build-info.json` identifying the exact source commit. The nesting engines
|
||||||
and Qwen38FlashNext are bundled in `Engines/` with their MIT license and source
|
are built into `OpenNest.Engine.dll`; no external engine repository or plug-in
|
||||||
manifest. `scripts/external-engines.json` pins the external repository revision;
|
DLL is packaged. `scripts/ReleaseSmoke` loads the packaged engine assembly and
|
||||||
no moving branch or prebuilt third-party DLL is used. The script tests and
|
checks that every built-in engine instantiates from it, that the renamed
|
||||||
builds each engine against this host, then exercises actual packaged registry
|
`Opus55NestingEngine` selection resolves to Irregular, and that an unknown
|
||||||
discovery and an intentionally missing-DLL failure case. Keep the explicit
|
engine name is rejected.
|
||||||
engine allowlist; never package the template, shared test kit, or test DLLs.
|
|
||||||
|
|
||||||
The workflow has read-only repository permissions and does **not** publish
|
The workflow has read-only repository permissions and does **not** publish
|
||||||
releases. Once present on the default branch, it can also be dispatched manually
|
releases. Once present on the default branch, it can also be dispatched manually
|
||||||
|
|||||||
Reference in New Issue
Block a user