Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MapKit - Make route line follow streets when map zoomed in

I wrote simple application which draws route between two locations on MapKit. I am using Google Map API. I used resources I found online and here's the code I am using to make request to Google:

_httpClient = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:@"http://maps.googleapis.com/"]];
    [_httpClient registerHTTPOperationClass: [AFJSONRequestOperation class]];
    [_httpClient setDefaultHeader:@"Accept" value:@"application/json"];

    NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
    [parameters setObject:[NSString stringWithFormat:@"%f,%f", coordinate.latitude, coordinate.longitude] forKey:@"origin"];
    [parameters setObject:[NSString stringWithFormat:@"%f,%f", endCoordinate.latitude, endCoordinate.longitude] forKey:@"destination"];
    [parameters setObject:@"true" forKey:@"sensor"];

    NSMutableURLRequest *request = [_httpClient requestWithMethod:@"GET" path: @"maps/api/directions/json" parameters:parameters];
    request.cachePolicy = NSURLRequestReloadIgnoringLocalCacheData;

    AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];    
    [operation  setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject){
        NSInteger statusCode = operation.response.statusCode;

        if (statusCode == 200)
        {
            NSLog(@"Success: %@", operation.responseString);
        }
        else
        {
            NSLog(@"Status code = %d", statusCode);
        }
    }
                                      failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                          NSLog(@"Error: %@",  operation.responseString);

                                      }
     ];

    [_httpClient enqueueHTTPRequestOperation:operation];

This works flawlessly. When I run this and try to show route between LA and Chicago, here's how it looks like:

LA - Chicago route zoomed out

BUT. When I zoom map to street level, here's how route looks like:

LA - Chicago route zoomed in

Does anyone know how can I achieve that route I am drawing follows streets when map is zoomed? I'd like route to show exact path through the streets. I don't know if some additional parameter needs to be added to my request to Google.

Any help or advice would be great. Many thanks in advance!


[edit #1: Adding request URL and response from Google]

My request URL after creating operation object from code above looks like this:

http://maps.googleapis.com/maps/api/directions/json?sensor=true&destination=34%2E052360,-118%2E243560&origin=41%2E903630,-87%2E629790

Just paste that URL to your browser and you will see the JSON data Google sends as the response which I get in my code also.


[edit #2: Parsing answer from Google and building the path]

- (void)parseResponse:(NSData *)response
{
    NSDictionary *dictResponse = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableContainers error:nil];
    NSArray *routes = [dictResponse objectForKey:@"routes"];
    NSDictionary *route = [routes lastObject];

    if (route)
    {
        NSString *overviewPolyline = [[route objectForKey: @"overview_polyline"] objectForKey:@"points"];
        _path = [self decodePolyLine:overviewPolyline];
    }
}

- (NSMutableArray *)decodePolyLine:(NSString *)encodedStr
{
    NSMutableString *encoded = [[NSMutableString alloc] initWithCapacity:[encodedStr length]];
    [encoded appendString:encodedStr];
    [encoded replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                options:NSLiteralSearch
                                  range:NSMakeRange(0, [encoded length])];
    NSInteger len = [encoded length];
    NSInteger index = 0;
    NSMutableArray *array = [[NSMutableArray alloc] init];
    NSInteger lat=0;
    NSInteger lng=0;

    while (index < len)
    {
        NSInteger b;
        NSInteger shift = 0;
        NSInteger result = 0;

        do
        {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);

        NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lat += dlat;
        shift = 0;
        result = 0;

        do
        {
            b = [encoded characterAtIndex:index++] - 63;
            result |= (b & 0x1f) << shift;
            shift += 5;
        } while (b >= 0x20);

        NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
        lng += dlng;
        NSNumber *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
        NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];

        CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:location];
    }

    return array;
}
like image 587
uerceg Avatar asked Nov 13 '22 19:11

uerceg


1 Answers

It looks like Google is not giving you all the points, or you are not looking at all the points. Actually, I'd expect polylines between placemarks, not only placemarks like you seem to have (with a straight line).

  • Check DirectionsStatus in the response to see if you are limited
  • Provide the json data that Google sends back.

I'm not so sure they use a radically different Mercator projection from the one used by Google.

like image 184
Cyril Godefroy Avatar answered Nov 15 '22 12:11

Cyril Godefroy