# OpenNest.Engine.Qwen38FlashNext An independent whole-job `INestingEngine` built by Qwen3.8-Flash-Next: **bottom-left greedy insertion over convex no-fit polygons with an exact clearance gate**. It does not call, wrap, or select over any built-in engine, nester, filler, or runner. ## Algorithm Bottom-left greedy insertion over convex No-Fit-Polygons, with an exact material-clearance gate, driven sheet by sheet by a greedy demand scheduler. All geometry math is the engine's own (`Engine/`); it calls no built-in nester, filler, or runner. - **`PartPreparation`** rebuilds each snapshot into a closed contour topology (perimeter + cutouts; rapids/scribe marks dropped), flattens it circumscribed (the collision polygon always contains the true material), and caches per-(part, angle, spacing) geometry: bounds, convex hull, and the spacing-inflated outline **rotated into that orientation's frame** (offset commutes with rotation; an unrotated inflation tests the candidate against the material of a different angle - this was a real overlap bug, caught by `RotatedConcavePartsKeepSpacingAtFixedAngles`). Candidate angles are the policy angles, or 0/90/180/270 plus the rotating-calipers minimum-bounding-rectangle angle for automatic rotation. - **`SheetPacker`** places one part instance at a time. Per already-placed part it builds a convex NFP as `placedHull (+) disk(spacing) (+) reflect(candidateHull)` via its own Minkowski edge-merge (`Convex.cs`; the merge picks the more-clockwise frontier edge, an inverted comparison here corrupts every non-parallel sum into a self-intersecting contour), then enumerates corner-point candidates: anchor work-box corners, NFP vertices, and NFP-edge/box-line slides, tried in ascending bottom-left order. Because the NFP is hull-based it only *certifies* clearance when both parts are convex solids with uncapped hulls; everything else falls through to the exact gate - placed material inflated by the spacing (holes shrunk, closed holes treated solid) versus the candidate's raw material with holes subtracted, the same inflation rule the benchmark validator uses, so interlocking concave parts are placed legally where the convex NFP alone would reject them. A uniform spatial grid keeps the pair tests near-constant as the sheet fills, and an overlap memo keyed by world pose collapses repeated clipper work across stock trials. - **`FastPoly` / `CachedCollision` (`TriSet`)** make the exact gate cheap. Each orientation caches flat-array triangulations of its raw material and its spacing-inflated gate material; a candidate-vs-placed pair then runs the built-in clipper algorithm on plain double arrays with the anchor offsets as translations - no `Polygon` clones, no per-check re-triangulation, no LINQ. A uniform edge grid on the gate outlines certifies disjoint shell pairs (clear) and convex-solid crossings (overlap) before any clip work; the certification is three-state (touch and collinear contact defer to the clip, containment is decided by sampled interior tests) so it can never report a false clear - cross-validated against `Collision.HasOverlap` over ~2.5M decisions per job run with zero verdict mismatches, and hole-clipping overflow falls back to the exact `Polygon` gate (0.2% of checks on the production job below). - **`JobSolver`** walks demands in its own order (priority, then largest material area - big parts first lay down the sheet skeleton the small parts fill against; measured 12% lower job cost than smallest-extent-first on the production job below) and drains each greedily, then a time-boxed gap-fill pass. For the next sheet it trials *every* available stock size independently and commits the trial delivering the cheapest plate area per unit of part area placed (the benchmark's cost function), breaking ties by priority coverage, instance count, then plate area; lost trials change no job state. The job stops on met demand, exhausted stock, no further placement, or the plate cap. Deterministic: identical input, identical layout. Trade-offs: greedy BLFG insertion leaves some of the density interlocking-pair and compaction pipelines find on regular jobs, and every stock size is trialled per sheet (O(sheets x stocks x fill)); on the 69-drawing/219-part production job below that costs ~110 s against the benchmark's 5-minute per-solve timeout. In exchange it places arcs, concaves, and holed parts under one uniform gate with no per-shape-class special cases. ## Benchmark results A real laser-cutting production job: 69 drawings, 219 parts, 3/16 mild steel, spacing 0.3, `--parallel 1`, same OpenNest build for every engine. | Sheet sizes offered | Result | Sheets | Utilization | Cost | Time | |---|---|---|---|---|---| | The job's own 4 sizes (60x96, 60x120, 72x120, 48x144) | valid, 219/219 | 28 | 78.4% | 219,744 | ~106 s | | OpenNest's standard 9-size catalog | valid, 219/219 | 14 | 56.6% | 304,128 | ~132 s | It uses the fewest sheets of any engine tested, but not the least material. The shop's original hand layout used 29 sheets (191,232 sq in). **Known weakness:** sheet choice is greedy one sheet at a time, so with large stock available it grabs 96x240 sheets and under-fills them. Optimization history on this job (all valid, 219/219): count-first trial scoring and span-first demand order cost 258048/39 plates; cost-first trial scoring brought it to 249696 (39); area-first demand order to 219744 (28). Wall time went from timeout (>400 s) to ~110 s via the cached-triangulation exact gate and the fast shell prefilter. ## Tests `tests/` holds acceptance tests whose layouts are checked by the benchmark's own `NestValidator` (bounds, spacing, quantities, stock, rotation), plus NFP geometry tests and a rotated-concave spacing regression test. ```bash dotnet test OpenNest.Engine.Qwen38FlashNext/tests/OpenNest.Engine.Qwen38FlashNext.Tests.csproj ``` ## Build and benchmark The project is a plugin outside `OpenNest.sln`. `OpenNest.Benchmark` loads plugin engines from an `Engines/` folder next to its own build output: ```bash dotnet build OpenNest.Engine.Qwen38FlashNext/OpenNest.Engine.Qwen38FlashNext.csproj -c Release dotnet build /OpenNest.Benchmark/OpenNest.Benchmark.csproj -c Release mkdir -p /OpenNest.Benchmark/bin/Release/net8.0/Engines cp OpenNest.Engine.Qwen38FlashNext/bin/Release/net8.0/OpenNest.Engine.Qwen38FlashNext.dll /OpenNest.Benchmark/bin/Release/net8.0/Engines/ dotnet /OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll --parallel 1 ``` `` is the OpenNest checkout root. Or build and deploy in one step with `./Build-Engines.ps1 -Engines Qwen38FlashNext`. The engine appears in reports as `Qwen38FlashNextNestingEngine`.