How can I convert from degrees to radians?

IosObjective CMacosSwiftMacros

Ios Problem Overview


I am trying to convert this Obj-C code to Swift code but I don't know what the equivalent of this code should be ?

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

I googled and found this

But I don't understand how to convert that in Swift in my case?

Ios Solutions


Solution 1 - Ios

Xcode 11 • Swift 5.1 or later

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

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

Playground

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

If you would like to make the binary integer return a floating point type instead of always returning a CGFloat you can make a generic method instead of a computed property:

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

Solution 2 - Ios

This is not identically what you asked, but in Swift 3 / iOS 10, you can use the Measurement type and do the conversion without knowing the formula!

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

Solution 3 - Ios

Apple provides these GLKit functions for conversion:

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

Solution 4 - Ios

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

Compiles under Swift 3. Still keep all values, do all calculations in radians with CGFloats..., but make the code more readable with the constants in degrees. For example: 90° The ° sign will magically do the degrees to radians conversion.

How to set this up:

Define and use a postfix operator for the ° sign. This operator will do the conversion from degrees to radians. This example is for Ints, extend these also for the Float types if you have the need.

postfix operator °
    
protocol IntegerInitializable: ExpressibleByIntegerLiteral {
  init (_: Int)
}

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

Some examples of usage:

let angle = 45°

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

Warning!

It is too easy to use this conversion twice (on a value already in radians by mistake), you will get a very small number as the result, and seemingly the resulting angle will be always zero... DO NOT use ° on the same value twice (do not convert twice)!!:

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

Solution 5 - Ios

Also, to convert fron radians to degrees (if anyone stumbles upon this on google):

var degrees = radians * (180.0 / M_PI)

Solution 6 - Ios

You're no longer limited to ASCII characters when creating variable names, so how about this using π (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
    }
}

Example usage:

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

Solution 7 - Ios

Swift 4.2

You can write global generic functions:

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

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

Example:

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

In case when you don't want to extension all your floating types like this

extension FloatingPoint { ... }

Solution 8 - Ios

The most efficient and accurate way to convert a Double between degrees and radians:

import Foundation

extension Double {
    var radians: Double { return Measurement(value: self, unit: UnitAngle.degrees).converted(to: UnitAngle.radians).value }
    var degrees: Double { return Measurement(value: self, unit: UnitAngle.radians).converted(to: UnitAngle.degrees).value }
}

The Foundation team at Apple addressed this problem long ago by developing a solution that surpasses all others:

Measurements and Units - WWDC 2016, Session 238

Solution 9 - Ios

I'd use the same principle @t1ser mentioned above, but create an extension of CGFloat to make it easier to use decimals for the degree as well (so you could have a 23.4 degrees, for example):

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

Using it would be pretty easy as well (mainly because I personally didn't know how to type °  - in case you didn't either, it's option+shift+8 btw):

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

Or to use the initialiser:

let convertedDegrees = CGFloat(degrees: 45.3)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionDharmesh KheniView Question on Stackoverflow
Solution 1 - IosLeo DabusView Answer on Stackoverflow
Solution 2 - IosmattView Answer on Stackoverflow
Solution 3 - IosCrashalotView Answer on Stackoverflow
Solution 4 - Iost1serView Answer on Stackoverflow
Solution 5 - IosnikansView Answer on Stackoverflow
Solution 6 - IosAshley MillsView Answer on Stackoverflow
Solution 7 - IosTikhonov AleksandrView Answer on Stackoverflow
Solution 8 - IosJames BushView Answer on Stackoverflow
Solution 9 - IosSeptronicView Answer on Stackoverflow