22

Whenever the user zoom in or out the map i need to know how many meters are currently represented on the map (width or height).

What i need is the inverse function of MKCoordinateRegionMakeWithDistance to calculate the distance represented by the current map span.

I tried the following code but i get wrong results :

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
    MKMapRect mRect = self.map.visibleMapRect;
    MKMapPoint northMapPoint = MKMapPointMake(MKMapRectGetMidX(mRect), MKMapRectGetMinY(mRect));
    MKMapPoint southMapPoint = MKMapPointMake(MKMapRectGetMidX(mRect), MKMapRectGetMaxY(mRect));

    self.currentDist = MKMetersBetweenMapPoints(northMapPoint, southMapPoint);
}

If i set the map region to 1500 meters i get something like 1800 as a result..

Thanks for your help, Vincent

vdaubry
  • 11,369
  • 7
  • 54
  • 76

6 Answers6

42

Actually it was a really stupid mistake, if i do the same operation along the X axis then i get the correct value :

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
MKMapRect mRect = self.map.visibleMapRect;
MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect));
MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect));

self.currentDist = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint);
}
vdaubry
  • 11,369
  • 7
  • 54
  • 76
18
- (void)mapView:(MKMapView *)map regionDidChangeAnimated:(BOOL)animated {
  MKCoordinateSpan span = mapView.region.span;
  NSLog(@" 1 = ~111 km -> %f = ~ %f km ",span.latitudeDelta,span.latitudeDelta*111);
}

According to the docs http://developer.apple.com/library/ios/#documentation/MapKit/Reference/MapKitDataTypesReference/Reference/reference.html,

latitudeDelta

The amount of north-to-south distance (measured in degrees) to display on the map. Unlike longitudinal distances, which vary based on the latitude, one degree of latitude is always approximately 111 kilometers (69 miles).

johndpope
  • 5,035
  • 2
  • 41
  • 43
  • Thanks, this works so i upvoted you. But i think this solution is kind of unclean (the calculation makes the code harder to read, and you have approximation in the result) – vdaubry Apr 28 '11 at 04:26
4

Thanks for the post all. I have an app that required a mile radius to figure out how many location records to fetch so this came in handy. Here is the swift equivalent for anyone who might come across this in the future.

let mRect: MKMapRect = self.mapView.visibleMapRect
        let eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect))
        let westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect))
        let currentDistWideInMeters = MKMetersBetweenMapPoints(eastMapPoint, westMapPoint)
        let milesWide = currentDistWideInMeters / 1609.34  // number of meters in a mile
        println(milesWide)
Christopher Wade Cantley
  • 7,122
  • 5
  • 35
  • 48
2

Swift 4.2

    func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {

        let mapRect = mapView.visibleMapRect
        let westMapPoint = MKMapPoint(x: mapRect.minX, y: mapRect.midY)
        let eastMapPoint = MKMapPoint(x: mapRect.maxX, y: mapRect.midY)
        let visibleDistance = westMapPoint.distance(to: eastMapPoint)
    }
rbaldwin
  • 4,581
  • 27
  • 38
1

Here's an easier way (to get width and height in meters)...

- (void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated {

    MKMapRect rect = mapView.visibleMapRect;

    double mapWidth = MKMapRectGetWidth(rect) / 10;
    double mapHeight = MKMapRectGetHeight(rect) / 10;

}
Nico teWinkel
  • 870
  • 11
  • 19
  • 1
    works well, thanks. Wondering why you divide them by 10, though. – Shyam Bhat Nov 12 '12 at 10:52
  • actually, I don't remember why it was 10, and looking at it now I think that might not actually be accurate for all places - it looks like MapRects are in "map points", and it appears that the proper math would include a conversion using something like MKMetersBetweenMapPoints, as the above answer shows. Sorry, I don't know for sure. – Nico teWinkel Jan 02 '13 at 22:41
0

Swift 4

extension MKMapView {
  func regionInMeter() -> CLLocationDistance {
    let eastMapPoint = MKMapPointMake(MKMapRectGetMinX(visibleMapRect), MKMapRectGetMidY(visibleMapRect))
    let westMapPoint = MKMapPointMake(MKMapRectGetMaxX(visibleMapRect), MKMapRectGetMidY(visibleMapRect))

    return MKMetersBetweenMapPoints(eastMapPoint, westMapPoint)
  }
}
onmyway133
  • 45,645
  • 31
  • 257
  • 263