Як я можу перетворити з градусів на радіани?


107

Я намагаюся перетворити цей Obj-Cкод у Swiftкод, але я не знаю, яким повинен бути еквівалент цього коду?

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

Я гуглив і знайшов це

Але я не розумію, як перетворити це в Swift в моєму випадку?


Я думаю, вам не вистачає якогось коду. Чи можете ви всі додати відповідний код? Будь-яке інше визначає, як градуси?
BlackHatSamurai

це мій стрімкий код: pastebin.com/bZ4a7EVN
Dharmesh Kheni

Ви можете мені показати вам .h файл?
BlackHatSamurai

Це макрос. Ви хочете функцію.
gnasher729

Відповіді:


267

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

4
Ви не повинні продовжувати CGFloat?
Зорайр

1
@Zorayr оновлено до Swift 3, а FloatingPoint тепер поширює їх усіх
Лео Дабус

3
Насправді, у Swift 3 ви можете використовувати типи вимірювань, і вам зовсім не потрібно знати формулу перетворення!
мат

3
ПРИМІТКА, ЯКЩО цей суперпровід… stackoverflow.com/a/28600210/294884
Fattie

1
Голосування без причини не має сенсу. Залиште коментар
Лев Дабус

63

Це ідентично не те, що ви запитували, але в Swift 3 / iOS 10 ви можете використовувати тип Measurement і робити перетворення, не знаючи формули!

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

4
Дивовижний @matt на роботі знову, дякую! На жаль, тільки iOS 10.
значення-питання

цікава річ, що нехай радіани = CGFloat (30,3 * .pi / 180,0) нехай radians2 = вимірювання (значення: 30,3, одиниця: UnitAngle.degrees) .конвертовано (в: .radians). значення буде іншим: 0,5288347633542818 та 0,5288345742619878
Запорожченко Олександр

і впевнений, що "Вимірювання" доступне лише для iOS 10.0 або новіших "
Олександр

42

Apple надає такі функції GLKit для перетворення:

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

GLKit скоро вийде зі сцени, оскільки зараз це світ металу, до побачення GL. Як перенесення програми iPad на Mac, GLKit більше не підтримується !.
Джугуанг

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

Компіляції під Swift 3 . Все ж зберігайте всі значення, робіть усі обчислення в радіанах із CGFloats ..., але зробіть код більш читабельним із константами в градусах. Наприклад: 90 ° Знак ° магічним чином зробить градуси до перетворення радіанів.

Як це налаштувати:

Визначте та використовуйте оператор постфікса для знака ° . Цей оператор здійснить перетворення градусів на радіани. Цей приклад для Ints, поширюйте їх також на типи 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протокол безглуздо. Int вже відповідаєExpressibleByIntegerLiteral
Лев Дабус

Btw Ви можете зробити цей оператор загальним для підтримки будь-якого цілого числа та повернення будь-якої плаваючої точки. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Лев Дабус

І перш ніж прокоментувати це під час створення загального методу, вам потрібно буде чітко встановити результат, якщо компілятор не зможе зробити висновок про отриманий тип let angle: CGFloat = 45°. Але він не потрібен там, де він очікує того CGFloatчи іншого FloatingPointтипуCGAffineTransform(rotationAngle: 45°)
Лев Дабус

11

Крім того, для перетворення фронтальних радіанів в градуси (якщо хтось натрапляє на це в Google):

var degrees = radians * (180.0 / M_PI)

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

Швидкий 4.2

Ви можете записати загальні загальні функції:

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 { ... }

Чому б не просто return .pi * degrees / 180?
Лев Дабус

@LeoDabus тому, що Tце FloatingPointтип і 180 - це Intтип. Швидко не можна робити розрахунки для різних типів.
Тихонов Олександр

Ви неправі. Швидкий може визначити тип. Він поводиться точно так само, як якщо б ви розширювали тип FloatingPoint. 180 може бути будь-якою річчю. необов'язково Int
Лев Дабус

1
Плаваючий
Point

1
180,0 потребує T, оскільки T не обов'язково є подвійним. Це може бути будь-який тип з плаваючою точкою. Ви ініціалізуєте нову зі своєї подвійної
180.0

1

Я б використовував той самий принцип @ t1ser, згаданий вище, але створити розширення, CGFloatщоб полегшити використання десяткових знаків і для ступеня (щоб у вас була, наприклад, 23,4 градуса):

extension CGFloat {
    func degrees() -> CGFloat {
        return self * .pi / 180
    }

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

Також це було б досить просто (головним чином тому, що я особисто не знав, як ввести ° 😜 - якщо ви цього не зробили, це option+shift+8btw):

let degreesToConvert: CGFloat = 45.7
.
.
.
let convertedDegrees = degreesToConvert.degrees()

Або використовувати ініціалізатор:

let convertedDegrees = CGFloat(degrees: 45.3)

-5

стрімкий 2.3

func  kilometersBetween(Place1:CLLocationCoordinate2D , Place2:CLLocationCoordinate2D) -> Double{
    var start = MKMapPointForCoordinate(Place1)
    var finish = MKMapPointForCoordinate(Place2)
    print(MKMetersBetweenMapPoints(start, finish) / 1000)
    return MKMetersBetweenMapPoints(start, finish) / 1000
} 

1
Хоча цей код може відповісти на питання, надаючи додатковий контекст щодо того, як та / або чому він вирішує проблему, покращить довгострокове значення відповіді.
Nic3500
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.