Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Google Maps iOS SDK: Distance between east and west points on the map

How can I calculate the distance (in meters) between the east point and the west point of the map? Suppose the user changed the position scrolling the map, then I catch the movement with mapView:didChangeCameraPosition: delegate method, but I don't know how to calculate the distance.

like image 241
Luca Torella Avatar asked May 31 '13 08:05

Luca Torella


1 Answers

Here's a helper function which can be used to calculate the distance in metres between two coordinates:

double getDistanceMetresBetweenLocationCoordinates(
    CLLocationCoordinate2D coord1, 
    CLLocationCoordinate2D coord2)
{
    CLLocation* location1 = 
        [[CLLocation alloc] 
            initWithLatitude: coord1.latitude 
            longitude: coord1.longitude];
    CLLocation* location2 = 
        [[CLLocation alloc] 
            initWithLatitude: coord2.latitude 
            longitude: coord2.longitude];

    return [location1 distanceFromLocation: location2];
}

UPDATE:

It depends what you mean by 'east' and 'west' of the map, since the map may be rotated or tilted. Even if it's not tilted or rotated, due to the curvature of the earth, the width of the map will be different in metres between the top of the map and the bottom (the edge closer to the equator will be wider in metres than the edge which is further from the equator). The difference will be less the more zoomed in you are.

But supposing you wanted to get the distance in metres between the bottom left and bottom right corners of the map, you could use this:

GMSMapView* mapView = ...;

CLLocationCoordinate2D bottomLeftCoord = 
    mapView.projection.visibleRegion.nearLeft;
CLLocationCoordinate2D bottomRightCoord = 
    mapView.projection.visibleRegion.nearRight;
double distanceMetres = getDistanceMetresBetweenLocationCoordinates(
    bottomLeftCoord, bottomRightCoord);

If you want to factor in rotation/tilt, you could wrap the visible region in a GMSCoordinateBounds, and then calculate the distance between the south east and south west corners, for example:

GMSMapView* mapView = ...;

GMSCoordinateBounds* bounds = [[GMSCoordinateBounds alloc] 
    initWithRegion: mapView.projection.visibleRegion];
CLLocationCoordinate2D southWest = bounds.southWest;
CLLocationCoordinate2D southEast = CLLocationCoordinate2DMake(
    bounds.southWest.latitude, bounds.northEast.longitude);
double distanceMetres = getDistanceMetresBetweenLocationCoordinates(
    southWest, southEast);

However, this could be wider than the area actually visible on the screen, as the GMSCoordinateBounds wraps the quadrilateral of the visible region in an axis-aligned bounding box.

Another option would be to choose points on each side of the map view's frame, then use the map view's projection to convert these into lat/lon, for example:

GMSMapView* mapView = ...;

CGPoint middleLeftPoint = CGPointMake(
    0, mapView.frame.size.height / 2);
CGPoint middleRightPoint = CGPointMake(
    mapView.frame.size.width, mapView.frame.size.height / 2);

CLLocationCoordinate2D middleLeftCoord = 
    [mapView.projection coordinateForPoint: middleLeftPoint];
CLLocationCoordinate2D middleRightCoord = 
    [mapView.projection coordinateForPoint: middleRightPoint];

double distanceMetres = getDistanceMetresBetweenLocationCoordinates(
    middleLeftCoord, middleRightCoord);
like image 61
Saxon Druce Avatar answered Oct 07 '22 16:10

Saxon Druce