将MapKit的纬度和经度转换为DMS格式

6

我能够使用以下方法确定地图中心位置的纬度和经度:

func TargetGridReference(outletMapView_PrimaryTargetLocationMap: MKMapView, regionDidChangeAnimated animated: Bool) {

    let ThreatGridReference = outletMapView_PrimaryTargetLocationMap.centerCoordinate

    let mapLatitude = String(format:"%.13f",ThreatGridReference.latitude)

    let mapLongitude = String(format:"%.13f",ThreatGridReference.longitude)
    let latAndLong = "Lat: \(mapLatitude) \nLong: \(mapLongitude)"

    self.outletLabel_TargetGridReference.text = latAndLong

    tempThreatGridReference = ThreatGridReference
    tempThreatGridReferenceLat = mapLatitude
    tempThreatGridReferenceLon = mapLongitude

}

这使我得以获得巴黎埃菲尔铁塔的纬度,如下所示:
Lat:  48.8582487759147
Long:  2.2945180844931

如何在Swift中将上述内容转换为以下DMS格式?
lat: 48° 51' 29.6956" N
long: 2° 17' 40.2651" E

MapKit是否提供自动转换各种坐标系统,如UTM、UPS、MGRS等?

5个回答

14

很不幸,目前没有自动转换的方法,但您可以按照以下步骤轻松创建一个:

Swift 4 或更高版本

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"

您还可以扩展CLLocationCoordinate2D以获取您的纬度/经度DMS描述:

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"

1
完美运行!感谢@Leo Dabus! - Jaco Griesel
我该如何做相反的操作(从度分秒转换为十进制)?谢谢。 - Cristina
只需将度数与分钟除以60相加,再将秒数除以3600即可。 - Leo Dabus
coordinateToDMS(latitude: 12.99999999, longitude: 0.0) 返回纬度 12° 59' 60.0000" N - user3441734

3

我对这段代码进行了一些更新,使其能在Swift3中运行(主要使用 .truncatingRemainder(dividingBy: ) 而不是 %),并且还扩展了它的输出为DMM,并包括将DMM和DMS转换为DD的函数!

extension CLLocationCoordinate2D {

    var latitudeMinutes:  Double { return (latitude * 3600).truncatingRemainder(dividingBy: 3600) / 60 }
    var latitudeSeconds:  Double { return ((latitude * 3600).truncatingRemainder(dividingBy: 3600)).truncatingRemainder(dividingBy: 60) }

    var longitudeMinutes: Double { return (longitude * 3600).truncatingRemainder(dividingBy: 3600) / 60 }
    var longitudeSeconds: Double { return ((longitude * 3600).truncatingRemainder(dividingBy: 3600)).truncatingRemainder(dividingBy: 60) }

    var dms:(latitude: String, longitude: String) {

        return (String(format:"%d°%d'%.1f\"%@",
                       Int(abs(latitude)),
                       Int(abs(latitudeMinutes)),
                       abs(latitudeSeconds),
                       latitude >= 0 ? "N" : "S"),
                String(format:"%d°%d'%.1f\"%@",
                       Int(abs(longitude)),
                       Int(abs(longitudeMinutes)),
                       abs(longitudeSeconds),
                       longitude >= 0 ? "E" : "W"))
    }

    var dmm: (latitude: String, longitude: String) {
        return (String(format:"%d°%.4f'%@",
                      Int(abs(latitude)),
                      abs(latitudeMinutes),
                      latitude >= 0 ? "N" : "S"),
               String(format:"%d°%.4f'%@",
                      Int(abs(longitude)),
                      abs(longitudeMinutes),
                      longitude >= 0 ? "E" : "W"))
    }
}

var coord = CLLocationCoordinate2D(latitude: 41.40338, longitude: 2.17403)

coord.latitude // 41.40338
coord.longitude // 2.17403
coord.latitudeMinutes // 24.20280000000009
coord.latitudeSeconds // 12.16800000000512
coord.longitudeMinutes // 10.44180000000001
coord.longitudeSeconds // 26.50800000000072

coord.dms.latitude   // "41°24'12.2"N"
coord.dms.longitude  // "2°10'26.5"E"
coord.dmm.latitude   // "41°24.2028'N"
coord.dmm.longitude  // "2°10.4418'E"

这些转换函数也允许输入时不指定方向,而只提供正数或负数:
func DMStoDD(latDeg: Double, latMin: Double, latSec: Double, latDir: String?, longDeg: Double, longMin: Double, longSec: Double, longDir: String?) -> CLLocationCoordinate2D {
    var latitude = CLLocationDegrees()
    if latDeg > 0 {
        latitude = CLLocationDegrees(latDeg + ((latMin*60)/3600) + (latSec/3600))
        if latDir == "S" {latitude *= -1}
    }
    else{
        latitude = CLLocationDegrees((latDeg * -1) + ((latMin*60)/3600) + (latSec/3600))
        latitude *= -1
    }

    var longitude = CLLocationDegrees()
    if longDeg > 0 {
        longitude = CLLocationDegrees(longDeg + ((longMin*60)/3600) + (longSec/3600))
        if longDir == "W" {longitude *= -1}
    }
    else{
        longitude = CLLocationDegrees((longDeg * -1) + ((longMin*60)/3600) + (longSec/3600))
        longitude *= -1
    }
    return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}

coord = DMStoDD(latDeg: 41, latMin: 24, latSec: 12.2, latDir: "", longDeg: 2, longMin: 10, longSec: 26.5, longDir: "")
coord.latitude // 41.40338888888889
coord.longitude // 2.174027777777777

将DMM转换为DD
func DMMtoDD(latDeg: Double, latMin: Double, latDir: String?, longDeg: Double, longMin: Double, longDir: String?) -> CLLocationCoordinate2D {
    var latitude = CLLocationDegrees()
    if latDeg > 0 {
        latitude = CLLocationDegrees(latDeg + ((latMin*60)/3600))
        if latDir == "S" {latitude *= -1}
    }
    else{
        latitude = CLLocationDegrees((latDeg * -1) + ((latMin*60)/3600))
        latitude *= -1
    }
    var longitude = CLLocationDegrees()
    if longDeg > 0 {
        longitude = CLLocationDegrees(longDeg + ((longMin*60)/3600))
        if longDir == "W" {longitude *= -1}
    }
    else{
        longitude = CLLocationDegrees((longDeg * -1) + ((longMin*60)/3600))
        longitude *= -1
    }
    return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
}

coord = DMMtoDD(latDeg: 41, latMin: 24.2028, latDir: "N", longDeg: 2, longMin: 10.4418, longDir: "E")
coord.latitude // 41.40338
coord.longitude // 41.40338

1

被接受的答案的第一部分有一个小错误:

let latDegrees = abs(Int(lat))

将始终产生正数latDegrees,因此返回部分latDegrees >= 0 ? "N" : "S"将始终产生N,无论输入的lat: Double符号如何。

只需要更改为lat >= 0 ? "N" : "S")以及lon >= 0 ? "E" : "W")来直接评估输入值的符号。


0

Swift 5 这是基于@Shō Ya Voorthuyzen上面的答案。

extension CLLocationCoordinate2D {

   var latitudeMinutes: Double { return (latitude * 3600).truncatingRemainder(dividingBy: 3600) / 60 }
   var latitudeSeconds: Double { return ((latitude * 3600).truncatingRemainder(dividingBy: 3600)).truncatingRemainder(dividingBy: 60) }

   var longitudeMinutes: Double { return (longitude * 3600).truncatingRemainder(dividingBy: 3600) / 60 }
   var longitudeSeconds: Double { return ((longitude * 3600).truncatingRemainder(dividingBy: 3600)).truncatingRemainder(dividingBy: 60) }

   var degrees: (latitude: String, longitude: String) {
    (String(format: "%.5f°", latitude), String(format: "%.5f°", longitude))
   }

   var dms: (latitude: String, longitude: String) {
    (String(format: "%d° %d' %.1f\" %@",
            Int(abs(latitude)),
            Int(abs(latitudeMinutes)),
            abs(latitudeSeconds),
            latitude >= 0 ? "N" : "S"),
     String(format: "%d° %d' %.1f\" %@",
            Int(abs(longitude)),
            Int(abs(longitudeMinutes)),
            abs(longitudeSeconds),
            longitude >= 0 ? "E" : "W"))
   }

   var ddm: (latitude: String, longitude: String) {
    (String(format: "%d° %.3f' %@",
            Int(abs(latitude)),
            abs(latitudeMinutes),
            latitude >= 0 ? "N" : "S"),
     String(format: "%d° %.3f' %@",
            Int(abs(longitude)),
            abs(longitudeMinutes),
            longitude >= 0 ? "E" : "W"))
   }
}

输出结果如下:

十进制度数:28.31668° -82.56701°

度分秒:28° 19' 0.0" N 82° 34' 1.2" W

度分:28° 19.001' N 82° 34.020' W


0

有时候被接受的答案会返回无效值,coordinateToDMS(latitude: 12.99999999, longitude: 0.0) 返回的纬度是12° 59' 60.0000" N

enum GeoFormat {
    case D
    case DM
    case DMS
}
func dms(value: Double, format: GeoFormat)->String {
    let sign = value < 0.0 ? -1 : 1
    let value = abs(value)
    switch format {
    case .D:
        return String(format: "%+15.10f°", value * Double(sign))
    case .DM:
        var deg = Int(value)
        var min = round((value - Double(deg)) * 60 * 10000000) * 0.0000001
        if min < 60.0 {} else {
            min -= 60.0
            deg += 1
        }
        return String(format: "%+4d°%010.7f′", deg * sign, min)
    case .DMS:
        var deg = Int(value)
        let _min = (value - Double(deg)) * 60
        var min = Int(_min)
        var sec = round((_min - Double(min)) * 60 * 10000) * 0.0001
        if sec < 60.0 {} else {
            sec -= 60.0
            min += 1
        }
        if min < 60 {} else {
            min -= 60
            deg += 1
        }
        return String(format: "%+4d°%02d′%07.4f″", deg * sign, min, sec)
    }
}

let value = -12.999999997222222
print(dms(value: value, format: .D))
print(dms(value: value, format: .DM))
print(dms(value: value, format: .DMS))

按要求打印

 -12.9999999972°
 -12°59.9999998′
 -13°00′00.0000″

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接