Como posso converter de graus em radianos?


107

Estou tentando converter este Obj-Ccódigo em Swiftcódigo, mas não sei qual deve ser o equivalente a este código.

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

Eu pesquisei e encontrei isso

Mas eu não entendo como converter isso em Swift no meu caso?


Acho que está faltando algum código. Vocês podem adicionar todos os códigos relevantes? Qualquer outra definição, como graus?
BlackHatSamurai

este é meu código swift: pastebin.com/bZ4a7EVN
Dharmesh Kheni

Você pode me mostrar seu arquivo .h?
BlackHatSamurai

É uma macro. Você quer uma função.
gnasher729

Respostas:


265

Xcode 11 • Swift 5.1 ou posterior

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

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

Parque infantil

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 você quiser fazer com que o inteiro binário retorne um tipo de ponto flutuante em vez de sempre retornar um CGFloat, você pode fazer um método genérico em vez de uma propriedade computada:

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
Você não deveria estender CGFloat?
Zorayr

1
@Zorayr atualizado para Swift 3 e estendendo FloatingPoint agora estende todos eles
Leo Dabus

3
Na verdade, no Swift 3 você pode usar os tipos de medição e não precisa saber a fórmula de conversão de forma alguma!
matt de

3
NOTA NO ENTANTO, esta dica superpro ... stackoverflow.com/a/28600210/294884
Fattie

1
Votar sem motivo não faz sentido. Postar um comentário
Leo Dabus

63

Não é exatamente o que você pediu, mas no Swift 3 / iOS 10, você pode usar o tipo de medição e fazer a conversão sem saber a fórmula!

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

4
Excelente @matt no trabalho novamente, obrigado! Infelizmente, apenas iOS 10.
significado importa

coisa interessante que deixe radianos = CGFloat (30,3 * .pi / 180,0) deixe radianos2 = Medição (valor: 30,3, unidade: UnitAngle.degrees) .convertido (para: .radians) .valor será diferente: 0,5288347633542818 e 0,5288345742619878
Zaporozhchenko Oleksandr

e certifique-se de que "'Medição' só está disponível no iOS 10.0 ou mais recente"
Zaporozhchenko Oleksandr

42

A Apple fornece estas funções GLKit para conversão:

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

O GLKit está saindo do palco em breve, pois agora é o mundo do Metal, tchau GL. Com a portabilidade do aplicativo do iPad para o Mac, o GLKit não é mais compatível.
Juguang

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

Compila em Swift 3 . Ainda mantenha todos os valores, faça todos os cálculos em radianos com CGFloats ..., mas torne o código mais legível com as constantes em graus. Por exemplo: 90 ° O sinal ° fará magicamente a conversão de graus em radianos.

Como configurar isso:

Defina e use um operador postfix para o sinal ° . Este operador fará a conversão de graus em radianos. Este exemplo é para Ints, estenda-os também para os tipos Float, se for necessário.

postfix operator °

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

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

Alguns exemplos de uso:

let angle = 45°

contentView.transform = CGAffineTransform(rotationAngle: 45°)

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

Aviso!

É muito fácil usar esta conversão duas vezes (em um valor já em radianos por engano), você obterá um número muito pequeno como resultado, e aparentemente o ângulo resultante será sempre zero ... NÃO use ° no mesmo valor duas vezes (não converta duas vezes) !!:

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

IntegerInitializableprotocolo é inútil. Int já está em conformidade comExpressibleByIntegerLiteral
Leo Dabus

A propósito, você pode tornar esse operador genérico para suportar qualquer número inteiro e retornar qualquer ponto flutuante também. public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
Leo Dabus

E antes de comentar sobre isso ao criar um método genérico, você precisa definir explicitamente o tipo resultante, se o compilador não puder inferir o tipo resultante let angle: CGFloat = 45°. Mas não é necessário onde se espera um CGFloatou qualquer FloatingPointtipoCGAffineTransform(rotationAngle: 45°)
Leo Dabus

11

Além disso, para converter radianos da frente em graus (se alguém encontrar isso no Google):

var degrees = radians * (180.0 / M_PI)

3

Você não está mais limitado a caracteres ASCII ao criar nomes de variáveis, então que tal usar π (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
    }
}

Exemplo de uso:

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

Você pode escrever funções genéricas globais:

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

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

Exemplo:

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

No caso de você não querer estender todos os seus tipos flutuantes como este

extension FloatingPoint { ... }

Por que não simplesmente return .pi * degrees / 180?
Leo Dabus

@LeoDabus porque Té FloatingPointtipo e 180 é Inttipo. No Swift, você não pode fazer cálculos em tipos diferentes.
Tikhonov Alexander

Você está errado. Swift pode inferir o tipo. Ele se comporta exatamente da mesma forma como se você estivesse estendendo o tipo de Ponto Flutuante. 180 pode ser qualquer coisa. não necessariamente um Int
Leo Dabus

1
FloatingPoint está em conformidade com ExpressibleByIntegerLiteral é por isso que você pode escrever 180 lá
Leo Dabus

1
180.0 precisa de T porque T não é necessariamente um Double. Pode ser qualquer tipo de ponto flutuante. Você inicializa um novo de seu duplo 180.0
Leo Dabus

1

Eu usaria o mesmo princípio @ t1ser mencionado acima, mas criaria uma extensão de CGFloatpara facilitar o uso de decimais para o grau também (para que você pudesse ter 23,4 graus, por exemplo):

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

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

Usá-lo também seria muito fácil (principalmente porque eu pessoalmente não sabia como digitar ° 😜 - caso você também não saiba, é a propósito option+shift+8):

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

Ou para usar o 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
Embora este código possa responder à pergunta, fornecer contexto adicional sobre como e / ou por que ele resolve o problema melhoraria o valor da resposta a longo prazo.
Nic3500 01 de
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.