This repository has been archived on 2026-09-29. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
OpenNest-Engines/OpenNest.Engine.Rectangles
aj 13478f5102 feat(rectangles): add rectangle-lane maximal-rectangles engine
Nests every part as the axis-aligned box of its material at its minimum-area
rotation and packs boxes with a maximal-rectangles free list (6 placement rules x
global/ordered pick). Sheet choice uses the salvage-credited look-ahead cost.

Curved extremes read the way the layout check sees them (circumscribed arcs on
the Clipper grid), so discs, rings and obrounds stay valid at box contact; an
80-job sweep failed 16-50 jobs before that rule.

Local 2026 production lanes (--min-salvage-dimension 12, --parallel 3):
- 91 all-rectangular jobs: 91/91 valid, cost 333081 vs best general 332153
  (Gpt6Astra, 89/91 valid), 5.9 s vs 13.7 s (Opus55) and 169.5 s (Gpt6Astra)
- 77 box-filling (>= 90%) jobs: 77/77 valid, lowest total cost 641637
2026-09-29 20:49:00 -04:00
..

OpenNest.Engine.Rectangles

A whole-job INestingEngine for the rectangle lane: jobs whose parts are plain or near-rectangular plates. Every part is nested as the axis-aligned box of its material at its minimum-area rotation(s), packed with a maximal-rectangles free list (Jylänki, A Thousand Ways to Pack the Bin, 2010).

For these parts the box wastes almost nothing, and exact box packing is both denser and far faster than contour-sliding engines. Irregular parts are still placed validly, but only as their bounding boxes: nothing is nested into another part's notch or hole. Use a general engine (Opus55, Gpt6Astra) for irregular work.

Algorithm

1. Boxes (BoxCatalog)

  • Rotations come from the host's RotationCandidates.ForShape (the policy angles plus, for Automatic, the minimum-bounding-rectangle alignment). Only the rotations whose box area is within 1e-6 of the minimum are kept, with duplicate box shapes removed. A 10 x 4 plate drawn at 30° is squared up; a fixed-rotation part keeps its one angle.
  • Bounds use material contours only (rapids and scribe/etch excluded), like the layout check.
  • Curved extremes: the layout check circumscribes arcs and snaps to a 1e-4 grid, so a disc or obround reads slightly larger than its true arc. Each box side takes the check's own outline (ClipperBridge.OffsetForValidation) plus one grid unit wherever that outline sticks out by more than a quarter of NestTolerances.SpacingSlack. Straight-edged parts are unchanged and still pack at exactly the part spacing.

2. One sheet (MaxRectsSheet, SheetPacker)

  • Boxes and the work area are grown by the part spacing on their right/top sides, so touching grown boxes are exactly one spacing apart and the last box can touch the work-area edge.
  • The free list keeps every maximal empty rectangle; placing a box splits each free rectangle it hits and prunes the contained ones.
  • Six placement rules: best short side, best long side, best area, bottom-left, left-bottom and contact point. Two pick modes: global (each step places whichever remaining box scores best anywhere) and ordered (priority, then largest box first, each type filled until it stops fitting). Lower priority numbers are always served first.

3. Whole job (RectanglesNestingEngine)

  • Sheet by sheet, every available stock is packed under all 12 rule/mode pairs. The candidate with the lowest estimated whole-job cost wins: its salvage-credited NestJobCost.NetSheetArea, plus the remaining demand priced at the best net-area-per-part-area ratio any candidate reached. A candidate that leaves more of the most urgent priority tier unplaced never wins.
  • Deterministic: no clocks or randomness; the only stop besides completion is the host token.

Results

OpenNest.Benchmark, --min-salvage-dimension 12, each file's own sheet sizes, --parallel 3 (times are under that load). Synthetic results only here; the real-part corpus stays local.

Local corpus of converted 2026 production nests (file names and parts stay out of this repo):

Lane Jobs Engine Valid Total cost Time
Every part plain or near-rectangular 91 Rectangles 91 333,081 5.9 s
Gpt6Astra 89 332,153 169.5 s
Opus55 91 332,925 13.7 s
StockLadder 89 337,641 36.0 s
Every part fills ≥ 90% of its box 77 Rectangles 77 641,637 19.1 s
Gpt6Astra 76 651,514 195.6 s
StockLadder 76 671,590 93.4 s
Opus55 76 693,972 31.8 s

Rectangles never leaves a part unplaced that another engine placed. Its losses are a handful of multi-sheet jobs where the sheet-by-sheet greedy choice commits to a worse sheet mix (see Next).

tests/ (27 tests): contract, starter and engine tests, including an 80-job sweep of discs, rings, obrounds and triangles at four spacings that failed 16–50 jobs before the curved-extreme rule.

Next

  • Multi-sheet jobs: the sheet-by-sheet greedy choice loses to whole-plan search on a few jobs. Re-plan the last sheets and try whole-job variants, as Opus55 does.
  • Guillotine-only mode for shears and for cut-off-friendly layouts.
  • Exhaustive search for small jobs (one or two part types).