diff --git a/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs b/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs new file mode 100644 index 0000000..a93f944 --- /dev/null +++ b/OpenNest.Engine.Tests/Jobs/PlateFillerContractTests.cs @@ -0,0 +1,75 @@ +using OpenNest.Engine.Jobs.Placement.Fillers; +using OpenNest.Geometry; + +namespace OpenNest.Engine.Tests.Jobs; + +public class PlateFillerContractTests +{ + [Fact] + public void NestProgressReporter_Report_ClonesPartsAndPreservesReportFields() + { + var source = new Part( + new Drawing("part", TestDrawingFactory.Rectangle(10, 20)), + new Vector(3, 5) + ); + source.Rotate(0.5); + var progress = new CapturingProgress(); + var workArea = new Box(1, 2, 30, 40); + + NestProgressReporter.Report( + progress, + new ProgressReport + { + Phase = NestPhase.Pairs, + PlateNumber = 3, + Parts = new List { source }, + WorkArea = workArea, + Description = "candidate preview", + IsOverallBest = true, + } + ); + + var reported = Assert.Single(progress.Reports); + Assert.Equal(NestPhase.Pairs, reported.Phase); + Assert.Equal(3, reported.PlateNumber); + Assert.Equal("candidate preview", reported.Description); + Assert.True(reported.IsOverallBest); + Assert.Equal(workArea.X, reported.ActiveWorkArea.X); + Assert.Equal(workArea.Y, reported.ActiveWorkArea.Y); + Assert.Equal(workArea.Width, reported.ActiveWorkArea.Width); + Assert.Equal(workArea.Length, reported.ActiveWorkArea.Length); + + var preview = Assert.Single(reported.BestParts); + Assert.NotSame(source, preview); + Assert.Same(source.BaseDrawing, preview.BaseDrawing); + Assert.Equal(source.Location.X, preview.Location.X); + Assert.Equal(source.Location.Y, preview.Location.Y); + Assert.Equal(source.Rotation, preview.Rotation); + } + + [Fact] + public void NestProgressReporter_Report_DoesNotForwardMissingProgressOrParts() + { + var progress = new CapturingProgress(); + var part = new Part(new Drawing("part", TestDrawingFactory.Rectangle())); + + NestProgressReporter.Report( + null, + new ProgressReport { Parts = new List { part } } + ); + NestProgressReporter.Report(progress, new ProgressReport { Parts = null }); + NestProgressReporter.Report(progress, new ProgressReport { Parts = new List() }); + + Assert.Empty(progress.Reports); + } + + private sealed class CapturingProgress : IProgress + { + public List Reports { get; } = new(); + + public void Report(NestProgress value) + { + Reports.Add(value); + } + } +} diff --git a/OpenNest.Engine/Fill/IterativeShrinkFiller.cs b/OpenNest.Engine/Fill/IterativeShrinkFiller.cs index ee8a267..9918e58 100644 --- a/OpenNest.Engine/Fill/IterativeShrinkFiller.cs +++ b/OpenNest.Engine/Fill/IterativeShrinkFiller.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using System.Threading.Tasks; +using OpenNest.Engine.Jobs.Placement.Fillers; using OpenNest.Geometry; namespace OpenNest.Engine.Fill @@ -136,7 +137,7 @@ namespace OpenNest.Engine.Fill var allParts = new List(placedSoFar.Count + best.Count); allParts.AddRange(placedSoFar); allParts.AddRange(best); - NestEngineBase.ReportProgress( + NestProgressReporter.Report( progress, new ProgressReport { diff --git a/OpenNest.Engine/Fill/ShrinkFiller.cs b/OpenNest.Engine/Fill/ShrinkFiller.cs index 30e91d4..0e1d018 100644 --- a/OpenNest.Engine/Fill/ShrinkFiller.cs +++ b/OpenNest.Engine/Fill/ShrinkFiller.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Threading; using OpenNest.Geometry; +using OpenNest.Engine.Jobs.Placement.Fillers; using OpenNest.Engine.RectanglePacking; namespace OpenNest.Engine.Fill @@ -89,7 +90,7 @@ namespace OpenNest.Engine.Fill var desc = $"Shrink {axis}: {bestParts.Count} parts, dim={dim:F1}"; - NestEngineBase.ReportProgress( + NestProgressReporter.Report( progress, new ProgressReport { diff --git a/OpenNest.Engine/Jobs/Placement/Fillers/NestProgressReporter.cs b/OpenNest.Engine/Jobs/Placement/Fillers/NestProgressReporter.cs new file mode 100644 index 0000000..3be10c5 --- /dev/null +++ b/OpenNest.Engine/Jobs/Placement/Fillers/NestProgressReporter.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; + +namespace OpenNest.Engine.Jobs.Placement.Fillers; + +internal static class NestProgressReporter +{ + internal static void Report(IProgress progress, ProgressReport report) + { + if (progress == null || report.Parts == null || report.Parts.Count == 0) + return; + + var clonedParts = new List(report.Parts.Count); + foreach (var part in report.Parts) + clonedParts.Add((Part)part.Clone()); + + Debug.WriteLine( + $"[Progress] Phase={report.Phase}, Plate={report.PlateNumber}, " + + $"Parts={clonedParts.Count} | {report.Description}" + ); + + progress.Report( + new NestProgress + { + Phase = report.Phase, + PlateNumber = report.PlateNumber, + BestParts = clonedParts, + Description = report.Description, + ActiveWorkArea = report.WorkArea, + IsOverallBest = report.IsOverallBest, + } + ); + } +} diff --git a/OpenNest.Engine/NestEngineBase.cs b/OpenNest.Engine/NestEngineBase.cs index 101992b..ef0c53f 100644 --- a/OpenNest.Engine/NestEngineBase.cs +++ b/OpenNest.Engine/NestEngineBase.cs @@ -6,6 +6,7 @@ using System.Threading; using OpenNest.Engine; using OpenNest.Engine.BestFit; using OpenNest.Engine.Fill; +using OpenNest.Engine.Jobs.Placement.Fillers; using OpenNest.Engine.Strategies; using OpenNest.Geometry; using OpenNest.Math; @@ -261,29 +262,7 @@ namespace OpenNest.Engine internal static void ReportProgress(IProgress progress, ProgressReport report) { - if (progress == null || report.Parts == null || report.Parts.Count == 0) - return; - - var clonedParts = new List(report.Parts.Count); - foreach (var part in report.Parts) - clonedParts.Add((Part)part.Clone()); - - Debug.WriteLine( - $"[Progress] Phase={report.Phase}, Plate={report.PlateNumber}, " - + $"Parts={clonedParts.Count} | {report.Description}" - ); - - progress.Report( - new NestProgress - { - Phase = report.Phase, - PlateNumber = report.PlateNumber, - BestParts = clonedParts, - Description = report.Description, - ActiveWorkArea = report.WorkArea, - IsOverallBest = report.IsOverallBest, - } - ); + NestProgressReporter.Report(progress, report); } protected string BuildProgressSummary() diff --git a/OpenNest.Engine/Strategies/FillContext.cs b/OpenNest.Engine/Strategies/FillContext.cs index ab56dac..3e4c0b2 100644 --- a/OpenNest.Engine/Strategies/FillContext.cs +++ b/OpenNest.Engine/Strategies/FillContext.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Threading; using OpenNest.Engine; using OpenNest.Engine.Fill; +using OpenNest.Engine.Jobs.Placement.Fillers; using OpenNest.Geometry; namespace OpenNest.Engine.Strategies @@ -50,7 +51,7 @@ namespace OpenNest.Engine.Strategies WinnerPhase = ActivePhase; } - NestEngineBase.ReportProgress( + NestProgressReporter.Report( Progress, new ProgressReport {