Clamping a value is an operation of moving the value to a range of allowed values. It can be achieved by comparing the value with allowed minimum and maximum values.

For example I was deforming SKWarpGeometryGrid from the direction of a point outside the grid and needed to constrain angles between grid points and the contact point. Maximum and minimum allowed angles were related to the angle between the contact point and the grid’s center point.

The solution I propose extends FloatingPoint and BinaryInteger protocols and gives a very readable form to this example problem:

let angleToCenter: CGFloat = .pi / 5 | |

let angleToGridPoint: CGFloat = .pi / 3 | |

// 1.0471975511966 | |

let allowedRange = (angleToCenter - .pi / 8)...(angleToCenter + .pi / 8) | |

let angle = angleToGridPoint.clamped(to: allowedRange) | |

// 1.02101761241668 |

### Extending FloatingPoint protocol

extension FloatingPoint { | |

func clamped(to range: ClosedRange<Self>) -> Self { | |

return max(min(self, range.upperBound), range.lowerBound) | |

} | |

} | |

let clamped = 5.4.clamped(to: 5.6...6.1) | |

let clamped = 10.5.clamped(to: 5...7) |

### Extending BinaryInteger protocol

extension BinaryInteger { | |

func clamped(to range: ClosedRange<Self>) -> Self { | |

return max(min(self, range.upperBound), range.lowerBound) | |

} | |

} | |

let clamped = 10.clamped(to: 5...7) |