6
votes

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.

3

3 Answers

10
votes

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);
4
votes

The Google Maps iOS SDK contains a bunch of geometry helpers.

You want this function:

GMSGeometryDistance (CLLocationCoordinate2D from, CLLocationCoordinate2D to) -> CLLocationDistance

"Returns the great circle distance between two coordinates, in meters, on Earth. This is the shortest distance between the two coordinates on the sphere. Both coordinates must be valid."

0
votes

Heres the code for finding distance between two points

 AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData];

NSString *urlString =@"https://maps.googleapis.com/maps/api/directions/json";

 NSDictionary *dictParameters = @{@"origin" : [NSString stringWithFormat:@"%@",_sourceAdd], @"destination" : [NSString stringWithFormat:@"%@",_destinationAdd], @"mode" : @"driving", @"key":@"AIzaSyD9cWTQkAxemELVXTNUCALOmzlDv5b9Dhg"};

[manager GET:urlString parameters:dictParameters success:^(AFHTTPRequestOperation *operation, id responseObject) {



    NSDictionary *arr=responseObject[@"routes"][0][@"legs"];
    NSMutableArray *loc=[[NSMutableArray alloc]init];    

    NSString *dis,*dur;
    loc=[[arr valueForKey:@"distance"]valueForKey:@"text"];
    dis=loc[0];

    loc=[[arr valueForKey:@"duration"]valueForKey:@"text"];
    dur=loc[0];


   UIAlertView *av=[[UIAlertView alloc]initWithTitle:@"Route Info" message:[NSString stringWithFormat:@"Distance:%@ \nDuration:%@",dis,dur] delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
    [av show];


} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
    NSLog(@"Error: %@", error);
}];