将角度归一化到 0 到 360 度的范围?
Normalizing an Angle to the range 0 to 360 degrees?
我们在 SwiftUI 中有 Angle 数据类型。这可以存储从 -infinity 到 +infinity 的度数或弧度值。
我想将角度转换为 0 到 360 之间的值。例如通过使用 wrap around mod:
等方法
func normalize(_ angle: Angle) -> Angle {
wrapAroundMod(angle.degrees, 360.0)
}
但是,wrapAroundMod
不是内置函数,不支持浮点数。我正在努力想出一个没有一堆分支逻辑的优雅解决方案。
是否有一种优雅的方法来归一化角度?
浮点数的 %
等价于 truncatingRemainder
,它可以很好地处理负值!
您可以使用此函数对角度进行归一化:
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)
}
}
如果您想在 -180° ..< 180°
范围内对其进行归一化,也可以考虑添加此扩展名:
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
}
}
这些函数具有以下属性:
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
优雅是见仁见智...
您可以通过使用 truncatingRemainder(dividingBy:)
:
的两个应用程序在不使用分支的情况下完成此操作
extension Angle {
/// Returns an Angle in the range `0° ..< 360°`
func normalized() -> Angle {
let degrees = (self.degrees.truncatingRemainder(dividingBy: 360) + 360)
.truncatingRemainder(dividingBy: 360)
return Angle(degrees: degrees)
}
}
我们在 SwiftUI 中有 Angle 数据类型。这可以存储从 -infinity 到 +infinity 的度数或弧度值。
我想将角度转换为 0 到 360 之间的值。例如通过使用 wrap around mod:
等方法func normalize(_ angle: Angle) -> Angle {
wrapAroundMod(angle.degrees, 360.0)
}
但是,wrapAroundMod
不是内置函数,不支持浮点数。我正在努力想出一个没有一堆分支逻辑的优雅解决方案。
是否有一种优雅的方法来归一化角度?
浮点数的 %
等价于 truncatingRemainder
,它可以很好地处理负值!
您可以使用此函数对角度进行归一化:
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)
}
}
如果您想在 -180° ..< 180°
范围内对其进行归一化,也可以考虑添加此扩展名:
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
}
}
这些函数具有以下属性:
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
优雅是见仁见智...
您可以通过使用 truncatingRemainder(dividingBy:)
:
extension Angle {
/// Returns an Angle in the range `0° ..< 360°`
func normalized() -> Angle {
let degrees = (self.degrees.truncatingRemainder(dividingBy: 360) + 360)
.truncatingRemainder(dividingBy: 360)
return Angle(degrees: degrees)
}
}