refactor(engine): remove legacy nesting engine surface
This commit is contained in:
@@ -3,6 +3,7 @@ using OpenNest.Geometry;
|
||||
using OpenNest.IO;
|
||||
using Xunit.Abstractions;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
|
||||
namespace OpenNest.Tests.Engine;
|
||||
|
||||
@@ -31,7 +32,7 @@ public class EngineOverlapTests
|
||||
[InlineData("Strip")]
|
||||
[InlineData("Vertical Remnant")]
|
||||
[InlineData("Horizontal Remnant")]
|
||||
public void FillPlate_NoOverlaps(string engineName)
|
||||
public void FillPlate_NoOverlaps(string strategy)
|
||||
{
|
||||
var drawing = ImportDxf();
|
||||
if (drawing is null)
|
||||
@@ -39,23 +40,21 @@ public class EngineOverlapTests
|
||||
|
||||
var plate = new Plate(60, 120);
|
||||
|
||||
NestEngineRegistry.ActiveEngineName = engineName;
|
||||
var engine = NestEngineRegistry.Create(plate);
|
||||
|
||||
var item = new NestItem { Drawing = drawing };
|
||||
var success = engine.Fill(item);
|
||||
var parts = PlateFillService.FillItem(
|
||||
strategy,
|
||||
plate,
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
progress: null,
|
||||
token: CancellationToken.None
|
||||
);
|
||||
plate.Parts.AddRange(parts);
|
||||
|
||||
_output.WriteLine(
|
||||
$"Engine: {engine.Name}, Parts: {plate.Parts.Count}, Utilization: {plate.Utilization():P1}"
|
||||
$"Strategy: {strategy}, Parts: {plate.Parts.Count}, Utilization: {plate.Utilization():P1}"
|
||||
);
|
||||
|
||||
if (engine is DefaultNestEngine defaultEngine)
|
||||
{
|
||||
_output.WriteLine($"Winner phase: {defaultEngine.WinnerPhase}");
|
||||
foreach (var pr in defaultEngine.PhaseResults)
|
||||
_output.WriteLine($" Phase {pr.Phase}: {pr.PartCount} parts in {pr.TimeMs}ms");
|
||||
}
|
||||
|
||||
// Show rotation distribution
|
||||
var rotGroups = plate
|
||||
.Parts.GroupBy(p => System.Math.Round(OpenNest.Math.Angle.ToDegrees(p.Rotation), 1))
|
||||
@@ -74,7 +73,7 @@ public class EngineOverlapTests
|
||||
|
||||
Assert.False(
|
||||
hasOverlaps,
|
||||
$"Engine '{engineName}' produced {collisionPoints.Count} collision point(s) with {plate.Parts.Count} parts"
|
||||
$"Strategy '{strategy}' produced {collisionPoints.Count} collision point(s) with {plate.Parts.Count} parts"
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Jobs.Placement.Fillers;
|
||||
|
||||
namespace OpenNest.Tests.Engine;
|
||||
|
||||
@@ -17,49 +18,49 @@ public class EngineRefactorSmokeTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultEngine_FillNestItem_ProducesResults()
|
||||
public void DefaultPlateFiller_FillNestItem_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
|
||||
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
System.Threading.CancellationToken.None
|
||||
);
|
||||
|
||||
Assert.True(parts.Count > 0, "DefaultNestEngine should fill parts");
|
||||
Assert.True(parts.Count > 0, "DefaultPlateFiller should fill parts");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultEngine_FillGroupParts_ProducesResults()
|
||||
public void DefaultPlateFiller_FillGroupParts_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
var drawing = MakeRectDrawing(20, 10);
|
||||
var groupParts = new List<Part> { new Part(drawing) };
|
||||
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
groupParts,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
System.Threading.CancellationToken.None
|
||||
);
|
||||
|
||||
Assert.True(parts.Count > 0, "DefaultNestEngine group fill should produce parts");
|
||||
Assert.True(parts.Count > 0, "DefaultPlateFiller group fill should produce parts");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultEngine_ForceFullAngleSweep_StillWorks()
|
||||
public void DefaultPlateFiller_ForceFullAngleSweep_StillWorks()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
engine.ForceFullAngleSweep = true;
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
filler.ForceFullAngleSweep = true;
|
||||
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
|
||||
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
@@ -70,33 +71,33 @@ public class EngineRefactorSmokeTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void StripEngine_Nest_ProducesResults()
|
||||
public void StripPlateFiller_Nest_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new StripNestEngine(plate);
|
||||
var filler = new StripPlateFiller(plate);
|
||||
var items = new List<NestItem>
|
||||
{
|
||||
new NestItem { Drawing = MakeRectDrawing(20, 10, "large"), Quantity = 10 },
|
||||
new NestItem { Drawing = MakeRectDrawing(8, 5, "small"), Quantity = 5 },
|
||||
};
|
||||
|
||||
var parts = engine.Nest(items, null, System.Threading.CancellationToken.None);
|
||||
var parts = filler.Nest(items, null, System.Threading.CancellationToken.None);
|
||||
|
||||
Assert.True(parts.Count > 0, "StripNestEngine should nest parts");
|
||||
Assert.True(parts.Count > 0, "StripPlateFiller should nest parts");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DefaultEngine_Nest_ProducesResults()
|
||||
public void DefaultPlateFiller_Nest_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
var items = new List<NestItem>
|
||||
{
|
||||
new NestItem { Drawing = MakeRectDrawing(20, 10, "a"), Quantity = 5 },
|
||||
new NestItem { Drawing = MakeRectDrawing(15, 8, "b"), Quantity = 3 },
|
||||
};
|
||||
|
||||
var parts = engine.Nest(items, null, System.Threading.CancellationToken.None);
|
||||
var parts = filler.Nest(items, null, System.Threading.CancellationToken.None);
|
||||
|
||||
Assert.True(parts.Count > 0, "Base Nest method should place parts");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace OpenNest.Tests.Engine;
|
||||
|
||||
/// <summary>
|
||||
/// Phase 3.2: MultiPlateNester and PlateOptimizer take an explicit placement strategy at their
|
||||
/// top-level call boundary instead of consulting the process-global NestEngineRegistry.
|
||||
/// top-level call boundary instead of consulting process-global selection state.
|
||||
/// </summary>
|
||||
public class ExplicitPlacementStrategyTests
|
||||
{
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Threading;
|
||||
using OpenNest.CNC;
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.BestFit;
|
||||
using OpenNest.Engine.Jobs.Placement.Fillers;
|
||||
using OpenNest.Geometry;
|
||||
using OpenNest.Math;
|
||||
|
||||
@@ -37,9 +38,9 @@ public class NestInvarianceTests
|
||||
private static int RunFillCount(Drawing drawing, Plate plate)
|
||||
{
|
||||
BestFitCache.Clear();
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
var item = new NestItem { Drawing = drawing };
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
progress: null,
|
||||
@@ -71,9 +72,9 @@ public class NestInvarianceTests
|
||||
foreach (var theta in new[] { 0.0, 0.3, 0.8, 1.2 })
|
||||
{
|
||||
BestFitCache.Clear();
|
||||
var engine = new DefaultNestEngine(plate);
|
||||
var filler = new DefaultPlateFiller(plate);
|
||||
var item = new NestItem { Drawing = MakeImportedAt(theta) };
|
||||
var parts = engine.Fill(item, workArea, progress: null, token: CancellationToken.None);
|
||||
var parts = filler.Fill(item, workArea, progress: null, token: CancellationToken.None);
|
||||
|
||||
Assert.NotNull(parts);
|
||||
foreach (var p in parts)
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using OpenNest.Engine;
|
||||
using OpenNest.Engine.Fill;
|
||||
using OpenNest.Engine.Jobs.Placement;
|
||||
using OpenNest.Engine.Jobs.Placement.Fillers;
|
||||
using OpenNest.Geometry;
|
||||
|
||||
namespace OpenNest.Tests.Engine;
|
||||
@@ -18,82 +20,79 @@ public class RemnantEngineTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerticalRemnantEngine_UsesVerticalRemnantComparer()
|
||||
public void VerticalRemnantPlateFiller_UsesHorizontalPreferredDirection()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new VerticalRemnantEngine(plate);
|
||||
Assert.Equal("Vertical Remnant", engine.Name);
|
||||
Assert.Equal(NestDirection.Horizontal, engine.PreferredDirection);
|
||||
var filler = new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical);
|
||||
Assert.Equal(NestDirection.Horizontal, filler.PreferredDirection);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HorizontalRemnantEngine_UsesHorizontalRemnantComparer()
|
||||
public void HorizontalRemnantPlateFiller_UsesVerticalPreferredDirection()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new HorizontalRemnantEngine(plate);
|
||||
Assert.Equal("Horizontal Remnant", engine.Name);
|
||||
Assert.Equal(NestDirection.Vertical, engine.PreferredDirection);
|
||||
var filler = new RemnantPlateFiller(plate, RemnantFillPolicy.Horizontal);
|
||||
Assert.Equal(NestDirection.Vertical, filler.PreferredDirection);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerticalRemnantEngine_Fill_ProducesResults()
|
||||
public void VerticalRemnantPlateFiller_Fill_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new VerticalRemnantEngine(plate);
|
||||
var filler = new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical);
|
||||
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
|
||||
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
System.Threading.CancellationToken.None
|
||||
);
|
||||
|
||||
Assert.True(parts.Count > 0, "VerticalRemnantEngine should fill parts");
|
||||
Assert.True(parts.Count > 0, "VerticalRemnantPlateFiller should fill parts");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void HorizontalRemnantEngine_Fill_ProducesResults()
|
||||
public void HorizontalRemnantPlateFiller_Fill_ProducesResults()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var engine = new HorizontalRemnantEngine(plate);
|
||||
var filler = new RemnantPlateFiller(plate, RemnantFillPolicy.Horizontal);
|
||||
var item = new NestItem { Drawing = MakeRectDrawing(20, 10) };
|
||||
|
||||
var parts = engine.Fill(
|
||||
var parts = filler.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
System.Threading.CancellationToken.None
|
||||
);
|
||||
|
||||
Assert.True(parts.Count > 0, "HorizontalRemnantEngine should fill parts");
|
||||
Assert.True(parts.Count > 0, "HorizontalRemnantPlateFiller should fill parts");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Registry_ContainsBothRemnantEngines()
|
||||
public void PlateFillService_ListsBothRemnantStrategies()
|
||||
{
|
||||
var names = NestEngineRegistry.AvailableEngines.Select(e => e.Name).ToList();
|
||||
Assert.Contains("Vertical Remnant", names);
|
||||
Assert.Contains("Horizontal Remnant", names);
|
||||
Assert.Contains("Vertical Remnant", PlateFillService.BuiltInStrategies);
|
||||
Assert.Contains("Horizontal Remnant", PlateFillService.BuiltInStrategies);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void VerticalRemnantEngine_ProducesTighterXExtent_ThanDefault()
|
||||
public void VerticalRemnantPlateFiller_ProducesTighterXExtent_ThanDefault()
|
||||
{
|
||||
var plate = new Plate(60, 120);
|
||||
var drawing = MakeRectDrawing(20, 10);
|
||||
var item = new NestItem { Drawing = drawing };
|
||||
|
||||
var defaultEngine = new DefaultNestEngine(plate);
|
||||
var remnantEngine = new VerticalRemnantEngine(plate);
|
||||
var defaultFiller = new DefaultPlateFiller(plate);
|
||||
var remnantFiller = new RemnantPlateFiller(plate, RemnantFillPolicy.Vertical);
|
||||
|
||||
var defaultParts = defaultEngine.Fill(
|
||||
var defaultParts = defaultFiller.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
System.Threading.CancellationToken.None
|
||||
);
|
||||
var remnantParts = remnantEngine.Fill(
|
||||
var remnantParts = remnantFiller.Fill(
|
||||
item,
|
||||
plate.WorkArea(),
|
||||
null,
|
||||
@@ -110,7 +109,7 @@ public class RemnantEngineTests
|
||||
|
||||
Assert.True(
|
||||
remnantXExtent <= defaultXExtent + 0.01,
|
||||
$"Remnant X-extent ({remnantXExtent:F1}) should be <= default ({defaultXExtent:F1})"
|
||||
$"Remnant X-extent ({remnantXExtent:F1}) should be <= default filler ({defaultXExtent:F1})"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user