Reverse function of MKCoordinateRegionMakeWithDistance?

688 Views Asked by At

MapKit's built in function MKCoordinateRegionMakeWithDistance takes distances in meters and turns them into a MKCoordinateRegion:

func MKCoordinateRegionMakeWithDistance(
    _ centerCoordinate: CLLocationCoordinate2D, 
    _ latitudinalMeters: CLLocationDistance, 
    _ longitudinalMeters: CLLocationDistance) 
        -> MKCoordinateRegion

is there a reverse function that takes a MKCoordinateRegion and gives me latitudinalMeters and longitudinalMeters?

2

There are 2 best solutions below

0
On BEST ANSWER

MKCoordinateRegion gives a center (latitude and longitude) and span (delta latitude and longitude). Given these values, you can determine the location of the edges of the region in latitude and longitude. Once you do that, you can use the haversine formula to obtain latitudinal and longitudinal distances, and you already know the center. In fact, CLLocation has a function distanceFromLocation:(const CLLocation *)location which you should use to avoid a direct implementation of the formula.

0
On

Based on Adam H.s idea, this is my implementation in Swift 4 with unit tests:

extension MKCoordinateRegion {
    /// middle of the south edge
    var south: CLLocation {
        return CLLocation(latitude: center.latitude - span.latitudeDelta / 2, longitude: center.longitude)
    }
    /// middle of the north edge
    var north: CLLocation {
        return CLLocation(latitude: center.latitude + span.latitudeDelta / 2, longitude: center.longitude)
    }
    /// middle of the east edge
    var east: CLLocation {
        return CLLocation(latitude: center.latitude, longitude: center.longitude + span.longitudeDelta / 2)
    }
    /// middle of the west edge
    var west: CLLocation {
        return CLLocation(latitude: center.latitude, longitude: center.longitude - span.longitudeDelta / 2)
    }
    /// distance between south and north in meters. Reverse function for MKCoordinateRegionMakeWithDistance
    var latitudinalMeters: CLLocationDistance {
        return south.distance(from: north)
    }
    /// distance between east and west in meters. Reverse function for MKCoordinateRegionMakeWithDistance
    var longitudinalMeters: CLLocationDistance {
        return east.distance(from: west)
    }
}

Unit test:

func testMKCoordinateRegionMakeWithDistance() {
    // arbitrary parameters
    let center = CLLocationCoordinate2DMake(49, 9)
    let latitudinalMeters: CLLocationDistance = 1000
    let longitudinalMeters: CLLocationDistance = 2000

    let region = MKCoordinateRegionMakeWithDistance(center, latitudinalMeters, longitudinalMeters)
    XCTAssertEqual(latitudinalMeters, round(region.latitudinalMeters*100)/100)
    XCTAssertEqual(longitudinalMeters, round(region.longitudinalMeters*100)/100)
}

test design:

  • use different numbers for lat and long to find errors where variables are mixed up
  • rounding checks for about 5 significant decimal places