diff --git a/OpenNest.Engine/NestEngine.cs b/OpenNest.Engine/NestEngine.cs index c934aad..5092bc3 100644 --- a/OpenNest.Engine/NestEngine.cs +++ b/OpenNest.Engine/NestEngine.cs @@ -5,6 +5,7 @@ using System.Linq; using System.Threading; using OpenNest.Converters; using OpenNest.Engine.BestFit; +using OpenNest.Engine.ML; using OpenNest.Geometry; using OpenNest.Math; using OpenNest.RectanglePacking; @@ -129,6 +130,32 @@ namespace OpenNest } } + // When the work area triggers a full sweep (and we're not forcing it for training), + // try ML angle prediction to reduce the sweep. + if (!ForceFullAngleSweep && angles.Count > 2) + { + var features = FeatureExtractor.Extract(item.Drawing); + if (features != null) + { + var predicted = AnglePredictor.PredictAngles( + features, workArea.Width, workArea.Length); + + if (predicted != null) + { + // Use predicted angles, but always keep bestRotation and bestRotation + 90. + var mlAngles = new List(predicted); + + if (!mlAngles.Any(a => a.IsEqualTo(bestRotation))) + mlAngles.Add(bestRotation); + if (!mlAngles.Any(a => a.IsEqualTo(bestRotation + Angle.HalfPI))) + mlAngles.Add(bestRotation + Angle.HalfPI); + + Debug.WriteLine($"[FindBestFill] ML: {angles.Count} angles -> {mlAngles.Count} predicted"); + angles = mlAngles; + } + } + } + // Try pair-based approach first. var pairResult = FillWithPairs(item, workArea); var best = pairResult; @@ -214,6 +241,32 @@ namespace OpenNest } } + // When the work area triggers a full sweep (and we're not forcing it for training), + // try ML angle prediction to reduce the sweep. + if (!ForceFullAngleSweep && angles.Count > 2) + { + var features = FeatureExtractor.Extract(item.Drawing); + if (features != null) + { + var predicted = AnglePredictor.PredictAngles( + features, workArea.Width, workArea.Length); + + if (predicted != null) + { + // Use predicted angles, but always keep bestRotation and bestRotation + 90. + var mlAngles = new List(predicted); + + if (!mlAngles.Any(a => a.IsEqualTo(bestRotation))) + mlAngles.Add(bestRotation); + if (!mlAngles.Any(a => a.IsEqualTo(bestRotation + Angle.HalfPI))) + mlAngles.Add(bestRotation + Angle.HalfPI); + + Debug.WriteLine($"[FindBestFill] ML: {angles.Count} angles -> {mlAngles.Count} predicted"); + angles = mlAngles; + } + } + } + // Pairs phase first var pairSw = Stopwatch.StartNew(); var pairResult = FillWithPairs(item, workArea, token, progress);