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.