diff --git a/OpenNest.Engine/Nfp/INestOptimizer.cs b/OpenNest.Engine/Nfp/INestOptimizer.cs
index cad4304..2664d98 100644
--- a/OpenNest.Engine/Nfp/INestOptimizer.cs
+++ b/OpenNest.Engine/Nfp/INestOptimizer.cs
@@ -1,5 +1,6 @@
using OpenNest.Engine.Fill;
using OpenNest.Geometry;
+using System;
using System.Collections.Generic;
using System.Threading;
@@ -11,9 +12,9 @@ namespace OpenNest.Engine.Nfp
public class OptimizationResult
{
///
- /// The best sequence found: (drawingId, rotation, drawing) tuples in placement order.
+ /// The best placement sequence found.
///
- public List<(int drawingId, double rotation, Drawing drawing)> Sequence { get; set; }
+ public List Sequence { get; set; }
///
/// The score achieved by the best sequence.
@@ -34,6 +35,7 @@ namespace OpenNest.Engine.Nfp
{
OptimizationResult Optimize(List items, Box workArea, NfpCache cache,
Dictionary> candidateRotations,
+ IProgress progress = null,
CancellationToken cancellation = default);
}
}
diff --git a/OpenNest.Engine/Nfp/NfpCache.cs b/OpenNest.Engine/Nfp/NfpCache.cs
index 90076b2..8f6a553 100644
--- a/OpenNest.Engine/Nfp/NfpCache.cs
+++ b/OpenNest.Engine/Nfp/NfpCache.cs
@@ -14,6 +14,8 @@ namespace OpenNest.Engine.Nfp
private readonly Dictionary cache = new Dictionary();
private readonly Dictionary> polygonCache
= new Dictionary>();
+ private readonly Dictionary<(int drawingId, double rotation), Polygon> ifpCache
+ = new Dictionary<(int drawingId, double rotation), Polygon>();
///
/// Registers a pre-computed polygon for a drawing at a specific rotation.
@@ -28,6 +30,26 @@ namespace OpenNest.Engine.Nfp
}
rotations[rotation] = polygon;
+
+ // Clear IFP cache if a polygon is updated (though usually they aren't).
+ ifpCache.Remove((drawingId, rotation));
+ }
+
+ ///
+ /// Gets or computes the IFP for a drawing at a specific rotation within a work area.
+ ///
+ public Polygon GetIfp(int drawingId, double rotation, Box workArea)
+ {
+ if (ifpCache.TryGetValue((drawingId, rotation), out var ifp))
+ return ifp;
+
+ var polygon = GetPolygon(drawingId, rotation);
+ if (polygon == null)
+ return new Polygon();
+
+ ifp = InnerFitPolygon.Compute(workArea, polygon);
+ ifpCache[(drawingId, rotation)] = ifp;
+ return ifp;
}
///
diff --git a/OpenNest.Engine/Nfp/PlacedPart.cs b/OpenNest.Engine/Nfp/PlacedPart.cs
new file mode 100644
index 0000000..a32fc49
--- /dev/null
+++ b/OpenNest.Engine/Nfp/PlacedPart.cs
@@ -0,0 +1,15 @@
+using OpenNest.Geometry;
+
+namespace OpenNest.Engine.Nfp
+{
+ ///
+ /// Represents a part that has been placed by the BLF algorithm.
+ ///
+ public class PlacedPart
+ {
+ public int DrawingId { get; set; }
+ public double Rotation { get; set; }
+ public Vector Position { get; set; }
+ public Drawing Drawing { get; set; }
+ }
+}
diff --git a/OpenNest.Engine/Nfp/SequenceEntry.cs b/OpenNest.Engine/Nfp/SequenceEntry.cs
new file mode 100644
index 0000000..1cc6091
--- /dev/null
+++ b/OpenNest.Engine/Nfp/SequenceEntry.cs
@@ -0,0 +1,24 @@
+namespace OpenNest.Engine.Nfp
+{
+ ///
+ /// An entry in a placement sequence — identifies which drawing to place and at what rotation.
+ ///
+ public readonly struct SequenceEntry
+ {
+ public int DrawingId { get; }
+ public double Rotation { get; }
+ public Drawing Drawing { get; }
+
+ public SequenceEntry(int drawingId, double rotation, Drawing drawing)
+ {
+ DrawingId = drawingId;
+ Rotation = rotation;
+ Drawing = drawing;
+ }
+
+ public SequenceEntry WithRotation(double rotation)
+ {
+ return new SequenceEntry(DrawingId, rotation, Drawing);
+ }
+ }
+}