The equivalent of %
for floating point numbers is truncatingRemainder
, and it handles negative values pretty well!
You can use this function to normalize an angle:
extension Angle {
/// Returns an Angle in the range `0° ..< 360°`
func normalized() -> Angle {
var degrees = self.degrees.truncatingRemainder(dividingBy: 360)
if degrees < 0 {
degrees = degrees + 360
}
return Angle(degrees: degrees)
}
}
If you want to normalize it in the range -180° ..< 180°
, consider adding this extension too:
extension Angle {
/// Returns an Angle in the range `-180° ..< 180°` by mapping `180° ..< 360°` to `-180° ..< 0°`
func normalizedDelta() -> Angle {
var normalized = normalized()
if normalized >= Angle(degrees: 180) {
normalized = normalized - Angle(degrees: 360)
}
return normalized
}
}
These functions have the properties:
Angle(degrees: -1081).normalized().degrees == 359
Angle(degrees: -721).normalized().degrees == 359
Angle(degrees: -361).normalized().degrees == 359
Angle(degrees: -1).normalized().degrees == 359
Angle(degrees: 0).normalized().degrees == 0
Angle(degrees: 359.9).normalized().degrees == 359.9
Angle(degrees: 360).normalized().degrees == 0
Angle(degrees: 361).normalized().degrees == 1
Angle(degrees: 720).normalized().degrees == 0
Angle(degrees: 721).normalized().degrees == 1
Angle(degrees: 1081).normalized().degrees == 1
Angle(degrees: -1081).normalizedDelta().degrees // == -1
Angle(degrees: -721).normalizedDelta().degrees // == -1
Angle(degrees: -361).normalizedDelta().degrees // == -1
Angle(degrees: -1).normalizedDelta().degrees // == -1
Angle(degrees: 0).normalizedDelta().degrees == 0
Angle(degrees: 359.9).normalizedDelta().degrees // == -0.1
Angle(degrees: 360).normalizedDelta().degrees == 0
Angle(degrees: 361).normalizedDelta().degrees == 1
Angle(degrees: 720).normalizedDelta().degrees == 0
Angle(degrees: 721).normalizedDelta().degrees == 1
Angle(degrees: 1081).normalizedDelta().degrees == 1