¿Cómo puedo convertir de grados a radianes?


107

Estoy tratando de convertir este Obj-Ccódigo en Swiftcódigo, pero no sé cuál debería ser el equivalente de este código.

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

Busqué en Google y encontré esto

¿Pero no entiendo cómo convertir eso en Swift en mi caso?


Creo que te falta un código. ¿Pueden todos agregar todo el código relevante? ¿Alguna otra definición, como grados?
BlackHatSamurai

este es mi código
SWIFT

¿Me puedes mostrar tu archivo .h?
BlackHatSamurai

Es una macro. Quieres una función.
gnasher729

Respuestas:


267

Xcode 11 • Swift 5.1 o posterior

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

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

Patio de recreo

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 desea que el entero binario devuelva un tipo de punto flotante en lugar de devolver siempre un CGFloat, puede crear un método genérico en lugar de una propiedad calculada:

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
¿No deberías extender CGFloat?
Zorayr

1
@Zorayr actualizado a Swift 3 y la extensión de FloatingPoint ahora los extiende a todos
Leo Dabus

3
En realidad, en Swift 3 puede usar los tipos de medición y no necesita conocer la fórmula de conversión en absoluto.
Matt

3
NOTA SIN EMBARGO, este consejo superpro ... stackoverflow.com/a/28600210/294884
Fattie

1
Votar en contra sin una razón no tiene ningún sentido. Publicar un comentario
Leo Dabus

63

Esto no es exactamente lo que pidió, pero en Swift 3 / iOS 10, puede usar el tipo de medición y realizar la conversión sin conocer la fórmula.

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

4
Increíble @matt en el trabajo de nuevo, ¡gracias! Desafortunadamente, solo iOS 10.
significado importa

algo interesante que deja radianes = CGFloat (30.3 * .pi / 180.0) deja radianes2 = Medida (valor: 30.3, unidad: UnitAngle.degrees) .converted (a: .radians) .value será diferente: 0.5288347633542818 y 0.5288345742619878
Zaporozhchenko Oleksandr

y seguro "'Medición' solo está disponible en iOS 10.0 o posterior"
Zaporozhchenko Oleksandr

42

Apple proporciona estas funciones GLKit para la conversión:

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

GLKit saldrá del escenario pronto, ya que ahora es el mundo del Metal, adiós GL. Como portando la aplicación de iPad a Mac, GLKit ya no es compatible.
Juguang

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

Compila bajo Swift 3 . Conserve todos los valores, haga todos los cálculos en radianes con CGFloats ..., pero haga que el código sea más legible con las constantes en grados. Por ejemplo: 90 ° El signo ° hará mágicamente la conversión de grados a radianes.

Cómo configurar esto:

Defina y use un operador de sufijo para el signo ° . Este operador hará la conversión de grados a radianes. Este ejemplo es para Ints, extiéndalos también para los tipos Float si es necesario.

postfix operator °

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

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

Algunos ejemplos de uso:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

¡Advertencia!

Es demasiado fácil usar esta conversión dos veces (en un valor que ya está en radianes por error), obtendrá un número muy pequeño como resultado, y aparentemente el ángulo resultante será siempre cero ... NO use ° en el mismo valor dos veces (no convertir dos veces) !!:

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

IntegerInitializableel protocolo es inútil. Int ya cumple conExpressibleByIntegerLiteral
Leo Dabus

Por cierto, puede hacer que este operador sea genérico para admitir cualquier número entero y también devolver cualquier punto flotante. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus

Y antes de comentarlo al crear un método genérico, necesitaría establecer explícitamente el tipo resultante si el compilador no puede inferir el tipo resultante let angle: CGFloat = 45°. Pero no es necesario donde espera un tipo CGFloato cualquier otroFloatingPointCGAffineTransform(rotationAngle: 45°)
Leo Dabus

11

Además, para convertir de radianes a grados (si alguien se encuentra con esto en Google):

var degrees = radians * (180.0 / M_PI)

3

Ya no está limitado a los caracteres ASCII al crear nombres de variables, entonces, ¿qué tal si usa π (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
    }
}

Uso de ejemplo:

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

Rápido 4.2

Puede escribir funciones genéricas 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
}

Ejemplo:

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

En caso de que no desee ampliar todos sus tipos flotantes como este

extension FloatingPoint { ... }

¿Por qué no simplemente return .pi * degrees / 180?
Leo Dabus

@LeoDabus porque Tes FloatingPointtipo y 180 es Inttipo. En Swift no se pueden hacer cálculos sobre diferentes tipos.
Tikhonov Alexander

Está usted equivocado. Swift puede inferir el tipo. Se comporta exactamente igual que si estuviera ampliando el tipo FloatingPoint. 180 puede ser cualquier cosa. no necesariamente un Int
Leo Dabus

1
FloatingPoint se ajusta a ExpressibleByIntegerLiteral, por eso puede escribir 180 allí
Leo Dabus

1
180.0 necesita T porque T no es necesariamente un Doble. Puede ser cualquier tipo de punto flotante. Inicializa uno nuevo de su doble 180.0
Leo Dabus

1

Usaría el mismo principio @ t1ser mencionado anteriormente, pero crearía una extensión de CGFloatpara facilitar el uso de decimales para el grado también (por lo que podría tener 23.4 grados, por ejemplo):

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

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

Usarlo también sería bastante fácil (principalmente porque personalmente no sabía cómo escribir ° 😜; en caso de que tú tampoco, por option+shift+8cierto):

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

O para usar el inicializador:

let convertedDegrees = CGFloat(degrees: 45.3)

-5

rápido 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
Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y / o por qué resuelve el problema mejoraría el valor de la respuesta a largo plazo.
Nic3500
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.