uerceg
uerceg

Reputation: 4807

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;
}

Upvotes: 5

Views: 1304

Answers (2)

Cyril Godefroy
Cyril Godefroy

Reputation: 1400

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.

Upvotes: 1

Marcelo
Marcelo

Reputation: 9407

I believe that the projection used by MapKit is different than that used by Google Maps. MapKit uses Cylindrical Mercator, while Google uses a variant of the Mercator Projection.

Converting Between Coordinate Systems Although you normally specify points on the map using latitude and longitude values, there may be times when you need to convert to and from other coordinate systems. For example, you typically use map points when specifying the shape of overlays.

Quoted from Apple:

Upvotes: 0

Related Questions