diff --git a/OpenNest.Engine/FillLinear.cs b/OpenNest.Engine/FillLinear.cs
index 6a8fd37..458c9f9 100644
--- a/OpenNest.Engine/FillLinear.cs
+++ b/OpenNest.Engine/FillLinear.cs
@@ -85,8 +85,74 @@ namespace OpenNest
///
/// Finds the geometry-aware copy distance between two identical patterns along an axis.
+ /// Checks every pair of parts across adjacent patterns so that multi-part
+ /// patterns (e.g. interlocking pairs) maintain spacing between ALL parts.
///
private double FindPatternCopyDistance(Pattern patternA, NestDirection direction)
+ {
+ if (patternA.Parts.Count <= 1)
+ return FindSinglePartPatternCopyDistance(patternA, direction);
+
+ var bboxDim = GetDimension(patternA.BoundingBox, direction);
+ var pushDir = GetPushDirection(direction);
+ var opposite = Helper.OppositeDirection(pushDir);
+
+ // Compute a starting offset large enough that every part-pair in
+ // patternB has its offset geometry beyond patternA's raw geometry.
+ var startOffset = bboxDim;
+
+ foreach (var partA in patternA.Parts)
+ {
+ var aUpper = direction == NestDirection.Horizontal
+ ? partA.BoundingBox.Right : partA.BoundingBox.Top;
+
+ foreach (var refB in patternA.Parts)
+ {
+ var bLower = direction == NestDirection.Horizontal
+ ? refB.BoundingBox.Left : refB.BoundingBox.Bottom;
+
+ var required = aUpper - bLower + PartSpacing + Tolerance.Epsilon;
+
+ if (required > startOffset)
+ startOffset = required;
+ }
+ }
+
+ var patternB = patternA.Clone(MakeOffset(direction, startOffset));
+
+ var maxCopyDistance = 0.0;
+
+ foreach (var partB in patternB.Parts)
+ {
+ var movingLines = Helper.GetOffsetPartLines(partB, PartSpacing, pushDir);
+
+ foreach (var partA in patternA.Parts)
+ {
+ var stationaryLines = Helper.GetPartLines(partA, opposite);
+ var slideDistance = Helper.DirectionalDistance(movingLines, stationaryLines, pushDir);
+
+ if (slideDistance >= double.MaxValue || slideDistance < 0)
+ continue; // No geometric interaction — pair doesn't constrain distance.
+
+ var copyDist = startOffset - slideDistance;
+
+ if (copyDist > maxCopyDistance)
+ maxCopyDistance = copyDist;
+ }
+ }
+
+ // Fallback: if no pair interacted (shouldn't happen for real parts),
+ // use the simple bounding-box + spacing distance.
+ if (maxCopyDistance <= 0)
+ return bboxDim + PartSpacing;
+
+ return maxCopyDistance;
+ }
+
+ ///
+ /// Fast path for single-part patterns — no cross-part conflicts possible.
+ ///
+ private double FindSinglePartPatternCopyDistance(Pattern patternA, NestDirection direction)
{
var bboxDim = GetDimension(patternA.BoundingBox, direction);
var pushDir = GetPushDirection(direction);