New engines start from the shared test kit (the template's tests are a one-line EngineContractTests subclass) and the host APIs, so they don't re-derive geometry reading, work areas or validator tolerances. BENCH-RULES.md now forbids clocks, unseeded randomness and environment variables from influencing placement (budgets count work; wall time only through the host's cancellation token) and lists the kit as read-only. Build-Engines.ps1 deploys only OpenNest.Engine.* folders, and New-Engine.ps1 -IncludeBuildFiles copies the kit. Co-Authored-By: Codex <noreply@openai.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4.3 KiB
OpenNest.Engine.NAME
An independent INestingEngine implementation. It must not be a wrapper, ensemble, or
selector over OpenNest's built-in engines. Solve() must not call, instantiate, or
delegate to any existing INestingEngine (StockLadderNestingEngine,
FixedStrategyNestingEngine), NestingEngineRegistry, NestJobRunner, or the whole-plate
nesters/fillers behind PlateNesterFactory (DefaultPlateNester, StripPlateNester,
RemnantPlateNester, PlateFillService, DefaultPlateFiller, ...). It must also never run
several of them and keep the best result.
The decisions that make it an engine must be yours: which sheet(s) to use, which parts go where and in what order, which pattern/strategy to apply to which region, and when to stop.
Read BENCH-RULES.md before starting. It covers your workspace, version control, the
real-part drawing archive, tests and your final report.
Allowed building blocks
Reuse is encouraged. These are tools you drive, composed by your own decision logic:
OpenNest.Engine.Jobs:JobPartGeometry, stockWorkArea/Area/Fits,RotationPolicy.EnumerateAngles,RotationCandidates,NestJobCost,NestTolerances,NestLayoutCheck, andNestJobResultBuilder. These prepare geometry, check and account for decisions made by your algorithm; they do not choose placements.OpenNest.Coregeometry:Polygon,Shape,BoundingBox,Vector,Box,ConvexHull,ConvexDecomposition,RotatingCalipers,Collision,NoFitPolygon,ShapeProfile,SpatialQuery.- Fill and pattern components in
OpenNest.Engine.Fill:FillLinear,FillExtents,PairFiller,ShrinkFiller,RemnantFiller/RemnantFinder,Compactor,FillScore,Pattern/PatternTiler,PartBoundary,RotationAnalysis,AngleCandidateBuilder,BestCombination. OpenNest.Engine.BestFit(BestFitFinder,PairEvaluator, ...),RectanglePacking,CirclePacking.
If you find a faster or better way to do something a shared component already does (for
example linear patterning), implement it inside this engine's own project and leave the
shared code untouched. Do not edit OpenNest.Core, OpenNest.Engine, or
OpenNest.Benchmark. Call it out in your report (what it replaces, why it is better,
measured numbers) so it can be generalized and upstreamed for every engine later.
What to fill in
__NAME__NestingEngine.cs— implementSolve(). Pick and document an actual placement strategy (NFP-based sliding placement, skyline/shelf packer, simulated-annealing/genetic layout search, guillotine-cut packer, physics/gravity-settling, etc). It's fine to be simpler or worse than the built-in engines to start; it must not be the same algorithm re-derived through indirection.- This README — replace this section with a description of the algorithm, its trade-offs, and benchmark results.
Tests
tests/ references the read-only ../Engine.Testing kit and subclasses
EngineContractTests<TEngine>. LayoutAssert.Valid uses NestLayoutCheck.Violations,
the benchmark's shared validation primitive, plus strict bounds and accounting checks.
The acceptance tests fail until Solve() is implemented. Keep them and add engine-specific
tests next to them. No clocks, unseeded randomness or environment variables may influence
placement; count work for budgets and honor the host cancellation token for wall time.
dotnet test OpenNest.Engine.__NAME__/tests/OpenNest.Engine.__NAME__.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:
dotnet build OpenNest.Engine.__NAME__/OpenNest.Engine.__NAME__.csproj -c Release
dotnet build <OpenNest>/OpenNest.Benchmark/OpenNest.Benchmark.csproj -c Release
mkdir -p <OpenNest>/OpenNest.Benchmark/bin/Release/net8.0/Engines
cp OpenNest.Engine.__NAME__/bin/Release/net8.0/OpenNest.Engine.__NAME__.dll <OpenNest>/OpenNest.Benchmark/bin/Release/net8.0/Engines/
dotnet <OpenNest>/OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll <path-to-.nest-or-folder> --parallel 1
<OpenNest> is the OpenNest checkout root. Your engine shows up in the report under its
CLR type name (__NAME__NestingEngine), competing on equal footing against the built-in
engines.