Previously each job fixed one plate size and ran a single Nest() call, which doesn't reflect the actual problem: a real job is fulfilled across however many plates are needed, drawn from a pool of standard sheet sizes, not forced onto one fixed sheet. NestEngineBase.Nest() has no way to pick its own plate's size - it fills whatever Plate it's given - so size selection now lives in the harness itself, applied identically to every engine: - BenchmarkJob carries the full candidate size pool (CandidateSizes) instead of one fixed PlateSize; one job per file, not one per size. - BenchmarkRunner drives a loop: while items remain, pick the smallest candidate size that fits the largest still-unplaced drawing (reusing the codebase's own MultiPlateNester.CreatePlate/FitsBounds), build a fresh plate of that size, and run one Nest() call to fill it. Repeat until everything is placed, no candidate size fits what's left, or a safety cap (40 plates) is hit. - NestValidator now validates bounds/spacing per plate but the quantity cap once globally across all plates, since that limit belongs to the whole order, not any one sheet. - JobResult/Report report PlatesUsed and a per-size breakdown instead of a single-plate bounding-box compactness metric; utilization is now aggregated across every plate the engine used. Ranking keeps the same rule (utilization first), with fewer plates as the tie-break when both are fully placed and tied - the natural multi-plate analogue of the old single-plate compactness tie-break. Smoke-tested against the synthetic sample across 5 candidate sizes: correctly builds one job, picks the smallest fitting size, uses however many plates each engine needs (1-2 here), and still catches StripNestEngine's pre-existing out-of-bounds bug.
OpenNest
A Windows desktop application for CNC nesting — imports DXF drawings, arranges parts on material plates, and exports layouts as DXF or G-code for cutting.
OpenNest takes your part drawings, lets you define your sheet (plate) sizes, and arranges the parts to make efficient use of material. The result can be exported as DXF files or post-processed into G-code that your CNC cutting machine understands.
Features
Import & Export
| Feature | Description |
|---|---|
| DXF/DWG Import | Load part drawings from AutoCAD DXF or DWG files via ACadSharp |
| DXF Export | Export completed nest layouts back to DXF for downstream tools |
| BOM Import | Batch-import part lists with quantities from Excel spreadsheets |
| Bend Line Detection | Import bend lines from DXF via pluggable detectors (SolidWorks flat pattern built in) |
| Built-in Shapes | 12 parametric shapes (circles, rectangles, L/T/flange, etc.) for quick parts |
Nesting
| Feature | Description |
|---|---|
| Pluggable Engines | Default multi-phase, Vertical Remnant, Horizontal Remnant, plus custom plugin DLLs |
| Fill Strategies | Linear grid, interlocking pairs, rectangle best-fit, and extents-based tiling |
| Best-Fit Pair Nesting | NFP-based pair evaluation finds tight interlocking orientations between parts |
| Gravity Compaction | Geometry-based directional push that preserves part spacing, including rotated parts and near passes between outlines |
| Part Rotation | Automatic angle sweep to find better fits across allowed orientations |
| Multi-Plate Support | Manage multiple plates of different sizes and materials in one nest |
Plate Operations
| Feature | Description |
|---|---|
| Sheet Cut-Offs | Auto-generated trim cuts with geometry-aware clearance around placed parts |
| Drawing Splitting | Split oversized parts with straight cuts, weld-gap tabs, or spike-groove joints |
| Interactive Editing | Zoom, pan, select, clone, rotate, push, and manually arrange parts |
CNC Output
| Feature | Description |
|---|---|
| Lead-Ins, Lead-Outs & Tabs | Configurable approach/exit paths and holding tabs with snap placement |
| Contour & Program Editing | Inline G-code editor with contour reordering and cut-direction reversal |
| User-Defined Variables | Named G-code variables ($name) emitted as machine variables (#200+) at post time |
| Post-Processors | Plugin-based G-code generation; Cincinnati CL-707/800/900/940/CLX included |
Prerequisites
- Windows 10 or later
- .NET 8 SDK
Getting Started
Build
git clone https://github.com/ajisaacs/OpenNest.git
cd OpenNest
dotnet build OpenNest.sln
Run
dotnet run --project OpenNest/OpenNest.csproj
Or open OpenNest.sln in Visual Studio and run the OpenNest project.
Quick Walkthrough
- Create a nest — File > New Nest
- Add drawings — Import DXF files via the CAD Converter (handles bend detection, layer filtering, and color/linetype exclusion) or create built-in shapes
- Set up a plate — Define the plate size, material, quadrant, and spacing
- Fill the plate — The nesting engine arranges parts automatically using the active fill strategy
- Add cut-offs — Optionally add horizontal/vertical cut-off lines to trim unused plate material
- Export — Save as a
.nestfile, export to DXF, or post-process to G-code
CAD Converter
The CAD Converter turns DXF/DWG files into nest-ready drawings. Detected bend notes replace their original CAD annotations in the preview, avoiding duplicate labels without hiding unrelated text. Toggle layers, colors, and linetypes to exclude construction geometry; review detected bend lines; and preview the generated cut program with contour ordering before accepting the drawing into the nest.
Command-Line Interface
OpenNest includes a CLI for batch nesting without the GUI — useful for automation, scripting, and CI pipelines.
dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- <input-files> [options]
Import DXF files and nest onto a plate:
# Import a DXF and fill a 60x120 plate
dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- part.dxf --size 60x120
# Import multiple DXFs with mixed-part auto-nesting (experimental)
dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- part1.dxf part2.dxf --size 60x120 --autonest
Work with existing nest files:
# Re-fill an existing nest file
dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- project.zip
# Add a new DXF to an existing nest and auto-nest
dotnet run --project OpenNest.Console/OpenNest.Console.csproj -- project.zip extra-part.dxf --autonest
Options:
| Option | Description |
|---|---|
--size <WxL> |
Plate size (e.g. 60x120). Required for DXF-only mode. |
--autonest |
Use mixed-part nesting instead of linear fill (experimental) |
--drawing <name> |
Select which drawing to fill with (default: first) |
--quantity <n> |
Max parts to place (default: unlimited) |
--spacing <value> |
Override part spacing |
--template <path> |
Load plate defaults (thickness, quadrant, material, spacing) from a nest file |
--output <path> |
Output file path (default: <input>-result.zip) |
--keep-parts |
Keep existing parts instead of clearing before fill |
--check-overlaps |
Run overlap detection after fill (exits with code 1 if found) |
--engine <name> |
Select a registered nesting engine |
--post <name> |
Post-process the result with the named post-processor plugin |
--no-save |
Skip saving the output file |
--no-log |
Skip writing the debug log |
Benchmarking Nest Engines
OpenNest.Benchmark compares every registered NestEngineBase implementation against each other on a set of .nest files, scoring by material utilization:
# Benchmark all registered engines against every .nest file in a folder
dotnet run --project OpenNest.Benchmark/OpenNest.Benchmark.csproj -- ./benchmark-jobs
# Sweep a fixed list of sheet sizes instead of each file's own, limit to specific engines
dotnet run --project OpenNest.Benchmark/OpenNest.Benchmark.csproj -- job.nest \
--sheet-sizes 48x96,60x96,60x120,72x120,72x144 --engines Default,Astra,Claude --csv results.csv
An engine's layout is rejected (scoring zero for that job) if any part falls outside the work area, any two parts are closer than the required spacing, or a drawing gets more parts placed than requested.
Project Structure
OpenNest.sln
├── OpenNest/ # WinForms desktop application (UI)
├── OpenNest.Core/ # Domain model, geometry, and CNC primitives
├── OpenNest.Engine/ # Nesting algorithms (fill, pack, compact, best-fit)
├── OpenNest.IO/ # File I/O — DXF import/export, nest file format
├── OpenNest.Console/ # Command-line interface for batch nesting
├── OpenNest.Api/ # Programmatic nesting API (NestRunner pipeline)
├── OpenNest.Data/ # Machine configuration and cutting parameters
├── OpenNest.Gpu/ # GPU-accelerated pair evaluation (ILGPU)
├── OpenNest.Training/ # ML training data collection (SQLite + EF Core)
├── OpenNest.Benchmark/ # Head-to-head comparison of registered nest engines
├── OpenNest.Mcp/ # MCP server for AI tool integration
├── OpenNest.Posts.Cincinnati/ # Cincinnati CL-707 laser post-processor plugin
└── OpenNest.Tests/ # Unit tests (xUnit)
| Project | What it does |
|---|---|
| OpenNest | The app you run. WinForms MDI interface with plate viewer, drawing list, CAD converter, and dialogs. |
| OpenNest.Console | Command-line interface for batch nesting, scripting, and automation. |
| OpenNest.Core | The building blocks — parts, plates, drawings, geometry, G-code representation, bend lines, cut-offs, and drawing splitting. |
| OpenNest.Engine | The brains — fill strategies (linear, pairs, rect best-fit, extents), NFP-based pair evaluation, gravity compaction, and a pluggable engine registry. |
| OpenNest.IO | Reads and writes files — DXF/DWG (via ACadSharp), G-code, the .nest ZIP format, BOM spreadsheets (via ClosedXML), and bend detection from CAD files. |
| OpenNest.Api | High-level API for running the full nesting pipeline programmatically (import, nest, export). |
| OpenNest.Data | Machine configuration data layer — stores machine profiles, material/thickness parameters, lead-in/lead-out settings, and cut-off defaults. JSON-based local storage with an IDataProvider interface. |
| OpenNest.Gpu | GPU-accelerated bitmap overlap detection for best-fit pair evaluation using ILGPU. |
| OpenNest.Posts.Cincinnati | Post-processor plugin for Cincinnati CL-707/800/900/940/CLX laser cutting machines. Outputs Cincinnati-format G-code with material library, kerf compensation, and pierce logic. |
| OpenNest.Mcp | MCP (Model Context Protocol) server exposing nesting operations as tools for AI assistants. |
| OpenNest.Benchmark | Runs every registered nest engine against a set of .nest files and scores them by material utilization, so engine implementations can be compared head-to-head. |
| OpenNest.Tests | 89 test files covering core geometry, fill strategies, splitting, bending, BOM import, post-processing, and the API. |
Nesting Engines
OpenNest uses a pluggable engine architecture. The active engine can be selected at runtime.
| Engine | Description |
|---|---|
| Default | Multi-phase strategy: linear fill, pair fill, rect best-fit, then remainder. Balances density and speed. |
| Vertical Remnant | Optimizes for a clean vertical drop on the right side of the plate. |
| Horizontal Remnant | Optimizes for a clean horizontal drop on the top of the plate. |
Custom engines can be built by subclassing NestEngineBase and registering via NestEngineRegistry or dropping a plugin DLL in the Engines/ directory.
Fill Strategies
Each engine composes from a set of fill strategies:
| Strategy | Description |
|---|---|
| Linear | Grid-based fill with geometry-aware copy distance and 4-config rotation/axis optimization |
| Pairs | NFP-based interlocking pair evaluation — finds tight-fitting orientations between two parts |
| Rect Best-Fit | Greedy rectangle bin-packing with horizontal and vertical orientation trials |
| Extents | Extents-based pair tiling for simple rectangular arrangements |
Drawing Splitting
Oversized parts that don't fit on a single plate can be split into smaller pieces:
- Straight Split — Clean cut with no joining features
- Weld-Gap Tabs — Rectangular tab spacers on one side for weld alignment
- Spike-Groove — Interlocking V-shaped spike and groove pairs for self-aligning joints
The split system supports fit-to-plate (auto-calculates split lines) and split-by-count modes, with an interactive UI for adjusting split positions and feature parameters.
Cutout-aware clipping. Split lines are trimmed against interior cutouts so cut paths never travel through a hole. Lines are Liang-Barsky clipped at region boundaries and arcs/circles are iteratively split at their intersections with the region box, so a cutout that straddles a split correctly contributes material to both sides. When a cutout fully spans the region between two splits, the material breaks into physically disconnected strips — the splitter detects the connected components via endpoint connectivity, nests any remaining holes inside their outer loops by bounding-box and point-in-polygon containment, and emits one drawing per strip.
Post-Processors
Post-processors convert nested layouts into machine-specific G-code. They are loaded as plugin DLLs from the Posts/ directory at runtime.
Included:
- Cincinnati — Full post-processor for Cincinnati CL-707/800/900/940/CLX laser cutting machines with variable declarations, material library resolution, speed classification, kerf compensation, and optional part sub-programs (M98).
Custom post-processors implement the IPostProcessor interface and are auto-discovered from DLLs in the Posts/ directory.
Keyboard Shortcuts
| Key | Action |
|---|---|
Ctrl+F |
Fill the area around the cursor with the selected drawing |
F |
Zoom to fit the plate view |
Shift + Mouse Wheel |
Rotate parts when a drawing is selected |
Shift + Left Click |
Push the selected group of parts to the bottom-left most point |
| Middle Mouse Click | Rotate selected parts 90 degrees |
X |
Push selected parts left (negative X) |
Shift+X |
Push selected parts right (positive X) |
Y |
Push selected parts down (negative Y) |
Shift+Y |
Push selected parts up (positive Y) |
| Arrow Keys | Nudge selected parts by an increment |
Shift + Arrow Keys |
Push selected parts in that direction |
Supported Formats
| Format | Import | Export |
|---|---|---|
| DXF (AutoCAD Drawing Exchange) | Yes | Yes |
| DWG (AutoCAD Drawing) | Yes | No |
| Excel BOM (Bill of Materials) | Yes | No |
| G-code | No | Yes (via post-processors) |
.nest (ZIP-based project format) |
Yes | Yes |
Nest File Format
Nest files (.nest) are ZIP archives containing:
nest.json— JSON metadata: nest info (name, customer, units, material, thickness, assist gas, salvage rate), plate defaults, plate options (alternative sizes with cost), drawings (with bend lines, material, source path, rotation constraints), and plates (size, quadrant, grain angle, parts with manual lead-in flags, cut-offs)programs/program-N— G-code text for drawing N's cut program (may include variable definitions and$namereferences)programs/program-N-subs— Sub-program definitions for drawing N (M98/G65-callable blocks for repeated features like holes)entities/entities-N— Original source entities for drawing N (preserved from DXF import with per-entity suppression state for round-trip editing)bestfits/bestfit-N— Cached best-fit pair evaluation results for drawing N, keyed by plate size and spacing (optional)
Status
OpenNest is under active development. The core nesting workflows function end-to-end — from DXF import through filling, splitting, cut-offs, and G-code post-processing. Contributions and feedback are welcome.
License
This project is licensed under the MIT License.



