Clamping numbers in Swift

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
view raw Clamp.swift hosted with ❤ by GitHub

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)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s