Wie kann ich von Grad in Bogenmaß umrechnen?

107

Ich versuche, diesen Obj-CCode in SwiftCode umzuwandeln , weiß aber nicht, wie dieser Code aussehen soll.

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

Ich googeln und fand diese

Aber ich verstehe nicht, wie ich das in meinem Fall in Swift umwandeln soll?

Dharmesh Kheni
quelle
Ich denke, Ihnen fehlt ein Code. Können Sie alle den relevanten Code hinzufügen? Gibt es noch andere Definitionen wie Abschlüsse?
BlackHatSamurai
Dies ist mein schneller Code: pastebin.com/bZ4a7EVN
Dharmesh Kheni
Können Sie mir Ihre .h-Datei zeigen?
BlackHatSamurai
Es ist ein Makro. Sie möchten eine Funktion.
Gnasher729
1
ultratip ... stackoverflow.com/a/28600210/294884
Fattie

Antworten:

265

Xcode 11 • Swift 5.1 oder höher

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

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

Spielplatz

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

Wenn Sie möchten, dass die binäre Ganzzahl einen Gleitkommatyp zurückgibt, anstatt immer ein CGFloat zurückzugeben, können Sie anstelle einer berechneten Eigenschaft eine generische Methode erstellen:

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
quelle
4
Solltest du nicht verlängern CGFloat?
Zorayr
1
@Zorayr auf Swift 3 aktualisiert und FloatingPoint erweitert erweitert jetzt alle
Leo Dabus
3
Tatsächlich können Sie in Swift 3 die Messtypen verwenden und müssen die Umrechnungsformel überhaupt nicht kennen!
Matt
3
Beachten Sie jedoch , diese superpro Spitze ... stackoverflow.com/a/28600210/294884
Fattie
1
Ohne Grund abzustimmen macht keinen Sinn. Kommentar
abgeben
63

Dies ist nicht identisch mit dem, was Sie gefragt haben, aber in Swift 3 / iOS 10 können Sie den Messtyp verwenden und die Konvertierung durchführen, ohne die Formel zu kennen!

let result = Measurement(value: 45, unit: UnitAngle.degrees)
    .converted(to: .radians).value
matt
quelle
4
Erstaunlich @matt wieder bei der Arbeit, danke! Leider nur iOS 10.
Bedeutung-Angelegenheiten
Interessante Sache, bei der Radiant = CGFloat (30,3 * .pi / 180,0) let radians2 = Messung (Wert: 30,3, Einheit: UnitAngle.degrees) .umgerechnet (in: .radians) .Wert ist unterschiedlich: 0,5288347633542818 und 0,5288345742619878
Zaporozhchenko Oleksandr
und sicher "'Measurement' ist nur unter iOS 10.0 oder neuer verfügbar"
Zaporozhchenko Oleksandr
42

Apple bietet diese GLKit-Funktionen für die Konvertierung an:

func GLKMathDegreesToRadians(_ degrees: Float) -> Float
func GLKMathRadiansToDegrees(_ radians: Float) -> Float
Crashalot
quelle
GLKit geht bald von der Bühne, da es jetzt die Welt des Metals ist, tschüss GL. Als Portierung der iPad-App auf den Mac wird GLKit nicht mehr unterstützt!.
Juguang
17
let angle = 45° // angle will be in radians, 45 is in degrees

Kompiliert unter Swift 3 . Behalten Sie weiterhin alle Werte bei, führen Sie alle Berechnungen im Bogenmaß mit CGFloats durch ..., aber machen Sie den Code mit den Konstanten in Grad besser lesbar. Zum Beispiel: 90 ° Das ° -Zeichen bewirkt auf magische Weise die Umrechnung von Grad in Bogenmaß.

So richten Sie dies ein:

Definieren und verwenden Sie einen Postfix-Operator für das ° -Zeichen. Dieser Operator führt die Umrechnung von Grad in Bogenmaß durch. Dieses Beispiel gilt für Ints. Erweitern Sie diese bei Bedarf auch für die Float-Typen.

postfix operator °

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

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

Einige Anwendungsbeispiele:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Warnung!

Es ist zu einfach, diese Konvertierung zweimal zu verwenden (bei einem Wert, der bereits versehentlich im Bogenmaß vorliegt). Als Ergebnis erhalten Sie eine sehr kleine Zahl, und der resultierende Winkel scheint immer Null zu sein. Verwenden Sie ° NICHT für denselben Wert Wert zweimal (nicht zweimal konvertieren) !!:

// 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
quelle
IntegerInitializableProtokoll ist sinnlos. Int entspricht bereitsExpressibleByIntegerLiteral
Leo Dabus
Übrigens können Sie diesen Operator generisch machen, um eine beliebige Ganzzahl zu unterstützen und auch einen beliebigen Gleitkomma zurückzugeben. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus
Und bevor Sie dies beim Erstellen einer generischen Methode kommentieren, müssen Sie den resultierenden Typ explizit festlegen, wenn der Compiler den resultierenden Typ nicht ableiten kann let angle: CGFloat = 45°. Aber es wird nicht benötigt, wenn es einen CGFloatoder einen anderen FloatingPointTyp erwartetCGAffineTransform(rotationAngle: 45°)
Leo Dabus
11

Um das Bogenmaß in Grad umzurechnen (falls jemand bei Google darauf stößt):

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

Sie sind beim Erstellen von Variablennamen nicht mehr auf ASCII-Zeichen beschränkt. Wie wäre es also mit π (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
    }
}

Anwendungsbeispiel:

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
quelle
2

Swift 4.2

Sie können globale generische Funktionen schreiben:

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

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

Beispiel:

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

Für den Fall, dass Sie nicht alle Ihre schwebenden Typen wie diese erweitern möchten

extension FloatingPoint { ... }
Tichonow Alexander
quelle
Warum nicht einfach return .pi * degrees / 180?
Leo Dabus
@LeoDabus weil Tist FloatingPointTyp und 180 ist IntTyp. In Swift können Sie keine Berechnungen für verschiedene Typen durchführen.
Tichonow Alexander
Sie liegen falsch. Swift kann auf den Typ schließen. Es verhält sich genauso, als würden Sie den FloatingPoint-Typ erweitern. 180 kann alles sein. nicht unbedingt ein Int
Leo Dabus
1
FloatingPoint entspricht ExpressibleByIntegerLiteral, deshalb können Sie dort 180 schreiben
Leo Dabus
1
180.0 benötigt T, weil T nicht unbedingt ein Double ist. Es kann sich um einen beliebigen Gleitkommatyp handeln. Sie initialisieren eine neue von Ihrem Doppel 180.0
Leo Dabus
1

Ich würde das oben erwähnte Prinzip @ t1ser verwenden, aber eine Erweiterung von erstellen CGFloat, um die Verwendung von Dezimalstellen für den Abschluss zu vereinfachen (so könnten Sie beispielsweise 23,4 Grad haben):

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

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

Es wäre auch ziemlich einfach (hauptsächlich, weil ich persönlich nicht wusste, wie man ° 😜 eingibt - falls Sie es auch nicht getan haben, ist es option+shift+8übrigens):

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

Oder um den Initialisierer zu verwenden:

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

schnell 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
quelle
1
Während dieser Code die Frage möglicherweise beantwortet, würde die Bereitstellung eines zusätzlichen Kontexts darüber, wie und / oder warum das Problem gelöst wird, den langfristigen Wert der Antwort verbessern.
Nic3500