feat(astra): add independent nesting engine and fix hole validation

Replace the Terra scaffold with an independent configuration-space contact placer and bounded stock-plan search. Include plugin tests, synthetic and DXF benchmark drivers, results, and deployment documentation.

Correct shared collision clipping and hole subtraction so curved-hole inserts validate consistently. Cover translated layouts, spacing violations, operand order, winding, and independent boolean-area comparisons.

Validation: 1,293 tests passed with 12 fixture skips; all 34 synthetic/generated and four DXF cases are valid and complete.
This commit is contained in:
aj
2026-09-24 00:14:36 -04:00
parent b6111a5486
commit fc9e46cad3
31 changed files with 1753 additions and 135 deletions
@@ -0,0 +1,89 @@
using OpenNest;
using OpenNest.CNC;
using OpenNest.Engine.Jobs;
using OpenNest.Geometry;
using OpenNest.Shapes;
using CncProgram = OpenNest.CNC.Program;
using M = System.Math;
namespace OpenNest.Engine.Astra.Benchmarks;
internal static class GeneratedCases
{
internal static IEnumerable<(string Name, NestJob Job)> Create()
{
var library = new ShapeDefinition[] {
new RoundedRectangleShape { Length = 11, Width = 5, Radius = 1.8 },
new TShape { Width = 10, Height = 9, StemWidth = 2, BarHeight = 2 },
new TrapezoidShape { BottomWidth = 10, TopWidth = 3, Height = 6 },
new NgonShape { Sides = 5, Width = 6 },
new NgonShape { Sides = 6, Width = 6 },
new RingShape { OuterDiameter = 10, InnerDiameter = 7 },
new PipeFlangeShape { OD = 7.5, HoleDiameter = 0.875, HolePatternDiameter = 5.5,
HoleCount = 8, PipeSize = "2", PipeClearance = 0.0625 }
};
for (var i = 0; i < library.Length; i++)
yield return ($"generated-library-{i}-{library[i].Name}", Job(new[] {
Part("main", library[i].GetDrawing().Program, i == 6 ? 12 : 24)
}, i));
yield return ("generated-ring-inserts", Job(new[] {
Part("ring", library[5].GetDrawing().Program, 8),
Part("insert", new CircleShape { Diameter = 6 }.GetDrawing().Program, 8)
}, 1));
var curvedC = new CncProgram();
curvedC.MoveTo(6, 0); curvedC.ArcTo(0, -6, 0, 0, RotationType.CCW);
curvedC.LineTo(0, -4); curvedC.ArcTo(4, 0, 0, 0, RotationType.CW); curvedC.LineTo(6, 0);
yield return ("generated-curved-C", Job(new[] { Part("C", curvedC, 16) }, 2));
yield return ("generated-narrow-U", Job(new[] { Part("U", Poly(0, 0, 10, 0, 10, 10,
8.5, 10, 8.5, 1.5, 1.5, 1.5, 1.5, 10, 0, 10), 24) }, 3));
yield return ("generated-stars", Job(new[] { Part("star", Star(7, 6, 2.5), 20) }, 0));
for (var seed = 0; seed < 12; seed++)
{
var random = new Random(19073 + seed);
var parts = new List<NestJobPart>();
for (var p = 0; p < 4; p++)
{
CncProgram program;
if (p == 0) program = new RoundedRectangleShape { Length = 5 + random.NextDouble() * 7,
Width = 3 + random.NextDouble() * 3, Radius = 0.7 }.GetDrawing().Program;
else if (p == 1) program = Star(5 + seed % 3, 3 + random.NextDouble() * 2, 1.5 + random.NextDouble());
else if (p == 2) program = new TrapezoidShape { BottomWidth = 5 + random.NextDouble() * 5,
TopWidth = 2 + random.NextDouble() * 2, Height = 3 + random.NextDouble() * 4 }.GetDrawing().Program;
else program = new NgonShape { Sides = 3 + seed % 5, Width = 3 + random.NextDouble() * 3 }.GetDrawing().Program;
// Nonzero source origins exercise pose reconstruction as well as shape packing.
program.Offset(new Vector(seed * 1.37 - 5, p * 2.13 - 3));
var rotation = p == 2 ? RotationPolicy.Fixed((seed % 4) * M.PI / 7) :
p == 3 ? RotationPolicy.BoundedSweep(-M.PI / 3, M.PI / 2, M.PI / 6, true) : RotationPolicy.Automatic;
parts.Add(Part($"p{p}", program, random.Next(3, 9), rotation));
}
yield return ($"generated-seed-{seed:00}", Job(parts.ToArray(), seed));
}
}
private static NestJob Job(NestJobPart[] parts, int seed) => new(parts, new[] {
new NestPlateStock("small", new Size(23 + seed % 3, 41 + seed % 5), 2,
seed % 4 == 0 ? 0 : 0.1 + seed % 3 * 0.075, new Spacing(0.2, 0.3, 0.4, 0.5), seed % 4 + 1),
new NestPlateStock("large", new Size(47, 83), partSpacing: 0.2,
edgeSpacing: new Spacing(0.3, 0.2, 0.5, 0.4), quadrant: seed % 4 + 1)
});
private static NestJobPart Part(string name, CncProgram p, int quantity, RotationPolicy rotation = null) =>
new(name, PartGeometrySnapshot.FromProgram(p), quantity, rotation: rotation);
private static CncProgram Star(int arms, double outer, double inner)
{
var coordinates = Enumerable.Range(0, arms * 2).SelectMany(i => {
var radius = i % 2 == 0 ? outer : inner;
var angle = i * M.PI / arms;
return new[] { radius * M.Cos(angle), radius * M.Sin(angle) };
}).ToArray();
return Poly(coordinates);
}
private static CncProgram Poly(params double[] points)
{
var p = new CncProgram(); p.MoveTo(points[0], points[1]);
for (var i = 2; i < points.Length; i += 2) p.LineTo(points[i], points[i + 1]);
p.LineTo(points[0], points[1]); return p;
}
}
@@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup><OutputType>Exe</OutputType><Nullable>disable</Nullable></PropertyGroup>
<ItemGroup>
<ProjectReference Include="../OpenNest.Engine.Astra.csproj" />
<Compile Include="../../../OpenNest.Benchmark/NestValidator.cs" Link="NestValidator.cs" />
</ItemGroup>
</Project>
@@ -0,0 +1,94 @@
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.Loader;
using OpenNest;
using OpenNest.CNC;
using OpenNest.Engine.Jobs;
using OpenNest.Engine.Jobs.Adapters;
using OpenNest.Geometry;
using OpenNest.Benchmark;
using CncProgram = OpenNest.CNC.Program;
CultureInfo.CurrentCulture = CultureInfo.InvariantCulture;
if (args.Contains("--diagnose-ring"))
{
var ringPart = new NestJobPart("ring", PartGeometrySnapshot.FromProgram(
new OpenNest.Shapes.RingShape { OuterDiameter = 10, InnerDiameter = 7 }.GetDrawing().Program), 1);
var insertPart = new NestJobPart("insert", PartGeometrySnapshot.FromProgram(
new OpenNest.Shapes.CircleShape { Diameter = 6 }.GetDrawing().Program), 1);
foreach (var quadrant in new[] { 1, 2 })
foreach (var offset in new[] { 0.0, 0.0003, 0.05, 0.1 })
{
var s = new NestPlateStock("s", new Size(24, 42), 1, 0.175,
new Spacing(0.2, 0.3, 0.4, 0.5), quadrant);
var j = new NestJob(new[] { ringPart, insertPart }, new[] { s });
var x = (quadrant == 1 ? 0 : -42) + s.EdgeSpacing.Left + 5;
var y = s.EdgeSpacing.Bottom + 5;
var result = new NestJobResult(NestJobStatus.Complete, NestJobStopReason.Completed,
new[] { new NestJobPlateResult(0, s, new[] { new NestJobPlacement("ring", 0, x, y, 0),
new NestJobPlacement("insert", 0, x + offset, y, 0) }) },
new[] { new PartFulfillment("ring", 1, 1, 0), new PartFulfillment("insert", 1, 1, 0) },
new[] { new StockUsage("s", 1, 0) });
var materialized = NestResultMaterializer.Materialize(j, result);
var check = NestValidator.Validate(materialized.Nest.Plates.Select(p => (p, p.Parts.ToList())).ToList(),
j.Parts.ToDictionary(p => materialized.DrawingsByPartId[p.Id], p => (p.Id, p.Quantity)));
Console.WriteLine($"q={quadrant} offset={offset} valid={check.Valid}: {string.Join(';', check.Violations)}");
}
return;
}
var assembly = args.Length > 0 && args[0].EndsWith(".dll")
? new AssemblyLoadContext("benchmark-plugin", isCollectible: true).LoadFromAssemblyPath(Path.GetFullPath(args[0])) : Assembly.Load("OpenNest.Engine.Astra");
var engine = (INestingEngine)Activator.CreateInstance(assembly.GetType("OpenNest.Engine.Astra.AstraNestingEngine")!);
var cases = new List<(string Name, NestJob Job)>();
var standard = new[] { new NestPlateStock("small", new Size(24, 48), partSpacing: 0.15),
new NestPlateStock("large", new Size(48, 96), partSpacing: 0.15) };
NestJobPart Part(string name, CncProgram p, int count, RotationPolicy rotation = null) =>
new(name, PartGeometrySnapshot.FromProgram(p), count, rotation: rotation);
CncProgram Polygon(params double[] xy)
{
var p = new CncProgram(); p.MoveTo(xy[0], xy[1]);
for (var i = 2; i < xy.Length; i += 2) p.LineTo(xy[i], xy[i + 1]);
p.LineTo(xy[0], xy[1]); return p;
}
CncProgram Rect(double w, double h) => Polygon(0, 0, w, 0, w, h, 0, h);
CncProgram Circle(double r) { var p = new CncProgram(); p.MoveTo(r, 0); p.ArcTo(r, 0, 0, 0, RotationType.CCW); return p; }
void Add(string name, NestJobPart[] parts, NestPlateStock[] stocks = null, NestJobOptions options = null) =>
cases.Add((name, new NestJob(parts, stocks ?? standard, options)));
Add("triangles", new[] { Part("triangle", Polygon(0, 0, 10, 0, 0, 10), 60) });
Add("circles", new[] { Part("circle", Circle(2.5), 90) });
Add("circles-dense", new[] { Part("circle", Circle(2.5), 80) });
Add("concave-L", new[] { Part("L", Polygon(0, 0, 8, 0, 8, 2, 2, 2, 2, 8, 0, 8), 60) });
Add("mixed", new[] { Part("rect", Rect(9, 4), 30), Part("triangle", Polygon(0, 0, 8, 0, 3, 6), 25),
Part("circle", Circle(2), 30), Part("L", Polygon(0, 0, 7, 0, 7, 2, 2, 2, 2, 6, 0, 6), 20) });
var ring = Rect(10, 10); ring.MoveTo(1, 1); ring.LineTo(1, 9); ring.LineTo(9, 9); ring.LineTo(9, 1); ring.LineTo(1, 1);
Add("holes", new[] { Part("frame", ring, 8), Part("insert", Rect(7, 7), 8) });
Add("rectangles", Enumerable.Range(0, 8).Select(i => Part($"r{i}", Rect(2 + i, 3 + i % 3), 12)).ToArray());
Add("grain", new[] { Part("fixed", Rect(13, 3), 20, RotationPolicy.Fixed(System.Math.PI / 6)),
Part("sweep", Rect(7, 2), 40, RotationPolicy.BoundedSweep(0, System.Math.PI / 2, System.Math.PI / 4)) });
Add("scarce-stock", new[] { Part("small", Rect(4, 4), 8), Part("large", Rect(10, 10), 1) },
new[] { new NestPlateStock("scarce", new Size(10, 10), 1), new NestPlateStock("small-only", new Size(4, 8)) });
Add("tail", new[] { Part("rect", Rect(6, 4), 17) }, new[] {
new NestPlateStock("small", new Size(8, 12), partSpacing: 0.1), new NestPlateStock("large", new Size(20, 30), partSpacing: 0.1) });
Add("plate-cap", new[] { Part("r", Rect(5, 5), 10) }, new[] {
new NestPlateStock("small", new Size(10, 10)), new NestPlateStock("large", new Size(20, 20)) }, new NestJobOptions(maxPlates: 1));
cases.AddRange(OpenNest.Engine.Astra.Benchmarks.GeneratedCases.Create());
Console.WriteLine("case,valid,placed,requested,sheets,area,milliseconds");
foreach (var (name, job) in cases)
{
if (args.Length > 1 && !name.Contains(args[1], StringComparison.OrdinalIgnoreCase)) continue;
var sw = Stopwatch.StartNew();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(90));
try
{
var result = engine.Solve(job, token: cts.Token); sw.Stop();
var nest = NestResultMaterializer.Materialize(job, result);
var validation = NestValidator.Validate(nest.Nest.Plates.Select(p => (p, p.Parts.ToList())).ToList(),
job.Parts.ToDictionary(p => nest.DrawingsByPartId[p.Id], p => (p.Id, p.Quantity)));
NestValidator.ValidateAgainstJob(job, result, job.Parts.ToDictionary(p => p.Id, p => p.Id), validation);
if (!validation.Valid) Environment.ExitCode = 1;
Console.WriteLine($"{name},{validation.Valid},{result.Fulfillment.Sum(f => f.Placed)},{job.Parts.Sum(p => p.Quantity)},{result.Plates.Count},{result.Plates.Sum(p => p.Stock.Size.Length * p.Stock.Size.Width)},{sw.ElapsedMilliseconds}");
foreach (var violation in validation.Violations.Take(4)) Console.Error.WriteLine($"{name}: {violation}");
}
catch (Exception ex) { Environment.ExitCode = 1; Console.WriteLine($"{name},ERROR,,,,,{sw.ElapsedMilliseconds}"); Console.Error.WriteLine(ex); }
}
+182
View File
@@ -0,0 +1,182 @@
# Astra development benchmark report
Measured locally on Linux with .NET SDK 8.0.425, Release builds, 2026-09-23.
The shared-validator fix was verified on 2026-09-24; its results are recorded separately below.
The baseline is Astra's original independent guillotine/bounding-rectangle implementation,
archived before the contact-search rewrite. These are not measurements against Opus or a
claim of performance on an unseen competition dataset.
## Synthetic cases
Both versions were run on exactly the same programmatically generated geometry and stock.
The driver validates materialized output with `OpenNest.Benchmark.NestValidator`, including
quantity, stock settings, rotation, material overlap and spacing. Timings cover `Solve` only,
exclude external validation, and are single-run observations rather than stable distributions.
Every contact result is valid and complete. The baseline is valid but incomplete on `plate-cap`.
| Case | Baseline area | Contact area | Change | Contact time (ms) |
|---|---:|---:|---:|---:|
| triangles | 8064 | 4608 | -42.9% | 3354 |
| circles | 3456 | 3456 | 0.0% | 1021 |
| circles-dense | 3456 | 2304 | -33.3% | 742 |
| concave-L | 5760 | 3456 | -40.0% | 1055 |
| mixed | 4608 | 3456 | -25.0% | 1990 |
| holes | 2304 | 1152 | -50.0% | 306 |
| rectangles | 3456 | 3456 | 0.0% | 261 |
| grain | 4608 | 2304 | -50.0% | 527 |
| scarce-stock | 228 | 228 | 0.0% | 1 |
| tail | 600 | 600 | 0.0% | 4 |
| plate-cap | 100 | 400 | 4/10 → 10/10 placed | 4 |
Excluding `plate-cap`, where baseline completion differs, purchased area fell from 36540
to 25020: **31.5% less area** across these ten cases. The original solver
usually took 0–30 ms; contact search takes approximately 1 ms to 3.4 s on this set. Packing
quality improved at a substantial CPU cost. No speedup over the original baseline is claimed.
## Extended generated cases
`GeneratedCases.cs` adds 23 jobs: rounded rectangles, T-shapes, trapezoids, pentagons,
hexagons, rings, pipe flanges, ring/insert mixtures, curved C-shapes, narrow U-shapes,
stars, and 12 seeded mixed jobs. These exercise all four quadrants, asymmetric edge margins,
finite small-sheet inventory, translated source origins, zero/positive spacing, fixed
non-cardinal rotations and bounded sweeps. The library supplies most shapes; the C, U and
star contours are generated directly. Seeded cases use seeds 19073 through 19084.
Both versions place every requested part in all 23 jobs with valid output. Seven cases use
less purchased area; the other sixteen match the baseline. Aggregate area drops from
58259 to 44353, **23.9% less area**. The changed cases are:
| Generated case | Baseline area | Contact area | Reduction |
|---|---:|---:|---:|
| T-shapes | 5917 | 2016 | 65.9% |
| Hexagons | 2160 | 1080 | 50.0% |
| Pipe flanges | 1932 | 966 | 50.0% |
| Curved C-shapes | 6051 | 2150 | 64.5% |
| Narrow U-shapes | 5925 | 3901 | 34.2% |
| Seed 19083 | 1968 | 984 | 50.0% |
| Seed 19084 | 2100 | 1050 | 50.0% |
The initial fine-mesh curved-C search exceeded the driver's 90-second cancellation budget
(an in-flight Minkowski operation delayed cancellation to 110 seconds). Separately coarsening
its contact outline, padding both approximation errors, and retaining fine safety geometry
reduced that case to approximately 2.3–2.5 seconds. No wall-clock cutoff was added to the engine.
The final regression pass validates all 34 generated/synthetic jobs and all four DXF jobs;
27 independent xUnit cases also pass. Raw results are in `results/`.
## Curved-hole validator fix (2026-09-24)
The generated ring/insert job exposed a shared-validator false positive. A ring with inner
radius 3.5 containing a concentric radius-3 disk has 0.5 units of clearance, yet the host's
triangulated collision check can report a violation with required spacing 0.175. The outcome
also changes with translations. Checking every candidate against that routine made a small
ring job take approximately 80–90 seconds.
Astra initially reserved curved cutouts as solid during placement, preserving the original
drawing in output. This workaround finished the ring/insert job in about 50 ms at the baseline
sheet cost. It has now been removed following a fix in `OpenNest.Core/Geometry/Collision.cs`.
Hole subtraction previously clipped each fragment independently against every triangle edge,
duplicating surviving area. It also classified points with an epsilon-shifted boundary but
intersected against the unshifted line, which could extrapolate outside the source segment.
The corrected routine emits disjoint outside fragments and carries the inside remainder to
the next edge. Classification and interpolation use the same signed cross products. Exact
closing vertices and local-coordinate area checks avoid additional small-fragment errors.
This remains the shared hand-written collision algorithm; Clipper is only an independent
oracle in the new tests, not a replacement per-pair validator.
The eight original translated reproductions all pass. Regression coverage also rejects real
spacing violations, checks both operand orders and windings, exercises all four quadrants,
and compares overlap areas against Clipper on 80 seeded pairs with multiple/concave holes.
The main suite passes 1,096 tests (12 font-fixture skips), Engine passes 170, and Astra passes
27. Astra's curved-hole tests now require a ring and insert to share stock whose usable area
fits only the ring, proving that insertion is enabled.
All 34 synthetic/generated jobs remain valid and complete with unchanged sheet-area costs.
The ring/insert job with hole search enabled takes about 4.8 seconds in this run and still
uses two small sheets. This fix improves validity and enables insertion; it does not improve
that job's stock plan. Results are in `results/validator-fixed-synthetic-generated.csv`.
All four repository-DXF jobs also remain valid and complete at unchanged sheet-area costs;
their rerun is recorded in `results/validator-fixed-dxf.csv`.
The isolated reproduction does not invoke any nesting engine:
```bash
dotnet run --project Engines/OpenNest.Engine.Astra/benchmarks -c Release -- --diagnose-ring
```
`results/ring-validator-reproducer.txt` retains the original failures;
`results/ring-validator-fixed.txt` records the corrected outcomes. Rebuild the host's Core
dependency when deploying. The benchmark validator's spacing rules and source are unchanged.
## Repository DXFs
The four manifests under `dxf/` use PT45, PT23 and PT11 repository drawings. Every result from
both versions was valid and complete. Runs used `--parallel 1`.
| Manifest | Baseline area | Contact area | Change |
|---|---:|---:|---:|
| locked.manifest | 115200 | 115200 | 0.0% |
| mixed.manifest | 144000 | 115200 | -20.0% |
| original.manifest | 115200 | 115200 | 0.0% |
| volume.manifest | 374400 | 374400 | 0.0% |
The mixed three-drawing job improves 20%; the other three retain baseline sheet-area cost.
The initial contact version regressed on `volume`; preserving a high-progress beam state and
ranking with observed per-part delivery cost removed that regression. Final results purchase
720000 area units versus 748800, a 3.8% reduction across the four manifests. Fewer physical
sheets sometimes have the same purchased area; those are not counted as area savings.
An exploratory run of the original manifest against StockLadder and Default found StockLadder
valid/complete at the same 115200 area cost; Default's result was flagged for spacing. That
single case does not establish general superiority. There is no Opus result available here.
## Local geometry optimizations
Apart from the shared Core collision fix described above, these optimizations are in Astra.
Astra caches NFPs and incrementally
subtracts each newly placed part from available translation regions, avoiding repeated unions
of all previous obstacles. A four-vertex rectangle configuration-space specialization avoids
round-offset polygons and polygon collision work for exact axis-aligned rectangle contacts.
During development, the 96-rectangle case dropped from roughly 1.5 s to 0.24 s after this
specialization. This is an end-to-end observation, not an isolated component microbenchmark.
Precision regression tests cover exact clearances and rotated zero-spacing contacts. In the
latter case, the host's four-decimal polygon rounding and triangulated collision test can
reject a contact accepted by Clipper at six decimals. Astra now retains the original rotated
frame for that validation, checks zero-clearance contacts with Core's collision primitive,
and tries tiny nearby translations when exact contact is unsafe.
## Reproduce
Run from the repository root:
```bash
dotnet run --project Engines/OpenNest.Engine.Astra/benchmarks -c Release
```
Run only the extended generated suite with `-- current generated`; the first positional
argument is either a previous plugin DLL or a label for the current build. Invalid layouts
and crashes make the driver exit with a nonzero status. Incompleteness is reported separately.
The standalone driver also accepts a prior plugin DLL and optional case-name filter:
```bash
dotnet run --project Engines/OpenNest.Engine.Astra/benchmarks -c Release -- /path/to/previous/OpenNest.Engine.Astra.dll triangles
```
An isolated assembly load context prevents .NET from silently substituting the currently
built plugin when comparing another version with the same assembly name. Historical baseline
CSV files are included; the old binary is not committed. The driver's 90-second cancellation
budget is a benchmark safeguard and is not an elapsed-time stopping rule inside the engine.
For real DXFs, build and deploy the plugin as described in the parent README, then:
```bash
dotnet OpenNest.Benchmark/bin/Release/net8.0/OpenNest.Benchmark.dll Engines/OpenNest.Engine.Astra/benchmarks/dxf --engines AstraNestingEngine --parallel 1 --csv /tmp/astra-dxf.csv
```
The CSV files under `results/` retain the measured results. Tests run independently:
```bash
dotnet test Engines/OpenNest.Engine.Astra/tests/OpenNest.Engine.Astra.Tests.csproj -c Release
```
@@ -0,0 +1,20 @@
{
"sheetSizes": [
"120x240",
"240x480"
],
"spacing": 0.25,
"edgeSpacing": 0.5,
"parts": [
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT45.dxf",
"quantity": 8,
"allowRotation": false
},
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT23.dxf",
"quantity": 4,
"allowRotation": false
}
]
}
@@ -0,0 +1,25 @@
{
"sheetSizes": [
"120x240",
"240x480"
],
"spacing": 0.25,
"edgeSpacing": 0.5,
"parts": [
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT45.dxf",
"quantity": 5,
"allowRotation": true
},
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT23.dxf",
"quantity": 4,
"allowRotation": true
},
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT11.dxf",
"quantity": 6,
"allowRotation": true
}
]
}
@@ -0,0 +1,20 @@
{
"sheetSizes": [
"120x240",
"240x480"
],
"spacing": 0.25,
"edgeSpacing": 0.5,
"parts": [
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT45.dxf",
"quantity": 8,
"allowRotation": true
},
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT23.dxf",
"quantity": 4,
"allowRotation": true
}
]
}
@@ -0,0 +1,20 @@
{
"sheetSizes": [
"120x240",
"240x480"
],
"spacing": 0.25,
"edgeSpacing": 0.5,
"parts": [
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT45.dxf",
"quantity": 32,
"allowRotation": true
},
{
"dxf": "../../../../OpenNest.Tests/Bending/TestData/4526 A14 PT23.dxf",
"quantity": 16,
"allowRotation": true
}
]
}
@@ -0,0 +1,5 @@
Job,Engine,Valid,Crashed,FullyPlaced,PartsPlaced,PartsRequested,Utilization,NetUtilization,PlateArea,NetSheetArea,Cost,PlatesUsed,SizeBreakdown,ElapsedMs,Notes
locked.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,1,240 x 480×1,83,
mixed.manifest,AstraNestingEngine,True,False,True,15,15,0.5983,0.5983,144000.00,144000.00,144000.00,5,120 x 240×5,298,
original.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,4,120 x 240×4,21,
volume.manifest,AstraNestingEngine,True,False,True,48,48,0.7977,0.7977,374400.00,374400.00,374400.00,4,240 x 480×3; 120 x 240×1,51,
1 Job Engine Valid Crashed FullyPlaced PartsPlaced PartsRequested Utilization NetUtilization PlateArea NetSheetArea Cost PlatesUsed SizeBreakdown ElapsedMs Notes
2 locked.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 1 240 x 480×1 83
3 mixed.manifest AstraNestingEngine True False True 15 15 0.5983 0.5983 144000.00 144000.00 144000.00 5 120 x 240×5 298
4 original.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 4 120 x 240×4 21
5 volume.manifest AstraNestingEngine True False True 48 48 0.7977 0.7977 374400.00 374400.00 374400.00 4 240 x 480×3; 120 x 240×1 51
@@ -0,0 +1,24 @@
case,valid,placed,requested,sheets,area,milliseconds
generated-library-0-RoundedRectangle,True,24,24,2,1886,24
generated-library-1-T,True,24,24,3,5917,0
generated-library-2-Trapezoid,True,24,24,2,2150,0
generated-library-3-Ngon,True,24,24,2,2024,0
generated-library-4-Ngon,True,24,24,2,2160,0
generated-library-5-Ring,True,24,24,1,3901,3
generated-library-6-PipeFlange,True,12,12,2,1932,19
generated-ring-inserts,True,16,16,2,2016,2
generated-curved-C,True,16,16,3,6051,0
generated-narrow-U,True,24,24,3,5925,0
generated-stars,True,20,20,1,3901,0
generated-seed-00,True,19,19,2,1886,1
generated-seed-01,True,22,22,2,2016,1
generated-seed-02,True,21,21,2,2150,1
generated-seed-03,True,20,20,1,1012,1
generated-seed-04,True,24,24,1,1080,1
generated-seed-05,True,22,22,2,2050,1
generated-seed-06,True,27,27,2,1932,1
generated-seed-07,True,19,19,1,1032,1
generated-seed-08,True,17,17,1,1100,1
generated-seed-09,True,22,22,2,2070,1
generated-seed-10,True,20,20,2,1968,1
generated-seed-11,True,19,19,2,2100,1
1 case valid placed requested sheets area milliseconds
2 generated-library-0-RoundedRectangle True 24 24 2 1886 24
3 generated-library-1-T True 24 24 3 5917 0
4 generated-library-2-Trapezoid True 24 24 2 2150 0
5 generated-library-3-Ngon True 24 24 2 2024 0
6 generated-library-4-Ngon True 24 24 2 2160 0
7 generated-library-5-Ring True 24 24 1 3901 3
8 generated-library-6-PipeFlange True 12 12 2 1932 19
9 generated-ring-inserts True 16 16 2 2016 2
10 generated-curved-C True 16 16 3 6051 0
11 generated-narrow-U True 24 24 3 5925 0
12 generated-stars True 20 20 1 3901 0
13 generated-seed-00 True 19 19 2 1886 1
14 generated-seed-01 True 22 22 2 2016 1
15 generated-seed-02 True 21 21 2 2150 1
16 generated-seed-03 True 20 20 1 1012 1
17 generated-seed-04 True 24 24 1 1080 1
18 generated-seed-05 True 22 22 2 2050 1
19 generated-seed-06 True 27 27 2 1932 1
20 generated-seed-07 True 19 19 1 1032 1
21 generated-seed-08 True 17 17 1 1100 1
22 generated-seed-09 True 22 22 2 2070 1
23 generated-seed-10 True 20 20 2 1968 1
24 generated-seed-11 True 19 19 2 2100 1
@@ -0,0 +1,12 @@
case,valid,placed,requested,sheets,area,milliseconds
triangles,True,60,60,4,8064,30
circles,True,90,90,3,3456,4
circles-dense,True,80,80,3,3456,0
concave-L,True,60,60,2,5760,0
mixed,True,105,105,4,4608,1
holes,True,16,16,2,2304,2
rectangles,True,96,96,3,3456,1
grain,True,60,60,4,4608,0
scarce-stock,True,9,9,5,228,0
tail,True,17,17,1,600,0
plate-cap,True,4,10,1,100,0
1 case valid placed requested sheets area milliseconds
2 triangles True 60 60 4 8064 30
3 circles True 90 90 3 3456 4
4 circles-dense True 80 80 3 3456 0
5 concave-L True 60 60 2 5760 0
6 mixed True 105 105 4 4608 1
7 holes True 16 16 2 2304 2
8 rectangles True 96 96 3 3456 1
9 grain True 60 60 4 4608 0
10 scarce-stock True 9 9 5 228 0
11 tail True 17 17 1 600 0
12 plate-cap True 4 10 1 100 0
@@ -0,0 +1,5 @@
Job,Engine,Valid,Crashed,FullyPlaced,PartsPlaced,PartsRequested,Utilization,NetUtilization,PlateArea,NetSheetArea,Cost,PlatesUsed,SizeBreakdown,ElapsedMs,Notes
locked.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,1,240 x 480×1,259,
mixed.manifest,AstraNestingEngine,True,False,True,15,15,0.7479,0.7479,115200.00,115200.00,115200.00,1,240 x 480×1,1724,
original.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,1,240 x 480×1,133,
volume.manifest,AstraNestingEngine,True,False,True,48,48,0.7977,0.7977,374400.00,374400.00,374400.00,4,240 x 480×3; 120 x 240×1,389,
1 Job Engine Valid Crashed FullyPlaced PartsPlaced PartsRequested Utilization NetUtilization PlateArea NetSheetArea Cost PlatesUsed SizeBreakdown ElapsedMs Notes
2 locked.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 1 240 x 480×1 259
3 mixed.manifest AstraNestingEngine True False True 15 15 0.7479 0.7479 115200.00 115200.00 115200.00 1 240 x 480×1 1724
4 original.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 1 240 x 480×1 133
5 volume.manifest AstraNestingEngine True False True 48 48 0.7977 0.7977 374400.00 374400.00 374400.00 4 240 x 480×3; 120 x 240×1 389
@@ -0,0 +1,24 @@
case,valid,placed,requested,sheets,area,milliseconds
generated-library-0-RoundedRectangle,True,24,24,2,1886,175
generated-library-1-T,True,24,24,2,2016,175
generated-library-2-Trapezoid,True,24,24,2,2150,120
generated-library-3-Ngon,True,24,24,2,2024,536
generated-library-4-Ngon,True,24,24,1,1080,93
generated-library-5-Ring,True,24,24,1,3901,85
generated-library-6-PipeFlange,True,12,12,1,966,46
generated-ring-inserts,True,16,16,2,2016,48
generated-curved-C,True,16,16,2,2150,1929
generated-narrow-U,True,24,24,1,3901,136
generated-stars,True,20,20,1,3901,3118
generated-seed-00,True,19,19,2,1886,578
generated-seed-01,True,22,22,2,2016,403
generated-seed-02,True,21,21,2,2150,1447
generated-seed-03,True,20,20,1,1012,356
generated-seed-04,True,24,24,1,1080,600
generated-seed-05,True,22,22,2,2050,1467
generated-seed-06,True,27,27,2,1932,1251
generated-seed-07,True,19,19,1,1032,724
generated-seed-08,True,17,17,1,1100,980
generated-seed-09,True,22,22,2,2070,930
generated-seed-10,True,20,20,1,984,460
generated-seed-11,True,19,19,1,1050,1151
1 case valid placed requested sheets area milliseconds
2 generated-library-0-RoundedRectangle True 24 24 2 1886 175
3 generated-library-1-T True 24 24 2 2016 175
4 generated-library-2-Trapezoid True 24 24 2 2150 120
5 generated-library-3-Ngon True 24 24 2 2024 536
6 generated-library-4-Ngon True 24 24 1 1080 93
7 generated-library-5-Ring True 24 24 1 3901 85
8 generated-library-6-PipeFlange True 12 12 1 966 46
9 generated-ring-inserts True 16 16 2 2016 48
10 generated-curved-C True 16 16 2 2150 1929
11 generated-narrow-U True 24 24 1 3901 136
12 generated-stars True 20 20 1 3901 3118
13 generated-seed-00 True 19 19 2 1886 578
14 generated-seed-01 True 22 22 2 2016 403
15 generated-seed-02 True 21 21 2 2150 1447
16 generated-seed-03 True 20 20 1 1012 356
17 generated-seed-04 True 24 24 1 1080 600
18 generated-seed-05 True 22 22 2 2050 1467
19 generated-seed-06 True 27 27 2 1932 1251
20 generated-seed-07 True 19 19 1 1032 724
21 generated-seed-08 True 17 17 1 1100 980
22 generated-seed-09 True 22 22 2 2070 930
23 generated-seed-10 True 20 20 1 984 460
24 generated-seed-11 True 19 19 1 1050 1151
@@ -0,0 +1,12 @@
case,valid,placed,requested,sheets,area,milliseconds
triangles,True,60,60,1,4608,3354
circles,True,90,90,3,3456,1021
circles-dense,True,80,80,2,2304,742
concave-L,True,60,60,3,3456,1055
mixed,True,105,105,3,3456,1990
holes,True,16,16,1,1152,306
rectangles,True,96,96,3,3456,261
grain,True,60,60,2,2304,527
scarce-stock,True,9,9,5,228,1
tail,True,17,17,1,600,4
plate-cap,True,10,10,1,400,4
1 case valid placed requested sheets area milliseconds
2 triangles True 60 60 1 4608 3354
3 circles True 90 90 3 3456 1021
4 circles-dense True 80 80 2 2304 742
5 concave-L True 60 60 3 3456 1055
6 mixed True 105 105 3 3456 1990
7 holes True 16 16 1 1152 306
8 rectangles True 96 96 3 3456 261
9 grain True 60 60 2 2304 527
10 scarce-stock True 9 9 5 228 1
11 tail True 17 17 1 600 4
12 plate-cap True 10 10 1 400 4
@@ -0,0 +1,8 @@
q=1 offset=0 valid=True:
q=1 offset=0.0003 valid=True:
q=1 offset=0.05 valid=True:
q=1 offset=0.1 valid=True:
q=2 offset=0 valid=True:
q=2 offset=0.0003 valid=True:
q=2 offset=0.05 valid=True:
q=2 offset=0.1 valid=True:
@@ -0,0 +1,8 @@
q=1 offset=0 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
q=1 offset=0.0003 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
q=1 offset=0.05 valid=True:
q=1 offset=0.1 valid=True:
q=2 offset=0 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
q=2 offset=0.0003 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
q=2 offset=0.05 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
q=2 offset=0.1 valid=False: 'ring' and 'insert' are closer than the required spacing (0.175)
@@ -0,0 +1,5 @@
Job,Engine,Valid,Crashed,FullyPlaced,PartsPlaced,PartsRequested,Utilization,NetUtilization,PlateArea,NetSheetArea,Cost,PlatesUsed,SizeBreakdown,ElapsedMs,Notes
locked.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,1,240 x 480×1,466,
mixed.manifest,AstraNestingEngine,True,False,True,15,15,0.7479,0.7479,115200.00,115200.00,115200.00,1,240 x 480×1,2820,
original.manifest,AstraNestingEngine,True,False,True,12,12,0.6481,0.6481,115200.00,115200.00,115200.00,1,240 x 480×1,435,
volume.manifest,AstraNestingEngine,True,False,True,48,48,0.7977,0.7977,374400.00,374400.00,374400.00,4,240 x 480×3; 120 x 240×1,2278,
1 Job Engine Valid Crashed FullyPlaced PartsPlaced PartsRequested Utilization NetUtilization PlateArea NetSheetArea Cost PlatesUsed SizeBreakdown ElapsedMs Notes
2 locked.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 1 240 x 480×1 466
3 mixed.manifest AstraNestingEngine True False True 15 15 0.7479 0.7479 115200.00 115200.00 115200.00 1 240 x 480×1 2820
4 original.manifest AstraNestingEngine True False True 12 12 0.6481 0.6481 115200.00 115200.00 115200.00 1 240 x 480×1 435
5 volume.manifest AstraNestingEngine True False True 48 48 0.7977 0.7977 374400.00 374400.00 374400.00 4 240 x 480×3; 120 x 240×1 2278
@@ -0,0 +1,35 @@
case,valid,placed,requested,sheets,area,milliseconds
triangles,True,60,60,1,4608,3344
circles,True,90,90,3,3456,1008
circles-dense,True,80,80,2,2304,748
concave-L,True,60,60,3,3456,1082
mixed,True,105,105,3,3456,1966
holes,True,16,16,1,1152,293
rectangles,True,96,96,3,3456,246
grain,True,60,60,2,2304,513
scarce-stock,True,9,9,5,228,1
tail,True,17,17,1,600,4
plate-cap,True,10,10,1,400,4
generated-library-0-RoundedRectangle,True,24,24,2,1886,170
generated-library-1-T,True,24,24,2,2016,172
generated-library-2-Trapezoid,True,24,24,2,2150,115
generated-library-3-Ngon,True,24,24,2,2024,510
generated-library-4-Ngon,True,24,24,1,1080,89
generated-library-5-Ring,True,24,24,1,3901,918
generated-library-6-PipeFlange,True,12,12,1,966,1467
generated-ring-inserts,True,16,16,2,2016,4755
generated-curved-C,True,16,16,2,2150,1883
generated-narrow-U,True,24,24,1,3901,134
generated-stars,True,20,20,1,3901,3087
generated-seed-00,True,19,19,2,1886,568
generated-seed-01,True,22,22,2,2016,398
generated-seed-02,True,21,21,2,2150,1427
generated-seed-03,True,20,20,1,1012,352
generated-seed-04,True,24,24,1,1080,600
generated-seed-05,True,22,22,2,2050,1447
generated-seed-06,True,27,27,2,1932,1254
generated-seed-07,True,19,19,1,1032,705
generated-seed-08,True,17,17,1,1100,1008
generated-seed-09,True,22,22,2,2070,1025
generated-seed-10,True,20,20,1,984,504
generated-seed-11,True,19,19,1,1050,1353
1 case valid placed requested sheets area milliseconds
2 triangles True 60 60 1 4608 3344
3 circles True 90 90 3 3456 1008
4 circles-dense True 80 80 2 2304 748
5 concave-L True 60 60 3 3456 1082
6 mixed True 105 105 3 3456 1966
7 holes True 16 16 1 1152 293
8 rectangles True 96 96 3 3456 246
9 grain True 60 60 2 2304 513
10 scarce-stock True 9 9 5 228 1
11 tail True 17 17 1 600 4
12 plate-cap True 10 10 1 400 4
13 generated-library-0-RoundedRectangle True 24 24 2 1886 170
14 generated-library-1-T True 24 24 2 2016 172
15 generated-library-2-Trapezoid True 24 24 2 2150 115
16 generated-library-3-Ngon True 24 24 2 2024 510
17 generated-library-4-Ngon True 24 24 1 1080 89
18 generated-library-5-Ring True 24 24 1 3901 918
19 generated-library-6-PipeFlange True 12 12 1 966 1467
20 generated-ring-inserts True 16 16 2 2016 4755
21 generated-curved-C True 16 16 2 2150 1883
22 generated-narrow-U True 24 24 1 3901 134
23 generated-stars True 20 20 1 3901 3087
24 generated-seed-00 True 19 19 2 1886 568
25 generated-seed-01 True 22 22 2 2016 398
26 generated-seed-02 True 21 21 2 2150 1427
27 generated-seed-03 True 20 20 1 1012 352
28 generated-seed-04 True 24 24 1 1080 600
29 generated-seed-05 True 22 22 2 2050 1447
30 generated-seed-06 True 27 27 2 1932 1254
31 generated-seed-07 True 19 19 1 1032 705
32 generated-seed-08 True 17 17 1 1100 1008
33 generated-seed-09 True 22 22 2 2070 1025
34 generated-seed-10 True 20 20 1 984 504
35 generated-seed-11 True 19 19 1 1050 1353