     func _verticalOffset(forGridPosition gridPosition: CGFloat) -> CGFloat {
         return (self.gridInsetFactor + gridPosition) * self.rowHeight
     }
-}
+    
+    // Private Helpers
+    func _locationOffset(nearestToOffset offset: CGFloat, minLocation: CGFloat, maxLocation: CGFloat, stepUnit: CGFloat) -> CGFloat {
+        if offset <= minLocation {
+            return minLocation
+        } else if offset >= maxLocation {
+            return maxLocation
+        } else {
+            let stepSize: CGFloat = self.subdivision.rawValue * stepUnit
+            return (round((offset - minLocation) / stepSize) * stepSize) + minLocation
+        }
+    }
+}

// MARK: Point <-> Location <-> SlotIndex Calculation
private extension GridLayer {
    func _point(for location: GridLayer.Location) -> CGPoint {
        return .zero
    }
    
    func _location(nearestTo point: CGPoint) -> GridLayer.Location {
        return (0, 0)
    }
    
    func _point(for slotIndex: UInt) -> CGPoint {
        return .zero
    }
    
    // Helpers

// MARK: Interface
public extension GridLayer {
    // MARK: Location
    public typealias Location = (row: CGFloat, column: CGFloat)
    
    public enum Subdivision: CGFloat {
        case none = 1.0
