Merge branch 'refactor/engines-subfolder'
This commit is contained in:
@@ -47,6 +47,7 @@ Nesting algorithms use the jobs-only API. `INestingEngine.Solve(NestJob)` return
|
||||
- **Placement boundary (`Jobs/Placement/`, `Jobs/Adapters/`)**: `DefaultPlateNester`, `StripPlateNester`, and `RemnantPlateNester` are built-ins with run-scoped private geometry. `PlateFillService` is the public single-plate proposal service for interactive fill/group/pack flows; it returns parts without mutating caller-owned plates. Job-path identity is reference-based rather than drawing name; `PlateOptimizer` retains name-based helpers and remains outside the runner path.
|
||||
- **Filler pipeline (`Jobs/Placement/Fillers/`)**: internal `DefaultPlateFiller`, `StripPlateFiller`, and policy-backed `RemnantPlateFiller` implement the standard single-plate geometry pipeline. `Default` runs the Linear, Pairs, RectBestFit, and Extents phases; remnant variants preserve their distinct comparer, direction, trim-axis, and angle-ordering policies.
|
||||
- **Engine registration**: `NestingEngineRegistry` holds whole-job `INestingEngine` implementations including the four fixed strategies and `StockLadder`. It loads plug-ins that implement `INestingEngine` and have a public parameterless constructor. Plug-ins for the removed single-plate inheritance API are not binary compatible.
|
||||
- **In-repo plugin engines (`Engines/`)**: each lives in `Engines/OpenNest.Engine.<Name>/` with an optional `tests/` subproject, outside `OpenNest.sln`. `Engines/Directory.Build.props` supplies the TFM, nullable/implicit usings, and the `OpenNest.Engine` reference, so an engine csproj only adds what is unique to it; `Engines/Directory.Build.targets` excludes `tests/**` from the engine compile (it must be a `.targets` file to run after the SDK's default Compile glob). `./Engines/Build-Engines.ps1 [-Engines Name1,Name2]` builds the benchmark and engines and deploys the DLLs into `OpenNest.Benchmark/bin/<Config>/net8.0/Engines/`. Add new engines here, not at the repo root.
|
||||
- **IFillComparer**: Interface enabling filler-specific scoring. `DefaultFillComparer` (count-then-density), `VerticalRemnantComparer` (minimize X-extent), and `HorizontalRemnantComparer` (minimize Y-extent) are grouped into `FillPolicy` on `FillContext`.
|
||||
- **Fill/** (`namespace OpenNest.Engine.Fill`): Fill algorithms — `FillLinear` (grid-based), `FillExtents` (extents-based pair tiling), `PairFiller` (interlocking pairs), `ShrinkFiller`, `RemnantFiller`/`RemnantFinder`, `Compactor` (post-fill gravity compaction), `FillScore` (lexicographic comparison: count > utilization > compactness), `Pattern`/`PatternTiler`, `PartBoundary`, `RotationAnalysis`, `AngleCandidateBuilder`, `BestCombination`, `AccumulatingProgress`.
|
||||
- **Strategies/** (`namespace OpenNest.Engine.Strategies`): Pluggable fill strategy layer — `IFillStrategy` interface, `FillContext`, `FillStrategyRegistry` (auto-discovers strategies via reflection, supports plugin DLLs), `FillHelpers`. Built-in strategies: `LinearFillStrategy`, `PairsFillStrategy`, `RectBestFitStrategy`, `ExtentsFillStrategy`.
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Builds every plugin engine under Engines/ and deploys it to the benchmark.
|
||||
|
||||
.DESCRIPTION
|
||||
OpenNest.Benchmark loads plugin engines from an Engines/ folder next to its own
|
||||
build output. This builds the benchmark plus each Engines/OpenNest.Engine.*/ project
|
||||
(test subprojects are skipped) and copies each engine DLL into that folder.
|
||||
|
||||
.EXAMPLE
|
||||
./Engines/Build-Engines.ps1
|
||||
./Engines/Build-Engines.ps1 -Engines Opus55,Terra -Configuration Debug
|
||||
#>
|
||||
param(
|
||||
[string]$Configuration = 'Release',
|
||||
# Engine names without the OpenNest.Engine. prefix; default is all of them.
|
||||
[string[]]$Engines
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
$repoRoot = Split-Path $PSScriptRoot -Parent
|
||||
|
||||
dotnet build (Join-Path $repoRoot 'OpenNest.Benchmark/OpenNest.Benchmark.csproj') -c $Configuration
|
||||
if ($LASTEXITCODE -ne 0) { throw 'OpenNest.Benchmark build failed.' }
|
||||
|
||||
$deployDir = Join-Path $repoRoot "OpenNest.Benchmark/bin/$Configuration/net8.0/Engines"
|
||||
New-Item -ItemType Directory -Force $deployDir | Out-Null
|
||||
|
||||
$projects = Get-ChildItem $PSScriptRoot -Directory -Filter 'OpenNest.Engine.*' |
|
||||
Where-Object { -not $Engines -or $Engines -contains $_.Name.Substring('OpenNest.Engine.'.Length) }
|
||||
|
||||
foreach ($dir in $projects) {
|
||||
$csproj = Join-Path $dir.FullName "$($dir.Name).csproj"
|
||||
dotnet build $csproj -c $Configuration
|
||||
if ($LASTEXITCODE -ne 0) { throw "$($dir.Name) build failed." }
|
||||
|
||||
$dll = Join-Path $dir.FullName "bin/$Configuration/net8.0/$($dir.Name).dll"
|
||||
Copy-Item $dll $deployDir -Force
|
||||
Write-Host "Deployed $($dir.Name) -> $deployDir"
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<Project>
|
||||
<!--
|
||||
Shared settings for out-of-solution nesting engine plugins. Each engine lives in
|
||||
Engines/OpenNest.Engine.<Name>/ with an optional tests/ subproject; both import this.
|
||||
AssemblyName and RootNamespace default to the project file name.
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="$(MSBuildThisFileDirectory)../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project>
|
||||
<!--
|
||||
Each engine's tests/ subproject sits inside the engine folder. This must live in a
|
||||
.targets file: removals in Directory.Build.props run before the SDK adds its default
|
||||
Compile glob, so they would have no effect.
|
||||
-->
|
||||
<ItemGroup>
|
||||
<Compile Remove="tests/**/*.cs" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Shared settings and the OpenNest.Engine reference come from Engines/Directory.Build.props. -->
|
||||
<ItemGroup>
|
||||
<InternalsVisibleTo Include="OpenNest.Engine.Opus55.Tests" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -61,8 +61,8 @@ Every placement decision (which part, which rotation, where, on which sheet) com
|
||||
## Build / test
|
||||
|
||||
```bash
|
||||
dotnet build OpenNest.Engine.Opus55/OpenNest.Engine.Opus55.csproj -c Release
|
||||
dotnet test OpenNest.Engine.Opus55/tests/OpenNest.Engine.Opus55.Tests.csproj
|
||||
dotnet build Engines/OpenNest.Engine.Opus55/OpenNest.Engine.Opus55.csproj -c Release
|
||||
dotnet test Engines/OpenNest.Engine.Opus55/tests/OpenNest.Engine.Opus55.Tests.csproj
|
||||
```
|
||||
|
||||
This project is intentionally **outside** `OpenNest.sln`, the same pattern as the
|
||||
@@ -73,10 +73,12 @@ This project is intentionally **outside** `OpenNest.sln`, the same pattern as th
|
||||
```bash
|
||||
dotnet build OpenNest.Benchmark/OpenNest.Benchmark.csproj -c Release
|
||||
mkdir -p OpenNest.Benchmark/bin/Release/net8.0/Engines
|
||||
cp OpenNest.Engine.Opus55/bin/Release/net8.0/OpenNest.Engine.Opus55.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
cp Engines/OpenNest.Engine.Opus55/bin/Release/net8.0/OpenNest.Engine.Opus55.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
dotnet OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll <path-to-.nest-or-manifest-or-folder>
|
||||
```
|
||||
|
||||
Or build and deploy in one step with `./Engines/Build-Engines.ps1 -Engines Opus55`.
|
||||
|
||||
The engine reports as `Opus55NestingEngine`.
|
||||
|
||||
## Known limitations
|
||||
+1
-5
@@ -1,8 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
@@ -14,8 +11,7 @@
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="../OpenNest.Engine.Opus55.csproj" />
|
||||
<ProjectReference Include="../../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
<!-- The benchmark's NestValidator is the arbiter the engine is scored by. -->
|
||||
<ProjectReference Include="../../OpenNest.Benchmark/OpenNest.Benchmark.csproj" />
|
||||
<ProjectReference Include="../../../OpenNest.Benchmark/OpenNest.Benchmark.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Shared settings and the OpenNest.Engine reference come from Engines/Directory.Build.props. -->
|
||||
</Project>
|
||||
@@ -31,7 +31,7 @@ engines to start; it must not be the same algorithm re-derived through indirecti
|
||||
## Build
|
||||
|
||||
```bash
|
||||
dotnet build OpenNest.Engine.Qwen/OpenNest.Engine.Qwen.csproj
|
||||
dotnet build Engines/OpenNest.Engine.Qwen/OpenNest.Engine.Qwen.csproj
|
||||
```
|
||||
|
||||
This project is intentionally **outside** `OpenNest.sln` (same pattern as the
|
||||
@@ -44,14 +44,16 @@ as part of the main solution.
|
||||
own build output:
|
||||
|
||||
```bash
|
||||
dotnet build OpenNest.Engine.Qwen/OpenNest.Engine.Qwen.csproj -c Release
|
||||
dotnet build Engines/OpenNest.Engine.Qwen/OpenNest.Engine.Qwen.csproj -c Release
|
||||
dotnet build OpenNest.Benchmark/OpenNest.Benchmark.csproj -c Release
|
||||
|
||||
mkdir -p OpenNest.Benchmark/bin/Release/net8.0/Engines
|
||||
cp OpenNest.Engine.Qwen/bin/Release/net8.0/OpenNest.Engine.Qwen.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
cp Engines/OpenNest.Engine.Qwen/bin/Release/net8.0/OpenNest.Engine.Qwen.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
|
||||
dotnet OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll <path-to-.nest-or-folder>
|
||||
```
|
||||
|
||||
Or build and deploy in one step with `./Engines/Build-Engines.ps1 -Engines Qwen`.
|
||||
|
||||
Your engine will show up in the report under its CLR type name (`QwenNestingEngine`),
|
||||
competing on equal footing against the built-in engines.
|
||||
-4
@@ -1,8 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
@@ -14,6 +11,5 @@
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="../OpenNest.Engine.Qwen.csproj" />
|
||||
<ProjectReference Include="../../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -0,0 +1,3 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<!-- Shared settings and the OpenNest.Engine reference come from Engines/Directory.Build.props. -->
|
||||
</Project>
|
||||
@@ -31,7 +31,7 @@ engines to start; it must not be the same algorithm re-derived through indirecti
|
||||
## Build
|
||||
|
||||
```bash
|
||||
dotnet build OpenNest.Engine.Terra/OpenNest.Engine.Terra.csproj
|
||||
dotnet build Engines/OpenNest.Engine.Terra/OpenNest.Engine.Terra.csproj
|
||||
```
|
||||
|
||||
This project is intentionally **outside** `OpenNest.sln` (same pattern as the
|
||||
@@ -44,14 +44,16 @@ as part of the main solution.
|
||||
own build output:
|
||||
|
||||
```bash
|
||||
dotnet build OpenNest.Engine.Terra/OpenNest.Engine.Terra.csproj -c Release
|
||||
dotnet build Engines/OpenNest.Engine.Terra/OpenNest.Engine.Terra.csproj -c Release
|
||||
dotnet build OpenNest.Benchmark/OpenNest.Benchmark.csproj -c Release
|
||||
|
||||
mkdir -p OpenNest.Benchmark/bin/Release/net8.0/Engines
|
||||
cp OpenNest.Engine.Terra/bin/Release/net8.0/OpenNest.Engine.Terra.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
cp Engines/OpenNest.Engine.Terra/bin/Release/net8.0/OpenNest.Engine.Terra.dll OpenNest.Benchmark/bin/Release/net8.0/Engines/
|
||||
|
||||
dotnet OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll <path-to-.nest-or-folder>
|
||||
```
|
||||
|
||||
Or build and deploy in one step with `./Engines/Build-Engines.ps1 -Engines Terra`.
|
||||
|
||||
Your engine will show up in the report under its CLR type name (`TerraNestingEngine`),
|
||||
competing on equal footing against the built-in engines.
|
||||
-4
@@ -1,8 +1,5 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
</PropertyGroup>
|
||||
@@ -14,6 +11,5 @@
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
<ProjectReference Include="../OpenNest.Engine.Terra.csproj" />
|
||||
<ProjectReference Include="../../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,14 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>OpenNest.Engine.Opus55</RootNamespace>
|
||||
<AssemblyName>OpenNest.Engine.Opus55</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="tests/**/*.cs" />
|
||||
<InternalsVisibleTo Include="OpenNest.Engine.Opus55.Tests" />
|
||||
<ProjectReference Include="../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>OpenNest.Engine.Qwen</RootNamespace>
|
||||
<AssemblyName>OpenNest.Engine.Qwen</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="tests/**/*.cs" />
|
||||
<ProjectReference Include="../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<RootNamespace>OpenNest.Engine.Terra</RootNamespace>
|
||||
<AssemblyName>OpenNest.Engine.Terra</AssemblyName>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Remove="tests/**/*.cs" />
|
||||
<ProjectReference Include="../OpenNest.Engine/OpenNest.Engine.csproj" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -265,6 +265,8 @@ An engine's layout is rejected (it places nothing and pays the penalty on every
|
||||
|
||||
Custom competitor engines can be added by dropping a DLL that implements `INestingEngine` with a public parameterless constructor into the `Engines/` directory next to the benchmark executable; each one is registered under its own CLR type name. This jobs plug-in contract is also the supported extension point for new nesting engines. Plugins built for the removed single-plate inheritance API are not binary compatible and must be migrated to `INestingEngine`.
|
||||
|
||||
In-repo plugin engines live in the top-level `Engines/` source folder, one `Engines/OpenNest.Engine.<Name>/` project each with an optional `tests/` subproject. They are outside `OpenNest.sln` and share their build settings and `OpenNest.Engine` reference through `Engines/Directory.Build.props`. `./Engines/Build-Engines.ps1` builds the benchmark and every engine, then copies the engine DLLs into the benchmark's runtime `Engines/` folder; pass `-Engines Opus55,Terra` to build a subset.
|
||||
|
||||
### Conservative bend endpoint repair (opt-in)
|
||||
|
||||
Bend endpoint repair is disabled by default in the shared CAD importer.
|
||||
@@ -314,6 +316,7 @@ OpenNest.sln
|
||||
├── OpenNest.Core/ # Domain model, geometry, and CNC primitives
|
||||
├── OpenNest.Engine/ # Nesting algorithms and whole-job contracts
|
||||
├── OpenNest.Engine.Tests/ # Cross-platform whole-job contract tests (net8.0)
|
||||
├── Engines/ # Out-of-solution plugin engines (OpenNest.Engine.<Name>/)
|
||||
├── OpenNest.IO/ # File I/O — DXF import/export, nest file format
|
||||
├── OpenNest.IO.Tests/ # Cross-platform CAD import and bend repair tests (net8.0)
|
||||
├── OpenNest.Console/ # Command-line interface for batch nesting
|
||||
|
||||
Reference in New Issue
Block a user