diff --git a/OpenNest.Core/Plate.cs b/OpenNest.Core/Plate.cs
index e024bbb3..2c96dbbf 100644
--- a/OpenNest.Core/Plate.cs
+++ b/OpenNest.Core/Plate.cs
@@ -155,11 +155,16 @@ namespace OpenNest
///
/// Minutes this sheet's cut-time estimate gains from (D9):
- /// each listed clamp adds once. Zero
- /// when there is no rail (removal is meaningless without one to remove clamps from).
+ /// each listed clamp the rail places on this sheet adds
+ /// once; a listed clamp that is beyond
+ /// the sheet (or unknown to the rail) is not pulled and costs nothing. Zero when there
+ /// is no rail (removal is meaningless without one to remove clamps from).
///
public double ClampRemovalMinutes =>
- ClampRail == null ? 0 : RemovedClamps.Count * ClampRail.RemovalMinutes;
+ ClampRail == null || RemovedClamps.Count == 0
+ ? 0
+ : ClampRail.ResolveFor(Size, Quadrant).Count(zone => RemovedClamps.Contains(zone.Id))
+ * ClampRail.RemovalMinutes;
///
/// Follows and replaces the zones with its resolution for
diff --git a/OpenNest.Tests/ClampRailTests.cs b/OpenNest.Tests/ClampRailTests.cs
index 2ff4b218..bf04204b 100644
--- a/OpenNest.Tests/ClampRailTests.cs
+++ b/OpenNest.Tests/ClampRailTests.cs
@@ -370,4 +370,16 @@ public class ClampRailTests
Assert.False(Machine().Matches(plate, Array.Empty()));
Assert.False(Machine().Matches(plate, new[] { "clamp-4" }));
}
+ // PM 6ded8ac4 (a): only removed clamps that are actually on this sheet cost time.
+ [Fact]
+ public void RemovalTimeCountsOnlyRemovedClampsOnTheSheet()
+ {
+ var plate = Sheet(48, 120);
+ plate.SetClampRail(Machine(), new[] { "clamp-3", "clamp-8", "clamp-99" });
+ Assert.Equal(2 * ClampRail.DefaultRemovalMinutes, plate.ClampRemovalMinutes); // 3 and 8
+
+ plate.Size = new Size(48, 60); // clamp-8 is now beyond the sheet
+ Assert.Equal(ClampRail.DefaultRemovalMinutes, plate.ClampRemovalMinutes);
+ Assert.Contains("clamp-8", plate.RemovedClamps); // still listed (C13)
+ }
}