Come posso convertire da gradi a radianti?


107

Sto provando a convertire questo Obj-Ccodice in Swiftcodice ma non so quale dovrebbe essere l'equivalente di questo codice?

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

Ho cercato su Google e ho trovato questo

Ma non capisco come convertirlo in Swift nel mio caso?


Penso che ti manchi del codice. Potete tutti aggiungere tutto il codice pertinente? Qualche altra definizione, come i gradi?
— BlackHatSamurai

questo è il mio codice SWIFT: pastebin.com/bZ4a7EVN
— Dharmesh Kheni

Puoi mostrarmi il tuo file .h?
— BlackHatSamurai

È una macro. Vuoi una funzione.
— gnasher729

Risposte:


267

Xcode 11 • Swift 5.1 o successivo

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

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

Terreno di gioco

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

Se desideri che il numero intero binario restituisca un tipo a virgola mobile invece di restituire sempre un CGFloat, puoi creare un metodo generico invece di una proprietà calcolata:

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
Non dovresti estendere CGFloat?
— Zorayr

1
@Zorayr aggiornato a Swift 3 e l'estensione FloatingPoint ora li estende tutti
— Leo Dabus,

3
In realtà, in Swift 3 puoi utilizzare i tipi di misurazione e non è necessario conoscere affatto la formula di conversione!
— opaco

3
Si noti tuttavia questo suggerimento superpro ... stackoverflow.com/a/28600210/294884
— Fattie

1
Votare senza motivo non ha alcun senso. Pubblica un commento
— Leo Dabus

63

Questo non è esattamente quello che hai chiesto, ma in Swift 3 / iOS 10 puoi utilizzare il tipo di misurazione ed eseguire la conversione senza conoscere la formula!

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

4
Incredibile @matt di nuovo al lavoro, grazie! Sfortunatamente solo iOS 10.
— significato conta il

cosa interessante che lascia radianti = CGFloat (30.3 * .pi / 180.0) let radians2 = Measurement (valore: 30.3, unità: UnitAngle.degrees) .converted (to: .radians) .value sarà diverso: 0.5288347633542818 e 0.5288345742619878
— Zaporozhchenko Oleksandr

e certo "'Misurazione' è disponibile solo su iOS 10.0 o più recente"
— Zaporozhchenko Oleksandr

42

Apple fornisce queste funzioni GLKit per la conversione:

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

GLKit uscirà presto dal palco, dato che ora è il mondo del Metal, ciao GL. Come porting di app per iPad su Mac, GLKit non è più supportato !.
— Juguang

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

Viene compilato in Swift 3 . Conserva ancora tutti i valori, esegui tutti i calcoli in radianti con CGFloats ..., ma rendi il codice più leggibile con le costanti in gradi. Ad esempio: 90 ° Il segno ° eseguirà magicamente la conversione da gradi a radianti.

Come impostarlo:

Definisci e utilizza un operatore suffisso per il segno ° . Questo operatore eseguirà la conversione da gradi a radianti. Questo esempio è per Ints, estendili anche per i tipi Float se ne hai bisogno.

postfix operator °

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

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

Alcuni esempi di utilizzo:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Avvertimento!

È troppo facile usare questa conversione due volte (su un valore già in radianti per errore), otterrai un numero molto piccolo come risultato, e apparentemente l'angolo risultante sarà sempre zero ... NON usare ° sullo stesso valore due volte (non convertire due volte) !!:

// 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

IntegerInitializableil protocollo è inutile. Int è già conforme aExpressibleByIntegerLiteral
— Leo Dabus

Btw Puoi rendere questo operatore generico per supportare qualsiasi numero intero e restituire anche qualsiasi virgola mobile. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
— Leo Dabus

E prima di commentarlo quando si crea un metodo generico, è necessario impostare esplicitamente il tipo risultante se il compilatore non può dedurre il tipo risultante let angle: CGFloat = 45°. Ma non è necessario dove si aspetta un CGFloato qualsiasi FloatingPointtipoCGAffineTransform(rotationAngle: 45°)
— Leo Dabus

11

Inoltre, per convertire i radianti fron in gradi (se qualcuno si imbatte in questo su google):

var degrees = radians * (180.0 / M_PI)

3

Non sei più limitato ai caratteri ASCII quando crei nomi di variabili, quindi che ne dici di usare π (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
    }
}

Utilizzo di esempio:

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

Puoi scrivere funzioni generiche globali:

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

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

Esempio:

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

Nel caso in cui non si desideri estendere tutti i tipi di floating in questo modo

extension FloatingPoint { ... }

Perché non semplicemente return .pi * degrees / 180?
— Leo Dabus

@LeoDabus perché Tè di FloatingPointtipo e 180 è di Inttipo. In swift non puoi fare calcoli su tipi diversi.
— Tikhonov Alexander

Tui hai torto. Swift può dedurre il tipo. Si comporta esattamente come se estendessi il tipo FloatingPoint. 180 può essere qualsiasi cosa. non necessariamente un Int
— Leo Dabus

1
FloatingPoint è conforme a ExpressibleByIntegerLiteral, ecco perché puoi scrivere 180 lì
— Leo Dabus

1
180.0 necessita di T perché T non è necessariamente un Double. Può essere Qualsiasi tipo a virgola mobile.
— Ne

1

Userei lo stesso principio @ t1ser menzionato sopra, ma creerei un'estensione di CGFloatper rendere più facile l'uso dei decimali anche per il grado (quindi potresti avere un 23,4 gradi, per esempio):

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

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

Anche usarlo sarebbe abbastanza facile (principalmente perché personalmente non sapevo come digitare ° 😜 - nel caso in cui non lo facessi, è option+shift+8btw):

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

O per usare l'inizializzatore:

let convertedDegrees = CGFloat(degrees: 45.3)

-5

swift 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
Sebbene questo codice possa rispondere alla domanda, fornire un contesto aggiuntivo su come e / o perché risolve il problema migliorerebbe il valore a lungo termine della risposta.
— Nic3500
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.