如何将角度转换为弧度?

117

我正在尝试将这段Obj-C代码转换为Swift代码,但我不知道这段代码的等效物是什么?

#define DEGREES_TO_RADIANS(degrees)((M_PI * degrees)/180)

我谷歌搜索并发现这里

但我不理解如何将它在我的情况下转换为Swift?


我认为你缺少一些代码。你能添加所有相关的代码吗?还有其他的定义,比如度数吗? - BlackHatSamurai
这是我的 Swift 代码:http://pastebin.com/bZ4a7EVN - Dharmesh Kheni
你能给我看一下你的.h文件吗? - BlackHatSamurai
这是一个宏。你需要一个函数。 - gnasher729
1
ultratip ... https://dev59.com/Fojca4cB1Zd3GeqPqQH3#28600210 - Fattie
10个回答

285

Xcode 11 • Swift 5.1 或更高版本

extension BinaryInteger {
    var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
}

extension FloatingPoint {
    var degreesToRadians: Self { self * .pi / 180 }
    var radiansToDegrees: Self { self * 180 / .pi }
}

游乐场

45.degreesToRadians         // 0.7853981633974483

Int(45).degreesToRadians    // 0.7853981633974483
Int8(45).degreesToRadians   // 0.7853981633974483
Int16(45).degreesToRadians  // 0.7853981633974483
Int32(45).degreesToRadians  // 0.7853981633974483
Int64(45).degreesToRadians  // 0.7853981633974483

UInt(45).degreesToRadians   // 0.7853981633974483
UInt8(45).degreesToRadians  // 0.7853981633974483
UInt16(45).degreesToRadians // 0.7853981633974483
UInt32(45).degreesToRadians // 0.7853981633974483
UInt64(45).degreesToRadians // 0.7853981633974483

Double(45).degreesToRadians    // 0.7853981633974483
CGFloat(45).degreesToRadians   // 0.7853981633974483
Float(45).degreesToRadians     // 0.7853981
Float80(45).degreesToRadians   // 0.78539816339744830963

如果你想让二进制整数返回浮点类型而不是始终返回CGFloat,你可以创建一个通用方法而不是计算属性:

extension BinaryInteger {
    func degreesToRadians<F: FloatingPoint>() -> F {  F(self) * .pi / 180 }
}

let radiansDouble: Double = 45.degreesToRadians()   // 0.7853981633974483
let radiansCGFloat: CGFloat = 45.degreesToRadians() // 0.7853981633974483
let radiansFloat: Float = 45.degreesToRadians()     // 0.7853981
let radiansFloat80: Float80 = 45.degreesToRadians() // 0.78539816339744830963

5
你应该扩展 CGFloat 吗? - Zorayr
2
@Zorayr 已更新到 Swift 3,并扩展了 FloatingPoint,现在它们都被扩展了。 - Leo Dabus
3
实际上,在Swift 3中,您可以使用度量类型,而无需了解任何转换公式! - matt
3
注意:这个超级专业技巧... https://dev59.com/Fojca4cB1Zd3GeqPqQH3#28600210 - Fattie
2
没有理由地投反对票是毫无意义的。请发表评论。 - Leo Dabus
显示剩余2条评论

73

这并不是你所问的完全一样,但在Swift 3 / iOS 10中,您可以使用Measurement类型,在不知道公式的情况下进行转换!

let result = Measurement(value: 45, unit: UnitAngle.degrees)
    .converted(to: .radians).value

5
感谢 @matt 的出色工作!不过很遗憾,只支持iOS 10。 - meaning-matters
有趣的事情是,以下代码中的两个变量值将不同:let radians = CGFloat(30.3 * .pi / 180.0)let radians2 = Measurement(value: 30.3, unit: UnitAngle.degrees) .converted(to: .radians).value它们分别为0.5288347633542818和0.5288345742619878。 - Zaporozhchenko Oleksandr
"“Measurement” 仅适用于 iOS 10.0 或更高版本" - Zaporozhchenko Oleksandr

43

苹果提供这些 GLKit函数 来进行转换:

func GLKMathDegreesToRadians(_ degrees: Float) -> Float
func GLKMathRadiansToDegrees(_ radians: Float) -> Float

1
GLKit即将退出舞台,因为现在是Metal的世界了,再见GL。当将iPad应用程序移植到Mac时,GLKit不再受支持! - Juguang

19
let angle = 45° // angle will be in radians, 45 is in degrees

支持 Swift 3 编译。仍然保留所有值,使用 CGFloats 进行弧度计算...,但使用角度常量使代码更易读。例如:90° 符号°将自动进行度数到弧度的转换。

如何设置:

定义并使用后缀操作符来处理° 符号。该操作符将把角度转换为弧度。 此示例适用于 Int 类型,如果需要,也可以扩展为 Float 类型。

postfix operator °

protocol IntegerInitializable: ExpressibleByIntegerLiteral {
  init (_: Int)
}

extension Int: IntegerInitializable {
  postfix public static func °(lhs: Int) -> CGFloat {
    return CGFloat(lhs) * .pi / 180
  }
}

使用示例:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

let angle = 45
contentView.transform = CGAffineTransform(rotationAngle: angle°)

警告!

使用此转换两次(错误地对已经在弧度中的值进行转换),会导致结果非常小,表现为所得角度始终为零... 不要对同一个值使用°进行两次转换(不要重复转换)!!:

// OBVIOUSLY WRONG!
let angle = 45°° // ° used twice here

// WRONG! BUT EASY TO MISS
let angle = 45° // ° used here
contentView.transform = CGAffineTransform(rotationAngle: angle°) // ° also used here

IntegerInitializable protocol is pointless. Int already conforms to ExpressibleByIntegerLiteral - Leo Dabus
顺便提一句,您可以将此操作符通用化以支持任何整数,并且还可以返回任何浮点数。public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } } - Leo Dabus
在创建通用方法时,如果编译器无法推断出结果类型,则需要显式设置结果类型,例如 let angle: CGFloat = 45°。但是,在期望 CGFloat 或任何 FloatingPoint 类型的情况下,不需要这样做,例如 CGAffineTransform(rotationAngle: 45°) - Leo Dabus

12

另外,如果有人在谷歌上看到这篇文章并想要将弧度转换为角度,请使用以下公式:

var degrees = radians * (180.0 / M_PI)

5

将 Double 类型的角度值和弧度值之间进行转换的最高效和准确的方法:

import Foundation

extension Double {
    var radians: Double { return Measurement(value: self, unit: UnitAngle.degrees).converted(to: UnitAngle.radians).value }
    var degrees: Double { return Measurement(value: self, unit: UnitAngle.radians).converted(to: UnitAngle.degrees).value }
}

苹果的Foundation团队早在很久以前就开发出了一种解决方案,超越了其他所有方案:

测量和单位- WWDC 2016,第238节


3

现在创建变量名称时不再受限于ASCII字符,那么使用π(alt-p)如何:

typealias RadianAngle = CGFloat

let π = RadianAngle(M_PI)
let π_x_2 = RadianAngle(M_PI * 2)
let π_2 = RadianAngle(M_PI_2)
let π_4 = RadianAngle(M_PI_4)

extension RadianAngle {
    var degrees: CGFloat {
        return self * 180 / π
    }
    init(degrees: Int) {
        self = CGFloat(degrees) * π / 180
    }
}

使用示例:

let quarterCircle = RadianAngle(degrees: 90)
print("quarter circle = \(quarterCircle) radians")
// quarter circle = 1.5707963267949 radians

let halfCircle = π
print("half circle = \(halfCircle.degrees) degrees")
// half circle = 180.0 degrees

2

Swift 4.2

You can write global generic functions:

public func radians<T: FloatingPoint>(degrees: T) -> T {
    return .pi * degrees / 180
}

public func degrees<T: FloatingPoint>(radians: T) -> T {
    return radians * 180 / .pi
}

例子:

let cgFloat: CGFloat = 23.0
let double: Double = 23.0
let float: Float = 23.0
let int: Int = 23

let cgf = radians(degrees: cgFloat) // 0.4014 CGFloat
let d = radians(degrees: double)    // 0.4014 Double
let f = radians(degrees: float)     // 0.4014 Float
let i = radians(degrees: int)       // compile error

最初的回答:如果您不想这样扩展所有浮动类型
extension FloatingPoint { ... }

@LeoDabus 因为 TFloatingPoint 类型而 180 是 Int 类型。在 Swift 中,您不能对不同类型进行计算。 - Tikhonov Aleksandr
你错了。Swift 可以推断类型。它的行为与扩展 FloatingPoint 类型完全相同。180 可以是任何东西,不一定是 Int。 - Leo Dabus
同样适用于您的.pi,您不需要调用T.pi,因为编译器知道您正在返回T,因此它推断.piT上的静态属性(在这种情况下表示FloatingPoint)。 - Leo Dabus
1
FloatingPoint符合ExpressibleByIntegerLiteral,这就是为什么你可以在那里写180的原因。 - Leo Dabus
1
180.0需要T,因为T不一定是Double类型。它可以是任何浮点类型。您可以从您的double 180.0初始化一个新的T。 - Leo Dabus
显示剩余6条评论

1

如果可以导入SwiftUI,或者你已经在使用它,那么你可以使用Angle类型来在角度单位之间进行转换,例如:

import SwiftUI

let radians = Angle(degrees: 45).radians

这将从 Double 转换为 Double


1
我会使用@t1ser上面提到的相同原理,但是创建一个CGFloat的扩展,以便更容易地使用小数表示度数(例如,您可以有23.4度):
extension CGFloat {
    func degrees() -> CGFloat {
        return self * .pi / 180
    }

    init(degrees: CGFloat) {
        self = degrees.degrees()
    }
}

使用它也很容易 (主要是因为我个人不知道如何输入° - 如果你也不知道,那么输入方式是option+shift+8):
let degreesToConvert: CGFloat = 45.7
.
.
.
let convertedDegrees = degreesToConvert.degrees()

或者使用初始化器:

let convertedDegrees = CGFloat(degrees: 45.3)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接