iOS - API Snap To Road с более чем 100 координатами

Я знаю, как использовать API привязки к дороге и анализировать ответ, отображать его на карте и т. Д. Однако API привязки к дороге имеет ограничение в 100 координат / запрос.

Допустим, у меня есть массив из 100+ координат, и я хочу, чтобы все они привязались к дороге.

Документы API Snap to Road описывают обходной путь при работе с более чем 100-ю координатами, однако это Java-код (я думаю), и я его не совсем понимаю.

Как я мог сделать это в Objective-C?

В моей реализации я вызываю привязку к дорогам api несколько раз, беря диапазоны в 100 координат из моего массива. Однако это приводит к странным полилиниям, когда рисуется на карте:

Вот мой код:

-(void)getDirectionsFrom:(CLLocation*)startLocation to:(CLLocation*)endLocation{

    //Create placemarks from the passed in locations
    MKPlacemark *start = [[MKPlacemark alloc] initWithCoordinate:locManager.location.coordinate addressDictionary:NULL];
    MKPlacemark *finsih = [[MKPlacemark alloc] initWithCoordinate:endLocation.coordinate addressDictionary:NULL];

    //Create direction request
    MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
    [request setSource:[[MKMapItem alloc] initWithPlacemark:start]];
    [request setDestination:[[MKMapItem alloc] initWithPlacemark:finsih]];
    [request setTransportType:MKDirectionsTransportTypeAutomobile];

    //Calculate directions
    MKDirections *direction = [[MKDirections alloc]initWithRequest:request];

    [direction calculateDirectionsWithCompletionHandler: ^(MKDirectionsResponse *response, NSError *error) {

        if (error) {
            NSLog(@"Error is %@",error);
        }

        else {

            MKRoute *route = [response.routes firstObject];

            NSUInteger pointCount = route.polyline.pointCount;

            //Allocate a C array to hold this many points/coordinates...
            CLLocationCoordinate2D *routeCoordinates = malloc(pointCount * sizeof(CLLocationCoordinate2D));

            //Get the coordinates (all of them)...
            [route.polyline getCoordinates:routeCoordinates range:NSMakeRange(0, pointCount)];

            NSMutableArray *locationsArray = [[NSMutableArray alloc] init];

            CLLocation *lastLocation = [[CLLocation alloc] init];


            //Call snap to road with 100 locations at a time
            for (int start = 0; start < pointCount; start += 99) {
                [locationsArray removeAllObjects];
                NSInteger length = MIN(99, pointCount-start);
                if(start != 0){
                    [locationsArray addObject:lastLocation];
                }
                for(int i = start;i<start+length;i++){
                    CLLocationCoordinate2D loc2D = routeCoordinates[i];
                    CLLocation *location = [[CLLocation alloc] initWithLatitude:loc2D.latitude longitude:loc2D.longitude];
                    [locationsArray addObject:location];
                }

                lastLocation = [locationsArray lastObject];
                [self snapPathToRoad:locationsArray];
            }

            //Free the memory used by the C array
            free(routeCoordinates);

        }
    }];

}


-(void)snapPathToRoad:(NSMutableArray*)passedInArray{

    //Create string to store coordinates in for the URL
    NSString *tempcoordinatesForURL = @"";

    //Append tempcoordinatesForURL string by the coordinates in the right format
    for(int i = 0;i<[passedInArray count];i++){

        CLLocationCoordinate2D coordinates = [[passedInArray objectAtIndex:i] coordinate];

        NSString *coordinatesString = [NSString stringWithFormat:@"|%f,%f|",coordinates.latitude,coordinates.longitude];

        tempcoordinatesForURL = [tempcoordinatesForURL stringByAppendingString:coordinatesString];
    }

    //Remove unnecessary charchters from tempcoordinatesForURL
    NSString *coordinatesForURL = [[tempcoordinatesForURL substringToIndex:[tempcoordinatesForURL length]-1] stringByReplacingOccurrencesOfString:@"||" withString:@"|"];

    //Create url by removing last charachter from coordinatesForURL string
    NSString *urlPath = [NSString stringWithFormat:@"https://roads.googleapis.com/v1/snapToRoads?path=%@&interpolate=true&key=AIzaSyDrtHA-AMiVVylUPcp46_Vf1eZJJFBwRCY",[coordinatesForURL substringFromIndex:1]];

    //Remove unsupproted charchters from urlPath and create an NSURL
    NSString *escapedUrlPath = [urlPath stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
    NSURL *url = [NSURL URLWithString:escapedUrlPath];

    //Create request
    NSURLRequest *request = [NSURLRequest requestWithURL:url];

    //Send request to server
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        //If response, parse JSON
        if(response){

            //Dictionary with the whole JSON file
            NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

            //Array of snapped points from the JSON
            NSArray *snappedPoints = [result objectForKey:@"snappedPoints"];

            //Loop through the snapped points array and add each coordinate to the path
            for (int i = 0; i<[snappedPoints count]; i++) {
                NSDictionary *location = [[snappedPoints objectAtIndex:i] objectForKey:@"location"];

                double latitude = [[location objectForKey:@"latitude"] doubleValue];
                double longitude = [[location objectForKey:@"longitude"] doubleValue];

                [pathToDraw addCoordinate:CLLocationCoordinate2DMake(latitude, longitude)];

            }

            //As this method is called multiple times, clear the previous polylines so only the final one will be visible on the map
            [self.mapView clear];

            //Draw polyline with path
            GMSPolyline *polyline = [GMSPolyline polylineWithPath:pathToDraw];
            polyline.map = self.mapView;
            polyline.strokeColor = [UIColor darkGrayColor];
            polyline.strokeWidth = 6;

        }

        //If error, log it
        else if(connectionError){
            NSLog(@"%@",connectionError);
        }

    }];

}

"patToDraw это GMSMutablePath Ивар"

1 ответ

Решение

В конце концов я нашел проблему.

Если несколько запросов вызываются асинхронно, не все они завершатся одновременно. Поскольку каждая из них добавляет координаты к одному и тому же пути, запросы с меньшим количеством координат, например, завершатся раньше, несмотря на то, что они были вызваны позже. Это приводит к тому, что координаты добавляются к пути в неправильном порядке.

Другие вопросы по тегам