Comment puis-je convertir des degrés en radians?

107

J'essaye de convertir ce Obj-Ccode en Swiftcode mais je ne sais pas quel devrait être l'équivalent de ce code?

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

J'ai cherché sur Google et j'ai trouvé ceci

Mais je ne comprends pas comment convertir cela en Swift dans mon cas?

Dharmesh Kheni
la source
Je pense qu'il vous manque du code. Pouvez-vous tous ajouter tout le code pertinent? Y a-t-il d'autres définitions, comme les degrés?
BlackHatSamurai
c'est mon code swift: pastebin.com/bZ4a7EVN
Dharmesh Kheni
Pouvez-vous me montrer votre fichier .h?
BlackHatSamurai
C'est une macro. Vous voulez une fonction.
gnasher729
1
ultratip ... stackoverflow.com/a/28600210/294884
Fattie

Réponses:

267

Xcode 11 • Swift 5.1 ou version ultérieure

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

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

Terrain de jeux

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

Si vous souhaitez que l'entier binaire renvoie un type à virgule flottante au lieu de toujours renvoyer un CGFloat, vous pouvez créer une méthode générique au lieu d'une propriété calculée:

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
Leo Dabus
la source
4
Ne devriez-vous pas prolonger CGFloat?
Zorayr
1
@Zorayr mis à jour vers Swift 3 et l'extension de FloatingPoint les étend désormais tous
Leo Dabus
3
En fait, dans Swift 3, vous pouvez utiliser les types de mesure et vous n'avez pas du tout besoin de connaître la formule de conversion!
mat
3
REMARQUE TOUTEFOIS cette astuce de superpro ... stackoverflow.com/a/28600210/294884
Fattie
1
Voter sans raison n'a aucun sens. Publier un commentaire
Leo Dabus
63

Ce n'est pas exactement ce que vous avez demandé, mais dans Swift 3 / iOS 10, vous pouvez utiliser le type Mesure et faire la conversion sans connaître la formule!

let result = Measurement(value: 45, unit: UnitAngle.degrees)
    .converted(to: .radians).value
mat
la source
4
Incroyable @matt au travail à nouveau, merci! Seulement iOS 10 malheureusement.
sens-questions
chose intéressante qui laisse radians = CGFloat (30.3 * .pi / 180.0) let radians2 = Measurement (value: 30.3, unit: UnitAngle.degrees) .converted (to: .radians) .value will be different: 0.5288347633542818 et 0.5288345742619878
Zaporozhchenko Oleksandr
et sûr que "'Measurement' est uniquement disponible sur iOS 10.0 ou plus récent"
Zaporozhchenko Oleksandr
42

Apple fournit ces fonctions GLKit pour la conversion:

func GLKMathDegreesToRadians(_ degrees: Float) -> Float
func GLKMathRadiansToDegrees(_ radians: Float) -> Float
Crashalot
la source
GLKit va bientôt quitter la scène, puisque maintenant c'est le monde du Metal, bye GL. En tant que portage de l'application iPad sur Mac, GLKit n'est plus pris en charge !.
Juguang
17
let angle = 45° // angle will be in radians, 45 is in degrees

Compile sous Swift 3 . Toujours garder toutes les valeurs, faire tous les calculs en radians avec CGFloats ..., mais rendre le code plus lisible avec les constantes en degrés. Par exemple: 90 ° Le signe ° fera comme par magie la conversion des degrés en radians.

Comment configurer cela:

Définissez et utilisez un opérateur postfix pour le signe ° . Cet opérateur effectuera la conversion des degrés en radians. Cet exemple est pour Ints, étendez-les également pour les types Float si vous en avez besoin.

postfix operator °

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

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

Quelques exemples d'utilisation:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Avertissement!

Il est trop facile d'utiliser cette conversion deux fois (sur une valeur déjà en radians par erreur), vous obtiendrez un très petit nombre comme résultat, et apparemment l'angle résultant sera toujours nul ... NE PAS utiliser ° sur le même valeur deux fois (ne pas convertir deux fois) !!:

// 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
t1ser
la source
IntegerInitializablele protocole est inutile. Int est déjà conforme àExpressibleByIntegerLiteral
Leo Dabus
Btw Vous pouvez rendre cet opérateur générique pour prendre en charge n'importe quel entier et renvoyer également n'importe quel virgule flottante. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus
Et avant de commenter lors de la création d'une méthode générique, vous devez définir explicitement le type résultant si le compilateur ne peut pas déduire le type résultant let angle: CGFloat = 45°. Mais il n'est pas nécessaire là où il attend un type CGFloatou n'importe quel FloatingPointtypeCGAffineTransform(rotationAngle: 45°)
Leo Dabus
11

Aussi, pour convertir des radians de fron en degrés (si quelqu'un tombe sur cela sur google):

var degrees = radians * (180.0 / M_PI)
Nikans
la source
3

Vous n'êtes plus limité aux caractères ASCII lors de la création de noms de variables, alors que diriez-vous de cela en utilisant π (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
    }
}

Exemple d'utilisation:

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
Ashley Mills
la source
2

Swift 4.2

Vous pouvez écrire des fonctions génériques globales:

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

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

Exemple:

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

Au cas où vous ne voudriez pas étendre tous vos types flottants comme celui-ci

extension FloatingPoint { ... }
Alexandre Tikhonov
la source
Pourquoi pas simplement return .pi * degrees / 180?
Leo Dabus
@LeoDabus parce que Tc'est du FloatingPointtype et 180 est du Inttype. Dans Swift, vous ne pouvez pas faire de calculs sur différents types.
Tikhonov Alexander
Vous avez tort. Swift peut déduire le type. Il se comporte exactement comme si vous étendiez le type FloatingPoint. 180 peut être n'importe quoi. pas nécessairement un Int
Leo Dabus
1
FloatingPoint est conforme à ExpressibleByIntegerLiteral c'est pourquoi vous pouvez y écrire 180
Leo Dabus
1
180.0 a besoin de T car T n'est pas nécessairement un Double. Il peut s'agir de tout type à virgule flottante. Vous en initialisez un nouveau à partir de votre double 180.0
Leo Dabus
1

J'utiliserais le même principe @ t1ser mentionné ci-dessus, mais créerais une extension de CGFloatpour faciliter l'utilisation des décimales pour le degré également (vous pouvez donc avoir 23,4 degrés, par exemple):

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

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

L'utiliser serait également assez facile (principalement parce que personnellement je ne savais pas comment taper ° 😜 - au cas où vous ne l'auriez pas non plus, c'est option+shift+8btw):

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

Ou pour utiliser l'initialiseur:

let convertedDegrees = CGFloat(degrees: 45.3)
Septronic
la source
-5

rapide 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
} 
HardikParmar
la source
1
Bien que ce code puisse répondre à la question, fournir un contexte supplémentaire sur la façon et / ou pourquoi il résout le problème améliorerait la valeur à long terme de la réponse.
Nic3500