Swift Convert decimal coordinate into degrees, min

2019-07-09 00:43发布

问题:

How can I covert this to swift? My best guess is that all the int get changed to a var. Removing all the @ that lead ". Also if any can point me to a good source to learn how things convert that would great.

- (NSString*)coordinateString {

int latSeconds = (int)(self.latitude * 3600);
int latDegrees = latSeconds / 3600;
latSeconds = ABS(latSeconds % 3600);
int latMinutes = latSeconds / 60;
latSeconds %= 60;

int longSeconds = (int)(self.longitude * 3600);
int longDegrees = longSeconds / 3600;
longSeconds = ABS(longSeconds % 3600);
int longMinutes = longSeconds / 60;
longSeconds %= 60;

NSString* result = [NSString stringWithFormat:@"%d°%d'%d\"%@ %d°%d'%d\"%@",
                    ABS(latDegrees),
                    latMinutes,
                    latSeconds,
                    latDegrees >= 0 ? @"N" : @"S",
                    ABS(longDegrees),
                    longMinutes,
                    longSeconds,
                    longDegrees >= 0 ? @"E" : @"W"];

return result;    
}

My attempt to convert it but Xcode proves me wrong. Reposted the fix suggest with the ABS. Does it look correct now?

func coordinateString {

var latSeconds = (Int8)(self.latitude * 3600);
var latDegrees = latSeconds / 3600;
latSeconds = abs(latSeconds % 3600);
var latMinutes = latSeconds / 60;
latSeconds %= 60;

var longSeconds = (Int8)(self.longitude * 3600);
var longDegrees = longSeconds / 3600;
longSeconds = abs(longSeconds % 3600);
var longMinutes = longSeconds / 60;
longSeconds %= 60;

    var result = (String(format: "%d°%d'%d\"%@ %d°%d'%d\"%@"),
abs(latDegrees),
latMinutes,
latSeconds,
latDegrees >= 0 ? "N" : "S",
abs(longDegrees),
longMinutes,
longSeconds,
longDegrees >= 0 ? "E" : "W",

return result;
}

回答1:

Xcode 8.3.2 • Swift 3.1

func coordinateString(_ latitude: Double,_ longitude: Double) -> String {
    var latSeconds = Int(latitude * 3600)
    let latDegrees = latSeconds / 3600
    latSeconds = abs(latSeconds % 3600)
    let latMinutes = latSeconds / 60
    latSeconds %= 60
    var longSeconds = Int(longitude * 3600)
    let longDegrees = longSeconds / 3600
    longSeconds = abs(longSeconds % 3600)
    let longMinutes = longSeconds / 60
    longSeconds %= 60
    return String(format:"%d°%d'%d\"%@ %d°%d'%d\"%@",
                  abs(latDegrees),
                  latMinutes,
                  latSeconds, latDegrees >= 0 ? "N" : "S",
                  abs(longDegrees),
                  longMinutes,
                  longSeconds,
                  longDegrees >= 0 ? "E" : "W" )
}


coordinateString(-22.9133950, -43.2007100)   // "22°54'48"S 43°12'2"W"


回答2:

I have just edited Leo Dabus answer to get those String as separate values. In case it is helpful for others:

Swift 3 and Swift 4

func getLocationDegreesFrom(latitude: Double) -> String {

    var latSeconds = Int(latitude * 3600)

    let latDegrees = latSeconds / 3600

    latSeconds = abs(latSeconds % 3600)

    let latMinutes = latSeconds / 60

    latSeconds %= 60

    return String(

        format: "%d°%d'%d\"%@",
        abs(latDegrees),
        latMinutes,
        latSeconds,
        latDegrees >= 0 ? "N" : "S"

    )

}

func getLocationDegreesFrom(longitude: Double) -> String {

    var longSeconds = Int(longitude * 3600)

    let longDegrees = longSeconds / 3600

    longSeconds = abs(longSeconds % 3600)

    let longMinutes = longSeconds / 60

    longSeconds %= 60

    return String(

        format: "%d°%d'%d\"%@",
        abs(longDegrees),
        longMinutes,
        longSeconds,
        longDegrees >= 0 ? "E" : "W"

    )

}


回答3:

I took the code of Leo Dabus and fixed a bug related with the detection of the cardinal directions when the values of the latitude or longitude are less than zero, I mean when we are at southern hemisphere or west of the prime meridian.

We can't represent a negative zero with Swift, so we lose the negative sign at the following expression:

let latDegrees = latSeconds / 3600

this bug also makes the expresion:

latDegrees >= 0 ? "N" : "S"

always return N (North) and never S (South).

Here is my version of the code (Swift 5 and Xcode 10):

func coordinate() -> (latitude: String, longitude: String) {

    // This function converts from DD (decimal degrees) to DMS (degrees, minutes and seconds)

    // Calculating the degrees, minutes and seconds for the given latitude value (DD)

    var latitudeSeconds = latitude * 3600

    let latitudeDegrees = latitudeSeconds / 3600

    latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 3600)

    let latitudeMinutes = latitudeSeconds / 60

    latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 60)

    // Calculating the degrees, minutes and seconds for the given longitude value (DD)

    var longitudeSeconds = longitude * 3600

    let longitudeDegrees = longitudeSeconds / 3600

    longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 3600)

    let longitudeMinutes = longitudeSeconds / 60

    longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 60)

    // Analyzing if it's North or South. (Latitude)

    let latitudeCardinalDirection = latitudeDegrees >= 0 ? "N" : "S"

    // Analyzing if it's East or West. (Longitude)

    let longitudeCardinalDirection = longitudeDegrees >= 0 ? "E" : "W"

    // Final strings with format <degrees>°<minutes>'<seconds>"<cardinal direction>

    let latitudeDescription = String(format:"%.2f°%.2f'%.2f\"%@",
                                     abs(latitudeDegrees), abs(latitudeMinutes),
                                     abs(latitudeSeconds), latitudeCardinalDirection)

    let longitudeDescription = String(format:"%.2f°%.2f'%.2f\"%@",
                                      abs(longitudeDegrees), abs(longitudeMinutes),
                                      abs(longitudeSeconds), longitudeCardinalDirection)

    return (latitudeDescription, longitudeDescription)

} // coordinate

I also chose to work with Double in order to handle the precision, for example, I prefer to show two decimal places.

The screen output of this code would be something like:

0.17°10.34'20.53"S 78.48°28.59'35.52"W



回答4:

Based on David Seek and Josué V. Herrera code

func latlon2DMS(latitude: Double) -> String {
    var latitudeSeconds = latitude * 3600
    let latitudeDegrees = latitudeSeconds / 3600
    latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 3600)
    let latitudeMinutes = latitudeSeconds / 60
    latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 60)
    let latitudeCardinalDirection = latitudeDegrees >= 0 ? "N" : "S"
    let latitudeDescription = String(format: "%.2f° %.2f' %.2f\" %@",
                                     abs(latitudeDegrees), abs(latitudeMinutes),
                                     abs(latitudeSeconds), latitudeCardinalDirection)
    return latitudeDescription
}

func latlon2DMS(longitude: Double) -> String {
    var longitudeSeconds = longitude * 3600
    let longitudeDegrees = longitudeSeconds / 3600
    longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 3600)
    let longitudeMinutes = longitudeSeconds / 60
    longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 60)
    let longitudeCardinalDirection = longitudeDegrees >= 0 ? "E" : "W"
    let longitudeDescription = String(format: "%.2f° %.2f' %.2f\" %@",
                                      abs(longitudeDegrees), abs(longitudeMinutes),
                                      abs(longitudeSeconds), longitudeCardinalDirection)
    return longitudeDescription
}

Call to it with

print(latlon2DMS(latitude: coordLat))
print(latlon2DMS(longitude: coordLong))

latitude.text = latlon2DMS(latitude: coordLat)
longitude.text = latlon2DMS(longitude: coordLong)


回答5:

I slightly modified Josue V.'s code to work in a timer that updates the location frequently

        if( CLLocationManager.authorizationStatus() == .authorizedWhenInUse ||
            CLLocationManager.authorizationStatus() ==  .authorizedAlways){
        let currentLocation = locationManager.location
        var latitudeSeconds = currentLocation!.coordinate.latitude * 3600
        let latitudeDegrees = latitudeSeconds / 3600

            latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 3600)

        let latitudeMinutes = latitudeSeconds / 60

            latitudeSeconds = latitudeSeconds.truncatingRemainder(dividingBy: 60)

        var longitudeSeconds = currentLocation!.coordinate.longitude * 3600
        let longitudeDegrees = longitudeSeconds / 3600

            longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 3600)

        let longitudeMinutes = longitudeSeconds / 60

            longitudeSeconds = longitudeSeconds.truncatingRemainder(dividingBy: 60)

        let latitudeCardinalDirection = latitudeDegrees >= 0 ? "N" : "S"
        let longitudeCardinalDirection = longitudeDegrees >= 0 ? "E" : "W"

        let latitudeDescription = String(format:"%.2f°%.2f'%.2f\"%@",
                                         abs(latitudeDegrees), abs(latitudeMinutes),
                                         abs(latitudeSeconds), latitudeCardinalDirection)

        let longitudeDescription = String(format:"%.2f°%.2f'%.2f\"%@",
                                          abs(longitudeDegrees), abs(longitudeMinutes),
                                          abs(longitudeSeconds), longitudeCardinalDirection)

        cell5.text = latitudeDescription + " " + longitudeDescription

        }
    }

and the timer

timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(coordinate), userInfo: nil, repeats: true)



标签: swift gps xcode6