From 0a1d021bf7df752688254dccad2d208457c3a3be Mon Sep 17 00:00:00 2001 From: AJ Isaacs Date: Tue, 6 Oct 2026 12:11:03 -0400 Subject: [PATCH] refactor(engine): rename the Default engine and fill strategy to Fill The multi-phase lattice fill (linear, pairs, rectangle best-fit, remainder) is no longer meant to be the engine used by default, so it gets a name for what it does. The registry lists it as Fill and maps the old name Default to it; PlateFillService, PlateNesterFactory and NestJobOptions use Fill, and every fill-strategy caller still accepts Default. Console --autonest now validates engine names through NestingEngineRegistry.ResolveName so renamed names work. Layouts are unchanged: Default and Fill resolve to the same fillers and the golden layouts pass under the new name. --- OpenNest.Benchmark/BenchmarkJob.cs | 2 +- OpenNest.Console/Program.cs | 10 +-- .../FillStrategyNameTests.cs | 81 +++++++++++++++++++ .../Jobs/Cutouts/CutoutLatticeFillTests.cs | 2 +- .../Jobs/FixedStrategyNestingEngineTests.cs | 4 +- .../Jobs/GoldenLayoutTests.cs | 8 +- .../Jobs/NestJobEngineSelectionTests.cs | 2 +- .../Jobs/NestJobExampleTests.cs | 4 +- .../Jobs/NestJobGeometryTests.cs | 2 +- .../Jobs/NestJobRunnerTests.cs | 2 +- .../Jobs/NestPipelineTests.cs | 6 +- .../Jobs/NestingEngineRegistryTests.cs | 10 +-- .../Jobs/PlateFillerContractTests.cs | 4 +- .../Jobs/PlateNesterParityTests.cs | 6 +- .../PlateFillServiceTests.cs | 8 +- .../RectanglePacking/AreaPackerTests.cs | 14 ++-- .../Jobs/Cutouts/CutoutLatticeFill.cs | 2 +- OpenNest.Engine/Jobs/NestJobOptions.cs | 2 +- OpenNest.Engine/Jobs/NestingEngineRegistry.cs | 5 +- .../Jobs/Placement/PlateFillService.cs | 23 ++++-- .../Jobs/Placement/PrivatePlateFill.cs | 2 +- .../Jobs/Placement/RemnantPlateNester.cs | 6 +- OpenNest.Engine/Jobs/PlateNesterFactory.cs | 3 +- OpenNest.Mcp/Tools/NestingTools.cs | 8 +- .../NestLayoutCheckEquivalenceTests.cs | 2 +- .../BestFit/NativeUClearanceTests.cs | 2 +- OpenNest.Tests/Engine/EngineOverlapTests.cs | 2 +- .../Engine/ExplicitPlacementStrategyTests.cs | 4 +- .../ActionSelectAreaCutOffTests.cs | 2 +- OpenNest/Forms/EngineSelection.cs | 6 +- README.md | 4 +- docs/geometry/pair-spacing.md | 2 +- docs/nesting-engines.md | 18 +++-- docs/performance/fill-verification.md | 2 +- scripts/ReleaseSmoke/Program.cs | 2 +- 35 files changed, 178 insertions(+), 84 deletions(-) create mode 100644 OpenNest.Engine.Tests/FillStrategyNameTests.cs diff --git a/OpenNest.Benchmark/BenchmarkJob.cs b/OpenNest.Benchmark/BenchmarkJob.cs index 063f827..158a20f 100644 --- a/OpenNest.Benchmark/BenchmarkJob.cs +++ b/OpenNest.Benchmark/BenchmarkJob.cs @@ -83,7 +83,7 @@ namespace OpenNest.Benchmark parts, stock, new NestJobOptions( - "Default", + "Fill", maxPlates, salvageRate ?? SalvageRate, minimumSalvageDimension ?? 0 diff --git a/OpenNest.Console/Program.cs b/OpenNest.Console/Program.cs index 94643c7..adc8923 100644 --- a/OpenNest.Console/Program.cs +++ b/OpenNest.Console/Program.cs @@ -79,10 +79,8 @@ static class NestConsole // single-plate placement strategy. Unknown names exit with the valid choices. if (options.AutoNest) { - var isJobsEngine = NestingEngineRegistry.AvailableEngines.Any(e => - e.Name.Equals(options.Engine, StringComparison.OrdinalIgnoreCase) - ); - if (!isJobsEngine) + // ResolveName also accepts renamed engines' old names (for example Default). + if (NestingEngineRegistry.ResolveName(options.Engine) == null) { Console.Error.WriteLine( $"Error: unknown engine '{options.Engine}'. Jobs engines: {string.Join(", ", NestingEngineRegistry.AvailableEngines.Select(e => e.Name))}" @@ -764,8 +762,8 @@ static class NestConsole --template Nest template for plate defaults (thickness, quadrant, material, spacing) --autonest Validated whole-job nesting onto one sheet; replaces only after acceptance --allow-invalid Explicitly keep representable invalid autonest layouts (default: reject, exit 2) - --engine With --autonest: jobs engine (default: Default; also StockLadder, Strip, ...). - Without --autonest: fill strategy (Default, Strip, Vertical Remnant, Horizontal Remnant) + --engine With --autonest: jobs engine (default: Default; also Irregular, Rectangles, Fill, ...). + Without --autonest: fill strategy (Fill (default), Strip, Vertical Remnant, Horizontal Remnant) --keep-parts Don't clear existing parts before filling --check-overlaps Run overlap detection after fill (exit code 1 if found) --no-save Skip saving output file diff --git a/OpenNest.Engine.Tests/FillStrategyNameTests.cs b/OpenNest.Engine.Tests/FillStrategyNameTests.cs new file mode 100644 index 0000000..d74ad07 --- /dev/null +++ b/OpenNest.Engine.Tests/FillStrategyNameTests.cs @@ -0,0 +1,81 @@ +using OpenNest.Engine.Jobs; +using OpenNest.Engine.Jobs.Placement; +using OpenNest.Engine.Tests.Jobs; +using OpenNest.Geometry; + +namespace OpenNest.Engine.Tests; + +/// +/// The fill engine and placement strategy are named "Fill"; the old name "Default" remains a +/// hidden alias so saved selections, scripts and API requests keep their behavior. +/// +public class FillStrategyNameTests +{ + [Fact] + public void FillIsListedAndDefaultIsNot() + { + var engines = NestingEngineRegistry.AvailableEngines.Select(e => e.Name).ToList(); + + Assert.Contains("Fill", engines); + Assert.DoesNotContain("Default", engines, StringComparer.OrdinalIgnoreCase); + Assert.Equal(new[] { "Fill", "Strip", "Vertical Remnant", "Horizontal Remnant" }, + PlateFillService.BuiltInStrategies); + } + + [Theory] + [InlineData("Default")] + [InlineData(" default ")] + public void LegacyDefaultEngineNameResolvesToFill(string name) + { + Assert.Equal("Fill", NestingEngineRegistry.ResolveName(name)); + Assert.IsType(NestingEngineRegistry.Create(name)); + Assert.Equal(NestJobStatus.Complete, NestingEngineRegistry.Create(name).Solve(FiniteStockJobTests.Job(1)).Status); + } + + [Fact] + public void PlugInNamedDefaultCannotShadowFill() + { + var before = NestingEngineRegistry.AvailableEngines.Count; + + NestingEngineRegistry.Register("Default", "stale plug-in", () => new FixedStrategyNestingEngine("Strip")); + + Assert.Equal(before, NestingEngineRegistry.AvailableEngines.Count); + Assert.Equal("Fill", NestingEngineRegistry.ResolveName("Default")); + } + + [Theory] + [InlineData(null, "Fill")] + [InlineData("", "Fill")] + [InlineData("fill", "Fill")] + [InlineData("Default", "Fill")] + [InlineData("DEFAULT", "Fill")] + public void PlacementStrategyResolvesFillAndItsLegacyName(string? strategy, string expected) + { + Assert.Equal(expected, PlateFillService.ResolveStrategy(strategy!)); + } + + [Fact] + public void LegacyStrategyNameStillFillsAPlate() + { + var plate = new Plate(new Size(60, 80)); + var drawing = new Drawing("part", TestDrawingFactory.Rectangle(6, 4)); + + var parts = PlateFillService.FillItem("Default", plate, + new NestItem { Drawing = drawing, Quantity = 6 }, plate.WorkArea(), null, CancellationToken.None); + + Assert.Equal(6, parts.Count); + } + + [Fact] + public void WholeJobRunnerAcceptsFillAndItsLegacyName() + { + Assert.IsType(PlateNesterFactory.Create("Fill")); + Assert.IsType(PlateNesterFactory.Create("Default")); + Assert.Equal("Fill", new NestJobOptions().PlacementStrategy); + + var job = FiniteStockJobTests.Job(1); + var legacy = new NestJobRunner(PlateNesterFactory.Create) + .Solve(new NestJob(job.Parts, job.Plates, new NestJobOptions("Default"))); + Assert.Equal(NestJobStatus.Complete, legacy.Status); + } +} diff --git a/OpenNest.Engine.Tests/Jobs/Cutouts/CutoutLatticeFillTests.cs b/OpenNest.Engine.Tests/Jobs/Cutouts/CutoutLatticeFillTests.cs index ab9f616..36b5655 100644 --- a/OpenNest.Engine.Tests/Jobs/Cutouts/CutoutLatticeFillTests.cs +++ b/OpenNest.Engine.Tests/Jobs/Cutouts/CutoutLatticeFillTests.cs @@ -54,7 +54,7 @@ public class CutoutLatticeFillTests } // Both cases fail intermittently; unskip when Project Memory opennest issue c98c21bd is fixed. - private const string FillNondeterminism = "Open defect (Project Memory opennest c98c21bd): Default Fill can " + private const string FillNondeterminism = "Open defect (Project Memory opennest c98c21bd): Fill can " + "return different, equally scored lattices between identical calls."; [Theory] diff --git a/OpenNest.Engine.Tests/Jobs/FixedStrategyNestingEngineTests.cs b/OpenNest.Engine.Tests/Jobs/FixedStrategyNestingEngineTests.cs index b16e811..831f6de 100644 --- a/OpenNest.Engine.Tests/Jobs/FixedStrategyNestingEngineTests.cs +++ b/OpenNest.Engine.Tests/Jobs/FixedStrategyNestingEngineTests.cs @@ -22,7 +22,7 @@ public class FixedStrategyNestingEngineTests [Fact] public void PreservesJobMaxPlates() { - var engine = new FixedStrategyNestingEngine("Default"); + var engine = new FixedStrategyNestingEngine("Fill"); var part = new NestJobPart( "part", PartGeometrySnapshot.FromProgram(TestDrawingFactory.Rectangle(100, 100)), @@ -39,7 +39,7 @@ public class FixedStrategyNestingEngineTests var job = new NestJob( new[] { part }, new[] { stock }, - new NestJobOptions("Default", maxPlates: 1) + new NestJobOptions("Fill", maxPlates: 1) ); var result = engine.Solve(job); diff --git a/OpenNest.Engine.Tests/Jobs/GoldenLayoutTests.cs b/OpenNest.Engine.Tests/Jobs/GoldenLayoutTests.cs index a47d39a..9a49c1a 100644 --- a/OpenNest.Engine.Tests/Jobs/GoldenLayoutTests.cs +++ b/OpenNest.Engine.Tests/Jobs/GoldenLayoutTests.cs @@ -165,7 +165,7 @@ public class GoldenLayoutTests [Fact] public void Default_MixedJob_GoldenLayout() { - var result = SolveStable(new NestJobRunner(PlateNesterFactory.Create), MixedJob("Default")); + var result = SolveStable(new NestJobRunner(PlateNesterFactory.Create), MixedJob("Fill")); Assert.Equal(NestJobStatus.Complete, result.Status); Assert.Equal(20, result.Plates.Sum(p => p.Placements.Count)); AssertGolden( @@ -299,7 +299,7 @@ public class GoldenLayoutTests [Fact] public void OrderedViaStockLadder_MixedJob_GoldenLayout() { - var result = SolveStable(new StockLadderNestingEngine(), MixedJob("Default")); + var result = SolveStable(new StockLadderNestingEngine(), MixedJob("Fill")); Assert.Equal(NestJobStatus.Complete, result.Status); AssertGolden( result, @@ -338,7 +338,7 @@ public class GoldenLayoutTests new NestPlateStock("small", new Size(14, 14), 4, 1, new Spacing(1, 1, 1, 1)), new NestPlateStock("large", new Size(30, 24), 3, 1, new Spacing(1, 1, 1, 1)), }, - new NestJobOptions("Default") + new NestJobOptions("Fill") ); private sealed record AuthoritativeStage( @@ -408,7 +408,7 @@ public class GoldenLayoutTests { var stages = new List(); var legacyPhases = new SortedSet(); - var result = new FixedStrategyNestingEngine("Default").Solve( + var result = new FixedStrategyNestingEngine("Fill").Solve( ProgressJob(), new StageCollector(stages, legacyPhases) ); diff --git a/OpenNest.Engine.Tests/Jobs/NestJobEngineSelectionTests.cs b/OpenNest.Engine.Tests/Jobs/NestJobEngineSelectionTests.cs index f86fe40..64e9fac 100644 --- a/OpenNest.Engine.Tests/Jobs/NestJobEngineSelectionTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestJobEngineSelectionTests.cs @@ -27,7 +27,7 @@ public class NestJobEngineSelectionTests [Fact] public void FactoryResolvesEachNamedBuiltInStrategy() { - var defaultNester = PlateNesterFactory.Create("Default"); + var defaultNester = PlateNesterFactory.Create("Fill"); var stripNester = PlateNesterFactory.Create("Strip"); var verticalNester = PlateNesterFactory.Create("Vertical Remnant"); var horizontalNester = PlateNesterFactory.Create("Horizontal Remnant"); diff --git a/OpenNest.Engine.Tests/Jobs/NestJobExampleTests.cs b/OpenNest.Engine.Tests/Jobs/NestJobExampleTests.cs index 8af8d70..2698b10 100644 --- a/OpenNest.Engine.Tests/Jobs/NestJobExampleTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestJobExampleTests.cs @@ -145,7 +145,7 @@ public class NestJobExampleTests quadrant: 1 ), }, - new NestJobOptions("Default", maxPlates: 1) + new NestJobOptions("Fill", maxPlates: 1) ); var result = new NestJobRunner(PlateNesterFactory.Create).Solve(job); @@ -172,7 +172,7 @@ public class NestJobExampleTests var item = new NestItem { Drawing = drawing, Quantity = 1 }; var parts = PlateFillService.Nest( - "Default", + "Fill", plate, new List { item }, progress: null, diff --git a/OpenNest.Engine.Tests/Jobs/NestJobGeometryTests.cs b/OpenNest.Engine.Tests/Jobs/NestJobGeometryTests.cs index 73e2f63..d6ae070 100644 --- a/OpenNest.Engine.Tests/Jobs/NestJobGeometryTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestJobGeometryTests.cs @@ -260,7 +260,7 @@ public class NestJobGeometryTests } [Theory] - [InlineData("Default")] + [InlineData("Fill")] [InlineData("Strip")] public void RealEngineSmokeCasesPreserveInputAndProduceSafeAccounting(string strategy) { diff --git a/OpenNest.Engine.Tests/Jobs/NestJobRunnerTests.cs b/OpenNest.Engine.Tests/Jobs/NestJobRunnerTests.cs index 1ce7409..0721b7b 100644 --- a/OpenNest.Engine.Tests/Jobs/NestJobRunnerTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestJobRunnerTests.cs @@ -105,7 +105,7 @@ public class NestJobRunnerTests Assert.Equal(100, job.Plates[0].Size.Width); Assert.Equal(1, job.Plates[0].EdgeSpacing.Left); Assert.Equal(0, job.Plates[0].Quantity); - Assert.Equal("Default", job.Options.PlacementStrategy); + Assert.Equal("Fill", job.Options.PlacementStrategy); Assert.Throws(() => ((IList)job.Parts).Clear()); } diff --git a/OpenNest.Engine.Tests/Jobs/NestPipelineTests.cs b/OpenNest.Engine.Tests/Jobs/NestPipelineTests.cs index fbbee52..fab6faf 100644 --- a/OpenNest.Engine.Tests/Jobs/NestPipelineTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestPipelineTests.cs @@ -43,7 +43,7 @@ public class NestPipelineTests var item = Item("bracket", 10); var codes = item.Drawing.Program.Codes.Count; - var result = NestPipeline.Run(Request("Default", item)); + var result = NestPipeline.Run(Request("Fill", item)); Assert.True(result.IsValid, string.Join("; ", result.Violations)); Assert.True(result.CanKeep); @@ -240,7 +240,7 @@ public class NestPipelineTests NestPipeline.Run(Request("Mystery Engine", Item("bracket", 1))) ); - Assert.Contains("Default", error.Message); + Assert.Contains("Fill", error.Message); } [Fact] @@ -265,7 +265,7 @@ public class NestPipelineTests cts.Cancel(); Assert.ThrowsAny(() => - NestPipeline.Run(Request("Default", Item("bracket", 1)), null, cts.Token) + NestPipeline.Run(Request("Fill", Item("bracket", 1)), null, cts.Token) ); } } diff --git a/OpenNest.Engine.Tests/Jobs/NestingEngineRegistryTests.cs b/OpenNest.Engine.Tests/Jobs/NestingEngineRegistryTests.cs index 0fed19f..52da257 100644 --- a/OpenNest.Engine.Tests/Jobs/NestingEngineRegistryTests.cs +++ b/OpenNest.Engine.Tests/Jobs/NestingEngineRegistryTests.cs @@ -12,7 +12,7 @@ public class NestingEngineRegistryTests Assert.Contains("Rectangles", names); Assert.Contains("Irregular", names); - Assert.Contains("Default", names); + Assert.Contains("Fill", names); Assert.Contains("Strip", names); Assert.Contains("Vertical Remnant", names); Assert.Contains("Horizontal Remnant", names); @@ -43,7 +43,7 @@ public class NestingEngineRegistryTests var before = NestingEngineRegistry.AvailableEngines.Count; NestingEngineRegistry.Register("Opus55NestingEngine", "stale plug-in", - () => new FixedStrategyNestingEngine("Default")); + () => new FixedStrategyNestingEngine("Fill")); Assert.Equal(before, NestingEngineRegistry.AvailableEngines.Count); Assert.Equal("Irregular", NestingEngineRegistry.ResolveName("Opus55NestingEngine")); @@ -67,9 +67,9 @@ public class NestingEngineRegistryTests var before = NestingEngineRegistry.AvailableEngines.Count; NestingEngineRegistry.Register( - "Default", + "Fill", "duplicate", - () => new FixedStrategyNestingEngine("Default") + () => new FixedStrategyNestingEngine("Fill") ); Assert.Equal(before, NestingEngineRegistry.AvailableEngines.Count); @@ -78,7 +78,7 @@ public class NestingEngineRegistryTests [Fact] public void CreateResolvesKnownNamesCaseInsensitivelyAndRejectsUnknown() { - Assert.NotNull(NestingEngineRegistry.Create("default")); + Assert.NotNull(NestingEngineRegistry.Create("fill")); Assert.NotNull(NestingEngineRegistry.Create("Vertical Remnant")); Assert.NotNull(NestingEngineRegistry.Create("stockladder")); diff --git a/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs b/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs index ac69144..cfd7162 100644 --- a/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs +++ b/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs @@ -8,7 +8,7 @@ namespace OpenNest.Engine.Tests.Jobs; public class PlateFillerContractTests { [Theory] - [InlineData("Default")] + [InlineData("Fill")] [InlineData("Vertical Remnant")] [InlineData("Horizontal Remnant")] public void StandardPlateFiller_Fill_ReturnsPartsBoundToInputDrawing(string strategy) @@ -353,7 +353,7 @@ public class PlateFillerContractTests private static PlateFillerBase CreateFiller(string strategy, Plate plate) => strategy switch { - "Default" => new DefaultPlateFiller(plate), + "Fill" => new DefaultPlateFiller(plate), "Vertical Remnant" => new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical), "Horizontal Remnant" => new RemnantPlateFiller(plate, RemnantFillPolicy.Horizontal), _ => throw new ArgumentOutOfRangeException(nameof(strategy)), diff --git a/OpenNest.Engine.Tests/Jobs/PlateNesterParityTests.cs b/OpenNest.Engine.Tests/Jobs/PlateNesterParityTests.cs index 9cdf366..421fcfc 100644 --- a/OpenNest.Engine.Tests/Jobs/PlateNesterParityTests.cs +++ b/OpenNest.Engine.Tests/Jobs/PlateNesterParityTests.cs @@ -22,7 +22,7 @@ public class PlateNesterParityTests private static NestJob Job( IReadOnlyList parts, int? stockQuantity = 3, - string strategy = "Default" + string strategy = "Fill" ) { var stock = new NestPlateStock("stock", PlateSize, stockQuantity, 1, Edge); @@ -97,7 +97,7 @@ public class PlateNesterParityTests [Fact] public void Builtins_AreResolvedByProductionFactory() { - Assert.IsType(PlateNesterFactory.Create("Default")); + Assert.IsType(PlateNesterFactory.Create("Fill")); Assert.IsType(PlateNesterFactory.Create("Strip")); Assert.IsType(PlateNesterFactory.Create("Vertical Remnant")); Assert.IsType(PlateNesterFactory.Create("Horizontal Remnant")); @@ -234,7 +234,7 @@ public class PlateNesterParityTests [Fact] public void RemnantRestrictedRotation_NeverTouchesFiller() { - // Same safety rule for the remnant nester, whose fillers inherit the Default pipeline's + // Same safety rule for the remnant nester, whose fillers inherit the Fill pipeline's // automatic-rotation limitation. The throwing factory proves the filler is never // constructed; completion at the locked angle proves OrderedPlateNester handled it. var part = new NestJobPart( diff --git a/OpenNest.Engine.Tests/PlateFillServiceTests.cs b/OpenNest.Engine.Tests/PlateFillServiceTests.cs index 868f749..c134ca5 100644 --- a/OpenNest.Engine.Tests/PlateFillServiceTests.cs +++ b/OpenNest.Engine.Tests/PlateFillServiceTests.cs @@ -9,7 +9,7 @@ public class PlateFillServiceTests { private static readonly string[] Strategies = [ - "Default", + "Fill", "Strip", "Vertical Remnant", "Horizontal Remnant", @@ -44,7 +44,7 @@ public class PlateFillServiceTests var drawing = new Drawing("part", TestDrawingFactory.Rectangle(6, 4)); var parts = PlateFillService.FillItem( - "Default", + "Fill", plate, new NestItem { Drawing = drawing, Quantity = 6 }, plate.WorkArea(), @@ -120,7 +120,7 @@ public class PlateFillServiceTests // The plateNumber overload reports the caller's plate index like the legacy // engine's PlateNumber did for interactive multi-plate loops. var progress = new CapturingProgress(); - var parts = PlateFillService.Nest("Default", plate, items, 3, progress, CancellationToken.None); + var parts = PlateFillService.Nest("Fill", plate, items, 3, progress, CancellationToken.None); Assert.NotEmpty(parts); Assert.NotEmpty(progress.Reports); @@ -217,7 +217,7 @@ public class PlateFillServiceTests var drawing = new Drawing("part", TestDrawingFactory.Rectangle(6, 4)); Assert.Throws(() => - PlateFillService.FillItem("Default", null!, new NestItem { Drawing = drawing, Quantity = 1 }, new Box(0, 0, 10, 10), null, CancellationToken.None) + PlateFillService.FillItem("Fill", null!, new NestItem { Drawing = drawing, Quantity = 1 }, new Box(0, 0, 10, 10), null, CancellationToken.None) ); } diff --git a/OpenNest.Engine.Tests/RectanglePacking/AreaPackerTests.cs b/OpenNest.Engine.Tests/RectanglePacking/AreaPackerTests.cs index d9e3028..9a969de 100644 --- a/OpenNest.Engine.Tests/RectanglePacking/AreaPackerTests.cs +++ b/OpenNest.Engine.Tests/RectanglePacking/AreaPackerTests.cs @@ -61,8 +61,8 @@ public class AreaPackerTests var area = plate.WorkArea(); var items = new List { Item("panel", 10 + SheetPacker.OverhangAllowance * 0.8, 4, 2) }; - var parts = PlateFillService.PackArea("Default", plate, area, items, null, CancellationToken.None); - var again = PlateFillService.PackArea("Default", plate, area, items, null, CancellationToken.None); + var parts = PlateFillService.PackArea("Fill", plate, area, items, null, CancellationToken.None); + var again = PlateFillService.PackArea("Fill", plate, area, items, null, CancellationToken.None); Assert.Equal(2, parts.Count); Assert.Equal(parts.Select(p => (p.Location, p.Rotation)), again.Select(p => (p.Location, p.Rotation))); @@ -92,7 +92,7 @@ public class AreaPackerTests }; var area = plate.WorkArea(); var items = new List { Item("panel", 4, 10 + SheetPacker.OverhangAllowance * 0.8, 2) }; - var parts = PlateFillService.PackArea("Default", plate, area, items, null, CancellationToken.None); + var parts = PlateFillService.PackArea("Fill", plate, area, items, null, CancellationToken.None); Assert.Equal(2, parts.Count); Assert.All(parts, p => @@ -117,7 +117,7 @@ public class AreaPackerTests var items = new List { rotated ? Item("panel", 6 + excess, 10 + excess, 1) : Item("panel", 10 + excess, 6 + excess, 1) }; - var part = Assert.Single(PlateFillService.PackArea("Default", plate, plate.WorkArea(), items, null, CancellationToken.None)); + var part = Assert.Single(PlateFillService.PackArea("Fill", plate, plate.WorkArea(), items, null, CancellationToken.None)); Assert.True(part.BoundingBox.Right <= 10 + NestTolerances.WorkAreaSlack); Assert.True(part.BoundingBox.Top <= 6 + NestTolerances.WorkAreaSlack); @@ -130,7 +130,7 @@ public class AreaPackerTests { var plate = new Plate(new Size(6, 10)) { PartSpacing = spacing }; var items = new List { Item("panel", 10 + NestTolerances.WorkAreaSlack * 1.1, 4, 1) }; - Assert.Empty(PlateFillService.PackArea("Default", plate, plate.WorkArea(), items, null, CancellationToken.None)); + Assert.Empty(PlateFillService.PackArea("Fill", plate, plate.WorkArea(), items, null, CancellationToken.None)); } [Theory] @@ -144,7 +144,7 @@ public class AreaPackerTests var area = new Box(x, y, w, h); var excess = SheetPacker.OverhangAllowance * 0.8; var items = new List { w == 5 ? Item("panel", w + excess, h - 0.25, 1) : Item("panel", 8, h + excess, 1) }; - var parts = PlateFillService.PackArea("Default", plate, area, items, null, CancellationToken.None); + var parts = PlateFillService.PackArea("Fill", plate, area, items, null, CancellationToken.None); Assert.Equal(fits ? 1 : 0, parts.Count); } @@ -181,7 +181,7 @@ public class AreaPackerTests var area = new Box(0, 0, 12, 12); var items = new List { Item("tall", 5, 7, 3), Item("small", 4, 3, 2) }; - var parts = PlateFillService.PackArea("Default", plate, area, items, null, CancellationToken.None); + var parts = PlateFillService.PackArea("Fill", plate, area, items, null, CancellationToken.None); Assert.Equal(5, parts.Count); Assert.Equal(3, parts.Count(p => p.BaseDrawing.Name == "tall")); diff --git a/OpenNest.Engine/Jobs/Cutouts/CutoutLatticeFill.cs b/OpenNest.Engine/Jobs/Cutouts/CutoutLatticeFill.cs index 66e119d..4492906 100644 --- a/OpenNest.Engine/Jobs/Cutouts/CutoutLatticeFill.cs +++ b/OpenNest.Engine/Jobs/Cutouts/CutoutLatticeFill.cs @@ -100,7 +100,7 @@ internal static class CutoutLatticeFill .Select((p, index) => p with { InstanceIndex = index }).ToArray(); } - /// Default Fill over the cutout's bounds grown by one step on every side, in frame + /// Fill over the cutout's bounds grown by one step on every side, in frame /// coordinates. Fill places whole parts only, so the margin keeps every offset covered. private static List Lattice(NestJobPart insert, Box bounds, double step, double spacing, CancellationToken token) diff --git a/OpenNest.Engine/Jobs/NestJobOptions.cs b/OpenNest.Engine/Jobs/NestJobOptions.cs index 0cf82c6..be47dcf 100644 --- a/OpenNest.Engine/Jobs/NestJobOptions.cs +++ b/OpenNest.Engine/Jobs/NestJobOptions.cs @@ -6,7 +6,7 @@ namespace OpenNest.Engine.Jobs; public sealed class NestJobOptions { public NestJobOptions( - string placementStrategy = "Default", + string placementStrategy = "Fill", int? maxPlates = null, double salvageRate = 0, double minimumSalvageDimension = 0 diff --git a/OpenNest.Engine/Jobs/NestingEngineRegistry.cs b/OpenNest.Engine/Jobs/NestingEngineRegistry.cs index 26a152d..6f8b2d5 100644 --- a/OpenNest.Engine/Jobs/NestingEngineRegistry.cs +++ b/OpenNest.Engine/Jobs/NestingEngineRegistry.cs @@ -28,6 +28,7 @@ public static class NestingEngineRegistry { ["Opus55NestingEngine"] = "Irregular", ["RectanglesNestingEngine"] = "Rectangles", + ["Default"] = "Fill", }; static NestingEngineRegistry() @@ -51,9 +52,9 @@ public static class NestingEngineRegistry ); Register( - "Default", + "Fill", "Multi-phase nesting (Linear, Pairs, RectBestFit, Remainder)", - () => new FixedStrategyNestingEngine("Default") + () => new FixedStrategyNestingEngine("Fill") ); Register( diff --git a/OpenNest.Engine/Jobs/Placement/PlateFillService.cs b/OpenNest.Engine/Jobs/Placement/PlateFillService.cs index e7d482e..ca8f4de 100644 --- a/OpenNest.Engine/Jobs/Placement/PlateFillService.cs +++ b/OpenNest.Engine/Jobs/Placement/PlateFillService.cs @@ -15,10 +15,16 @@ namespace OpenNest.Engine.Jobs.Placement; /// public static class PlateFillService { + /// Strategy used when a caller selection names none. + public const string DefaultStrategy = "Fill"; + + /// Name of the Fill strategy in earlier releases; accepted as an alias. + private const string LegacyFillName = "Default"; + /// The four built-in strategy names, in registry display order. public static IReadOnlyList BuiltInStrategies { get; } = [ - "Default", + "Fill", "Strip", "Vertical Remnant", "Horizontal Remnant", @@ -91,9 +97,10 @@ public static class PlateFillService } /// - /// Resolves a caller-supplied strategy name: null or empty means "Default"; otherwise the name + /// Resolves a caller-supplied strategy name: null or empty means "Fill"; otherwise the name /// must match a built-in strategy, matched case-insensitively like the legacy registry's - /// ActiveEngineName so tolerant interactive callers keep working. Returns the canonical name; + /// ActiveEngineName so tolerant interactive callers keep working. "Default", the Fill + /// strategy's name in earlier releases, still resolves to "Fill". Returns the canonical name; /// unknown names throw . /// public static string ResolveStrategy(string strategy) => ResolveStrategy(strategy, true); @@ -105,12 +112,14 @@ public static class PlateFillService if (string.IsNullOrWhiteSpace(strategy)) { if (allowEmpty) - return "Default"; + return DefaultStrategy; throw new NotSupportedException( $"Unknown placement strategy: '{strategy}'. Known strategies: {string.Join(", ", BuiltInStrategies)}." ); } + if (strategy.Equals(LegacyFillName, StringComparison.OrdinalIgnoreCase)) + return DefaultStrategy; foreach (var candidate in BuiltInStrategies) { if (candidate.Equals(strategy, StringComparison.OrdinalIgnoreCase)) @@ -122,13 +131,13 @@ public static class PlateFillService ); } - /// Builds the filler for an optional strategy (null/empty = Default). + /// Builds the filler for an optional strategy (null/empty = Fill). private static PlateFillerBase CreateFiller(string strategy, Plate plate) { ArgumentNullException.ThrowIfNull(plate); return ResolveStrategy(strategy) switch { - "Default" => new DefaultPlateFiller(plate), + "Fill" => new DefaultPlateFiller(plate), "Strip" => new StripPlateFiller(plate), "Vertical Remnant" => new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical), _ => new RemnantPlateFiller(plate, RemnantFillPolicy.Horizontal), @@ -140,7 +149,7 @@ public static class PlateFillService { ArgumentNullException.ThrowIfNull(strategy); // An explicit empty string is an unknown strategy; only ResolveStrategy(string), - // used for caller selections, maps null/empty to Default. + // used for caller selections, maps null/empty to Fill. ResolveStrategy(strategy, allowEmpty: false); return CreateFiller(strategy, plate); } diff --git a/OpenNest.Engine/Jobs/Placement/PrivatePlateFill.cs b/OpenNest.Engine/Jobs/Placement/PrivatePlateFill.cs index bee8133..9b41d0e 100644 --- a/OpenNest.Engine/Jobs/Placement/PrivatePlateFill.cs +++ b/OpenNest.Engine/Jobs/Placement/PrivatePlateFill.cs @@ -10,7 +10,7 @@ using OpenNest.Geometry; namespace OpenNest.Engine.Jobs.Placement; /// -/// Runs the Default Fill for one private drawing on a private plate, for callers that turn the +/// Runs the Fill strategy for one private drawing on a private plate, for callers that turn the /// result into job poses. The caller owns the drawing and must call /// for it when finished. /// diff --git a/OpenNest.Engine/Jobs/Placement/RemnantPlateNester.cs b/OpenNest.Engine/Jobs/Placement/RemnantPlateNester.cs index 9ba8106..368d368 100644 --- a/OpenNest.Engine/Jobs/Placement/RemnantPlateNester.cs +++ b/OpenNest.Engine/Jobs/Placement/RemnantPlateNester.cs @@ -13,8 +13,8 @@ namespace OpenNest.Engine.Jobs.Placement; /// . /// /// -/// The remnant fillers share the Default pipeline's automatic-rotation limitation, so non-automatic -/// requirements route through exactly as they do for Default. +/// The remnant fillers share the Fill pipeline's automatic-rotation limitation, so non-automatic +/// requirements route through exactly as they do for Fill. /// public sealed class RemnantPlateNester : IPlateNester { @@ -45,7 +45,7 @@ public sealed class RemnantPlateNester : IPlateNester ArgumentNullException.ThrowIfNull(request); token.ThrowIfCancellationRequested(); - // Same safety rule as DefaultPlateNester: the remnant fillers inherit the Default pipeline's + // Same safety rule as DefaultPlateNester: the remnant fillers inherit the Fill pipeline's // automatic-rotation limitation, so any non-automatic requirement goes to the policy-aware // ordered nester. if (request.Parts.Any(part => part.Rotation.Kind != RotationPolicyKind.Automatic)) diff --git a/OpenNest.Engine/Jobs/PlateNesterFactory.cs b/OpenNest.Engine/Jobs/PlateNesterFactory.cs index 4699846..55b11ca 100644 --- a/OpenNest.Engine/Jobs/PlateNesterFactory.cs +++ b/OpenNest.Engine/Jobs/PlateNesterFactory.cs @@ -15,7 +15,8 @@ public static class PlateNesterFactory ArgumentNullException.ThrowIfNull(strategy); return strategy switch { - "Default" => new DefaultPlateNester(), + // "Default" is the strategy's name in earlier releases. + "Fill" or "Default" => new DefaultPlateNester(), "Strip" => new StripPlateNester(), "Vertical Remnant" => RemnantPlateNester.Vertical(), "Horizontal Remnant" => RemnantPlateNester.Horizontal(), diff --git a/OpenNest.Mcp/Tools/NestingTools.cs b/OpenNest.Mcp/Tools/NestingTools.cs index 75fd802..77eb70d 100644 --- a/OpenNest.Mcp/Tools/NestingTools.cs +++ b/OpenNest.Mcp/Tools/NestingTools.cs @@ -31,7 +31,7 @@ namespace OpenNest.Mcp.Tools [Description("Index of the plate to fill")] int plateIndex, [Description("Name of the drawing to fill with")] string drawingName, [Description("Maximum quantity to place (0 = unlimited)")] int quantity = 0, - [Description("Placement strategy: Default, Strip, Vertical Remnant, Horizontal Remnant")] + [Description("Placement strategy: Fill, Strip, Vertical Remnant, Horizontal Remnant")] string engine = null ) { @@ -84,7 +84,7 @@ namespace OpenNest.Mcp.Tools [Description("Width of the area")] double width, [Description("Length of the area")] double length, [Description("Maximum quantity to place (0 = unlimited)")] int quantity = 0, - [Description("Placement strategy: Default, Strip, Vertical Remnant, Horizontal Remnant")] + [Description("Placement strategy: Fill, Strip, Vertical Remnant, Horizontal Remnant")] string engine = null ) { @@ -134,7 +134,7 @@ namespace OpenNest.Mcp.Tools [Description("Index of the plate")] int plateIndex, [Description("Name of the drawing to fill with")] string drawingName, [Description("Maximum quantity per remnant (0 = unlimited)")] int quantity = 0, - [Description("Placement strategy: Default, Strip, Vertical Remnant, Horizontal Remnant")] + [Description("Placement strategy: Fill, Strip, Vertical Remnant, Horizontal Remnant")] string engine = null ) { @@ -197,7 +197,7 @@ namespace OpenNest.Mcp.Tools [Description("Index of the plate")] int plateIndex, [Description("Comma-separated drawing names")] string drawingNames, [Description("Comma-separated quantities for each drawing")] string quantities, - [Description("Placement strategy: Default, Strip, Vertical Remnant, Horizontal Remnant")] + [Description("Placement strategy: Fill, Strip, Vertical Remnant, Horizontal Remnant")] string engine = null ) { diff --git a/OpenNest.Tests/Benchmark/NestLayoutCheckEquivalenceTests.cs b/OpenNest.Tests/Benchmark/NestLayoutCheckEquivalenceTests.cs index c0bad3d..96bf1c7 100644 --- a/OpenNest.Tests/Benchmark/NestLayoutCheckEquivalenceTests.cs +++ b/OpenNest.Tests/Benchmark/NestLayoutCheckEquivalenceTests.cs @@ -10,7 +10,7 @@ public class NestLayoutCheckEquivalenceTests { [Theory] [InlineData("StockLadder")] - [InlineData("Default")] + [InlineData("Fill")] [InlineData("Strip")] [InlineData("Vertical Remnant")] [InlineData("Horizontal Remnant")] diff --git a/OpenNest.Tests/BestFit/NativeUClearanceTests.cs b/OpenNest.Tests/BestFit/NativeUClearanceTests.cs index edc33a3..22ce6d4 100644 --- a/OpenNest.Tests/BestFit/NativeUClearanceTests.cs +++ b/OpenNest.Tests/BestFit/NativeUClearanceTests.cs @@ -38,7 +38,7 @@ public class NativeUClearanceTests PartSpacing = 0.25, EdgeSpacing = new Spacing(1, 1), }; - var parts = PlateFillService.FillItem("Default", plate, + var parts = PlateFillService.FillItem("Fill", plate, new NestItem { Drawing = drawing, Quantity = quantity }, plate.WorkArea(), null, CancellationToken.None); diff --git a/OpenNest.Tests/Engine/EngineOverlapTests.cs b/OpenNest.Tests/Engine/EngineOverlapTests.cs index 5ba7dfc..6b2bdad 100644 --- a/OpenNest.Tests/Engine/EngineOverlapTests.cs +++ b/OpenNest.Tests/Engine/EngineOverlapTests.cs @@ -28,7 +28,7 @@ public class EngineOverlapTests } [Theory] - [InlineData("Default")] + [InlineData("Fill")] [InlineData("Strip")] [InlineData("Vertical Remnant")] [InlineData("Horizontal Remnant")] diff --git a/OpenNest.Tests/Engine/ExplicitPlacementStrategyTests.cs b/OpenNest.Tests/Engine/ExplicitPlacementStrategyTests.cs index 1f435bf..a6db75a 100644 --- a/OpenNest.Tests/Engine/ExplicitPlacementStrategyTests.cs +++ b/OpenNest.Tests/Engine/ExplicitPlacementStrategyTests.cs @@ -26,9 +26,9 @@ public class ExplicitPlacementStrategyTests [InlineData(null)] [InlineData("")] [InlineData(" ")] - public void ResolveStrategy_UnsetMeansDefault(string strategy) + public void ResolveStrategy_UnsetMeansFill(string strategy) { - Assert.Equal("Default", PlateFillService.ResolveStrategy(strategy)); + Assert.Equal("Fill", PlateFillService.ResolveStrategy(strategy)); } [Theory] diff --git a/OpenNest.WinForms.Tests/ActionSelectAreaCutOffTests.cs b/OpenNest.WinForms.Tests/ActionSelectAreaCutOffTests.cs index f18c5b9..f444e7d 100644 --- a/OpenNest.WinForms.Tests/ActionSelectAreaCutOffTests.cs +++ b/OpenNest.WinForms.Tests/ActionSelectAreaCutOffTests.cs @@ -63,7 +63,7 @@ public class ActionSelectAreaCutOffTests program.LineTo(3, 0); program.LineTo(0, 0); // ActionFillArea passes SelectedArea directly to this service. - var parts = PlateFillService.FillItem("Default", plate, + var parts = PlateFillService.FillItem("Fill", plate, new NestItem { Drawing = new Drawing("square", program) }, area, null, CancellationToken.None); Assert.NotEmpty(parts); Assert.All(parts, part => diff --git a/OpenNest/Forms/EngineSelection.cs b/OpenNest/Forms/EngineSelection.cs index 85d26de..30bcac0 100644 --- a/OpenNest/Forms/EngineSelection.cs +++ b/OpenNest/Forms/EngineSelection.cs @@ -13,7 +13,7 @@ namespace OpenNest.Forms /// App-scoped nesting-engine selection. The selected name addresses a whole-job /// INestingEngine resolved through NestingEngineRegistry at call time; single-plate /// interactive fill uses FillStrategy, which maps a built-in engine to its placement - /// strategy and falls back to Default for jobs-only engines (StockLadder, plug-ins). + /// strategy and falls back to Fill for jobs-only engines (StockLadder, plug-ins). /// public static class EngineSelection { @@ -67,8 +67,8 @@ namespace OpenNest.Forms .ToList(); /// Placement strategy for single-plate fill: the selection when it names a - /// built-in strategy, otherwise Default. - public static string FillStrategy => IsFillStrategy(engineName) ? engineName : DefaultEngineName; + /// built-in strategy, otherwise Fill. + public static string FillStrategy => IsFillStrategy(engineName) ? engineName : PlateFillService.DefaultStrategy; public static bool IsFillStrategy(string name) => !string.IsNullOrWhiteSpace(name) diff --git a/README.md b/README.md index 19c04d8..f0afd69 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ Key options: `--size WxL`, `--autonest` (validated single-sheet whole-job nestin ```bash dotnet run --project OpenNest.Benchmark -- ./benchmark-jobs \ - --sheet-sizes 48x96,60x120,72x120 --engines Default,StockLadder --csv results.csv + --sheet-sizes 48x96,60x120,72x120 --engines Irregular,Rectangles --csv results.csv ``` Layouts are validated (bounds, spacing, quantity, rotation, stock match); invalid runs place nothing and pay the penalty. `--parallel` (default 3) speeds up scoring but inflates `Time(ms)` — use `--parallel 1` when comparing speed. Pass `--sheet-sizes` for an unbiased run; otherwise only each file's original sizes are offered. `--progress` logs each solve's start, the engine's `NestJobProgress` (plate evaluations throttled to one line per 2 s, every plate commit) and its finish. Custom engines drop in as DLLs implementing `INestingEngine` (public parameterless constructor) in an `Engines/` folder next to the benchmark. Built-in engines and how to change them: [nesting engines](docs/nesting-engines.md). @@ -93,7 +93,7 @@ Engines implement `INestingEngine.Solve(NestJob)`. Desktop Auto Nest, console au |--------|-------------| | **Rectangles** | Plain and near-rectangular plates: maximal-rectangles box packing | | **Irregular** | Irregular profiles: no-fit-polygon frontier packing | -| **Default** | Multi-phase: linear fill → pairs → rect best-fit → extents | +| **Fill** | Multi-phase: linear fill → pairs → rect best-fit → extents (named Default in earlier releases) | | **Strip** | Iterative shrink-fill for mixed-drawing layouts | | **Vertical / Horizontal Remnant** | Optimizes a clean remnant drop on one edge | | **StockLadder** | Whole-job, stock-constrained baseline with salvage-credit ranking | diff --git a/docs/geometry/pair-spacing.md b/docs/geometry/pair-spacing.md index 5942c99..257b920 100644 --- a/docs/geometry/pair-spacing.md +++ b/docs/geometry/pair-spacing.md @@ -18,7 +18,7 @@ Fresh-process import/cache/materialization probes used a 24-by-24 sheet, one-inc | --- | --- | --- | | Smallest-envelope kept pair, minimum raw clearance | 0.22548054744486495 | 0.24999929486961545 | | `PairFiller`, 70 parts, minimum raw clearance | 0.22548054744486434 | 0.24999929486961417 | -| `PlateFillService.FillItem("Default")`, 70 parts, minimum raw clearance | 0.2254805474448648 | 0.24999929486961447 | +| `PlateFillService.FillItem("Fill")`, 70 parts, minimum raw clearance | 0.2254805474448648 | 0.24999929486961447 | Measurements use raw material outlines tessellated at 1e-6 chord tolerance and independent Shapely boundary distances, not the slide solver or its offset contours. The roughly 7e-7 shortfall is within tessellation error. These specific pair/grid polygons were valid; no geometry repair was applied. The corrected top pair passes the existing validator. The full grids do **not** pass it; see below. diff --git a/docs/nesting-engines.md b/docs/nesting-engines.md index 86eda94..3b42ce3 100644 --- a/docs/nesting-engines.md +++ b/docs/nesting-engines.md @@ -14,7 +14,7 @@ in `OpenNest.Engine/NestingEngines//`, its tests in `OpenNest.Engine.Tests | Rectangles | Plain and near-rectangular plates | Each part packed as the box of its material at its minimum-area rotation, using a maximal-rectangles free list; stock chosen sheet by sheet by salvage-credited look-ahead cost | | Irregular | Irregular profiles | No-fit-polygon frontier packing with gap filling and best-fit pairs, six whole-job strategy variants and a tail re-plan | | StockLadder | Caller-supplied stock ladders | Constrained-first fill with equivalent-demand area repacking | -| Default, Strip, Vertical Remnant, Horizontal Remnant | Single-strategy fills | The fixed placement strategies behind interactive fill | +| Fill, Strip, Vertical Remnant, Horizontal Remnant | Single-strategy fills | The fixed placement strategies behind interactive fill; Fill is the multi-phase lattice fill (linear, pairs, rectangle best-fit, remainder) | Rectangles places irregular parts validly, but only as their bounding boxes; it never nests into a notch or hole. Box sides account for how the layout check flattens arcs, so round-edged parts stay @@ -44,8 +44,8 @@ with a single boundary/containment union. Any remaining numerical hole is filled only when its entire ring is certified to lie in forbidden space, preserving genuine enclosed placement pockets without changing spacing tolerances. -When remaining demand exceeds two, Irregular also offers Default Fill patterns as optional -multi-member candidates, not as solid bounding boxes or a whole-job Default fallback. It searches +When remaining demand exceeds two, Irregular also offers Fill patterns as optional +multi-member candidates, not as solid bounding boxes or a whole-job Fill fallback. It searches the empty work area and physical leftover space for up to two high-area rectangles. Occupied outlines are expanded by part spacing before rectangle search. Each sheet prepares blocks initially and after its first placement, for up to four high-demand-area types; each type has at most eight @@ -67,7 +67,7 @@ engine, so every engine benefits. Nothing calls it yet: a part inside a cutout m the cutout's contour, and the sequencer does not enforce that order. `CutoutLatticeFill` (`OpenNest.Engine/Jobs/Cutouts/`) fills one closed cutout with copies of one -part. It runs Default Fill over the cutout's bounds plus one part step on every side, then shifts +part. It runs Fill over the cutout's bounds plus one part step on every side, then shifts that lattice across a grid of offsets of up to half a step each way. At each offset it keeps the copies whose spacing-grown outline lies inside the cutout, using the part's inner-fit region of the inscribed, flattened cutout, and the offset keeping the most copies wins. Every returned pose @@ -78,16 +78,20 @@ calls for some parts, so results are not yet guaranteed identical between runs. ## Renamed engines -Earlier releases shipped these as plug-ins under other names. The registry maps the old names so -saved desktop selections, scripts and API requests keep working: +The registry maps names used by earlier releases (the first two shipped as plug-ins) so saved +desktop selections, scripts and API requests keep working: | Old name | Now | |---|---| | `Opus55NestingEngine` | Irregular | | `RectanglesNestingEngine` | Rectangles | +| `Default` | Fill | + +Fill strategy calls (interactive fill, `PlateFillService`, console fill without `--autonest`, MCP fill +tools) also accept `Default` as Fill. Gpt6Astra and Qwen38FlashNext are no longer shipped and have no alias. A saved selection of either -falls back to Default with the usual status-bar warning. +falls back to the default engine with the usual status-bar warning. ## Changing an engine diff --git a/docs/performance/fill-verification.md b/docs/performance/fill-verification.md index 3a3afc6..beb7469 100644 --- a/docs/performance/fill-verification.md +++ b/docs/performance/fill-verification.md @@ -18,7 +18,7 @@ Irregular's private block proposals opt into quantity-limited Row/Column stripe perpendicular copies stop after reaching the requested count. The final fill still trims its winner to the exact quantity. Existing overlap fallbacks and block spacing certification remain active; fallback tiling can exceed the soft limit. Nonpositive -limits remain uncapped. Ordinary Default fills and the zero-quantity cutout lattice +limits remain uncapped. Ordinary Fill-strategy fills and the zero-quantity cutout lattice keep their full-area behavior. This can change which private block candidate wins; it is not a promise of identical diff --git a/scripts/ReleaseSmoke/Program.cs b/scripts/ReleaseSmoke/Program.cs index 06906f5..2d59729 100644 --- a/scripts/ReleaseSmoke/Program.cs +++ b/scripts/ReleaseSmoke/Program.cs @@ -20,7 +20,7 @@ try var create = registry.GetMethod("Create")!; // Every built-in engine the desktop offers must instantiate from the packaged assembly. - string[] expected = ["Rectangles", "Irregular", "StockLadder", "Default", "Strip", "Vertical Remnant", "Horizontal Remnant"]; + string[] expected = ["Rectangles", "Irregular", "StockLadder", "Fill", "Strip", "Vertical Remnant", "Horizontal Remnant"]; foreach (var name in expected) { var engine = create.Invoke(null, [name])!;