Swift Convert decimal coordinate into degrees, minutes, seconds, direction
Xcode 12 • Swift 5 or later
extension BinaryFloatingPoint {
var dms: (degrees: Int, minutes: Int, seconds: Int) {
var seconds = Int(self * 3600)
let degrees = seconds / 3600
seconds = abs(seconds % 3600)
return (degrees, seconds / 60, seconds % 60)
}
}
extension CLLocation {
var dms: String { latitude + " " + longitude }
var latitude: String {
let (degrees, minutes, seconds) = coordinate.latitude.dms
return String(format: "%d°%d'%d\"%@", abs(degrees), minutes, seconds, degrees >= 0 ? "N" : "S")
}
var longitude: String {
let (degrees, minutes, seconds) = coordinate.longitude.dms
return String(format: "%d°%d'%d\"%@", abs(degrees), minutes, seconds, degrees >= 0 ? "E" : "W")
}
}
let latitude = -22.9133950
let longitude = -43.2007100
let location = CLLocation(latitude: latitude, longitude: longitude)
location.latitude // "22°54'48"S"
location.longitude // "43°12'2"W"
location.dms // "22°54'48"S 43°12'2"W"
How to convert degrees, minutes, seconds and direction to longitude and latitude coordinates?
I don't know if there is a built-in function, but this will work:
func convert(degrees degrees: Double, minutes: Double, seconds: Double, direction: String) -> Double {
let sign = (direction == "W" || direction == "S") ? -1.0 : 1.0
return (degrees + (minutes + seconds/60.0)/60.0) * sign
}
let lattitude = convert(degrees: 40, minutes: 58, seconds: 36, direction: "N") // 40.9766666666667
let longitude = convert(degrees: 28, minutes: 49, seconds: 16, direction: "W") // -28.8211111111111
Convert decimal coordinate into degrees, minutes, seconds, direction
Standard way:
char lonLetter = (lon > 0) ? 'E' : 'W';
char latLetter = (lat > 0) ? 'N' : 'S';
Convert MapKit latitude and longitude to DMS format
Unfortunately there is no automatic conversion but you can easily create one as follow:
Swift 4 or later
func coordinateToDMS(latitude: Double, longitude: Double) -> (latitude: String, longitude: String) {
let latDegrees = abs(Int(latitude))
let latMinutes = abs(Int((latitude * 3600).truncatingRemainder(dividingBy: 3600) / 60))
let latSeconds = Double(abs((latitude * 3600).truncatingRemainder(dividingBy: 3600).truncatingRemainder(dividingBy: 60)))
let lonDegrees = abs(Int(longitude))
let lonMinutes = abs(Int((longitude * 3600).truncatingRemainder(dividingBy: 3600) / 60))
let lonSeconds = Double(abs((longitude * 3600).truncatingRemainder(dividingBy: 3600).truncatingRemainder(dividingBy: 60) ))
return (String(format:"%d° %d' %.4f\" %@", latDegrees, latMinutes, latSeconds, latitude >= 0 ? "N" : "S"),
String(format:"%d° %d' %.4f\" %@", lonDegrees, lonMinutes, lonSeconds, longitude >= 0 ? "E" : "W"))
}
let dms = coordinateToDMS(latitude: 48.8582487759147, longitude: 2.2945180844931)
print(dms.latitude) // "48° 51' 29.6956" N"
print(dms.longitude) // "2° 17' 40.2651" E"
You can also extend CLLocationCoordinate2D to get your latitude/longitude DMS description:
import MapKit
extension FloatingPoint {
var minutes: Self {
return (self*3600)
.truncatingRemainder(dividingBy: 3600)/60
}
var seconds: Self {
return (self*3600)
.truncatingRemainder(dividingBy: 3600)
.truncatingRemainder(dividingBy: 60)
}
}
extension CLLocationCoordinate2D {
var dms: (latitude: String, longitude: String) {
return (String(format:"%d° %d' %.4f\" %@",
Int(abs(latitude)),
Int(abs(latitude.minutes)),
abs(latitude.seconds),
latitude >= 0 ? "N" : "S"),
String(format:"%d° %d' %.4f\" %@",
Int(abs(longitude)),
Int(abs(longitude.minutes)),
abs(longitude.seconds),
longitude >= 0 ? "E" : "W"))
}
}
let coord = CLLocationCoordinate2D(latitude: 48.8582487759147, longitude: 2.2945180844931)
coord.dms.latitude // "48° 51' 29.6956" N"
coord.dms.longitude // "2° 17' 40.2651" E"
Better way to parse and convert DMS Coordinates from String to Double in Swift
When ahead with the reply from https://codereview.stackexchange.com/questions/153291/parsing-and-converting-dms-coordinates-from-string-to-double
struct PLNWaypointCoordinate {
var latitude: Double
var longitude: Double
init(latitude: Double, longitude: Double) {
self.latitude = latitude
self.longitude = longitude
}
init?(coordinateString: String) {
let components = coordinateString.components(separatedBy: ",")
guard components.count >= 2,
let latitude = PLNWaypointCoordinate.convertCoordinate(coordinate: components[0],
positiveDirection: "N",
negativeDirection: "S"),
let longitude = PLNWaypointCoordinate.convertCoordinate(coordinate: components[1],
positiveDirection: "E",
negativeDirection: "W")
else {
return nil
}
self.init(latitude: latitude, longitude: longitude)
}
private static func convertCoordinate(coordinate: String,
positiveDirection: String,
negativeDirection: String) -> Double? {
// Determine the sign from the first character:
let sign: Double
let scanner = Scanner(string: coordinate)
if scanner.scanString(positiveDirection, into: nil) {
sign = 1.0
} else if scanner.scanString(negativeDirection, into: nil) {
sign = -1.0
} else {
return nil
}
// Parse degrees, minutes, seconds:
var degrees = 0
var minutes = 0
var seconds = 0.0
guard scanner.scanInt(°rees), // Degrees (integer),
scanner.scanString("°", into: nil), // followed by °,
scanner.scanInt(&minutes), // minutes (integer)
scanner.scanString("'", into: nil), // followed by '
scanner.scanDouble(&seconds), // seconds (floating point),
scanner.scanString("\"", into: nil), // followed by ",
scanner.isAtEnd // and nothing else.
else { return nil }
return sign * (Double(degrees) + Double(minutes)/60.0 + seconds/3600.0)
}
}
Thanks for the help everybody!
Converting coordinates from decimal degrees to possibly EPSG 4326
(Disclaimer: I do not know this API, but I am certain that you should direct such questions to them. Nevertheless...)
If you visit the API root here, you'll find the following:
The spatial reference system is Spherical Mercator as used by Google and Bing: EPSG 3785 / 3857 / 900913.
Which is actually true! If you convert the example coordinates from EPSG:3857 to EPSG:4326, and take care to not reverse latitude and longitude, you'll see that the coordinates match up with the descriptions.
Just make sure that don't mix up longitude and latitude when looking up the results on a map.
To convert a WGS84 coordinate you get from iOS in the tool, you should:
- select EPSG:4326 for input;
- select EPSG:3857 for output;
- and input coordinates as
longitude;latitude
(for example:-122.408917;37.782683
).
To do this conversion programmatically, other SO questions will help. Porting any of those code fragments to Objective-C or Swift should be easy.
Convert Degrees/Minutes/Seconds to Decimal Coordinates
Try this:
public double ConvertDegreeAngleToDouble( double degrees, double minutes, double seconds )
{
//Decimal degrees =
// whole number of degrees,
// plus minutes divided by 60,
// plus seconds divided by 3600
return degrees + (minutes/60) + (seconds/3600);
}
Related Topics
How to Create a Nsmutabledictionary in Swift
Subscript of a Struct Doesn't Set Values When Created as an Implicitly Unwrapped Optional
Create Spotlight-Like Window in Swift 4
Detect When Wkwebview Is Finished Loading
Is This Safe to Call Wait() of Dispatchsemaphore Several Times at One Time
Nsposixerrordomain When Binding to Socket on MACos 10.12
Can Nscoding and Codable Co-Exist
Reflection with Swift - Get Functions Name of a Class
How to Save Value in Nsset Core Data (Swift)
Avplayer Can't Resume After Paused + Some Waiting
Xcode Error - Undefined Symbols for Architecture X86_64
How to Get a Double Value Up to 2 Decimal Places
How to Make Swiftui Uiviewrepresentable View Hug Its Content
iOS Swift Didbegincontact Not Being Called
How to I Access Argv and Argc in Swift
Uilabel Subclass Appearance in Storyboard
How to Use Enumeratedate in Swift 3 to Find All Sundays the Last 50 Years