Рисование маршрута в MapKit в iPhone SDK


Я хочу нарисовать маршрут между двумя точками на карте. Что-то вроде гида. Когда турист нажимает другое место, я хочу иметь возможность нарисовать маршрут; а также сообщить о расстоянии от текущего местоположения.

Я знаю сайты в Интернете, которые рассказывают как рисовать полилинии на карте. Но, большинство примеров были предварительно загружены .CSV-файл с различными координатами.

есть ли альтернативный способ получить координаты от Google или любой другой провайдер, так как расположение выбирается динамически.

Если нет, то как я могу получить информацию для промежуточных координат?

обеспечивает ли iOS 6 какой-либо прямой путь для этой проблемы?

9 53

9 ответов:

Это сложный вопрос. Это невозможно сделать с помощью MapKit: достаточно легко рисовать линии, когда вы знаете координаты, но MapKit не даст вам доступ к дорогам или другой информации о маршруте. Я бы сказал, что вам нужно вызвать внешний API, чтобы получить ваши данные.

Я играю с cloudmade.com API-интерфейс. Сервер векторного потока должен возвращать то, что вам нужно, а затем вы можете нарисовать это на своей карте. Тем не менее, расхождения между картами Google и OSM карты, используемые cloudmade, могут заставить вас использовать cloudmade maps полностью: у них есть эквивалент MapKit.

P. S.: У других поставщиков карт - Гугл, Бинг и т. д. может также предоставлять эквивалентные каналы данных. Я просто недавно смотрел на OSM/Cloudmade.

P. P. S.: ничто из этого не является тривиальным новичком! Удачи вам!

следующее viewDidLoad will (1) установить два местоположения, (2) удалить все предыдущие аннотации и (3) вызвать пользовательские вспомогательные функции (чтобы получить точки маршрута и нарисовать маршрут).

-(void)viewDidLoad
{
    [super viewDidLoad];

    // Origin Location.
    CLLocationCoordinate2D loc1;
    loc1.latitude = 29.0167;
    loc1.longitude = 77.3833;
    Annotation *origin = [[Annotation alloc] initWithTitle:@"loc1" subTitle:@"Home1" andCoordinate:loc1];
    [objMapView addAnnotation:origin];

    // Destination Location.
    CLLocationCoordinate2D loc2;
    loc2.latitude = 19.076000;
    loc2.longitude = 72.877670;
    Annotation *destination = [[Annotation alloc] initWithTitle:@"loc2" subTitle:@"Home2" andCoordinate:loc2];
    [objMapView addAnnotation:destination];

    if(arrRoutePoints) // Remove all annotations
        [objMapView removeAnnotations:[objMapView annotations]];

    arrRoutePoints = [self getRoutePointFrom:origin to:destination];
    [self drawRoute];
    [self centerMap];
}

следующее MKMapViewDelegate метод, который рисует наложение (iOS 4.0 и более поздние версии).

/* MKMapViewDelegate Meth0d -- for viewForOverlay*/
- (MKOverlayView*)mapView:(MKMapView*)theMapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineView *view = [[MKPolylineView alloc] initWithPolyline:objPolyline];
    view.fillColor = [UIColor blackColor];
    view.strokeColor = [UIColor blackColor];
    view.lineWidth = 4;
    return view;
}

следующая функция получит оба местоположения и подготовит URL, чтобы получить все точки маршрута. И конечно, вызовет stringWithURL.

/* This will get the route coordinates from the Google API. */
- (NSArray*)getRoutePointFrom:(Annotation *)origin to:(Annotation *)destination
{
    NSString* saddr = [NSString stringWithFormat:@"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
    NSString* daddr = [NSString stringWithFormat:@"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];

    NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
    NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];

    NSError *error;
    NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
    NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\"([^\\"]*)\\"" capture:1L];

    return [self decodePolyLine:[encodedPoints mutableCopy]];
}

следующий код-это настоящая магия (декодер для ответа, который мы получили от API). Я бы не стал изменять этот код, если я не знаю, что я делаю:)

- (NSMutableArray *)decodePolyLine:(NSMutableString *)encodedString
{
    [encodedString replaceOccurrencesOfString:@"\\" withString:@"\"
                                  options:NSLiteralSearch
                                    range:NSMakeRange(0, [encodedString length])];
    NSInteger len = [encodedString 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 = [encodedString 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 = [encodedString 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];
        printf("\n[%f,", [latitude doubleValue]);
        printf("%f]", [longitude doubleValue]);
        CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:loc];
    }
    return array;
}

эта функция нарисует маршрут и добавит наложение.

- (void)drawRoute
{
    int numPoints = [arrRoutePoints count];
    if (numPoints > 1)
    {
        CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < numPoints; i++)
        {
            CLLocation* current = [arrRoutePoints objectAtIndex:i];
            coords[i] = current.coordinate;
        }

        self.objPolyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
        free(coords);

        [objMapView addOverlay:objPolyline];
        [objMapView setNeedsDisplay];
    }
}

следующий код выравнивает карту по центру.

- (void)centerMap
{
    MKCoordinateRegion region;

    CLLocationDegrees maxLat = -90;
    CLLocationDegrees maxLon = -180;
    CLLocationDegrees minLat = 90;
    CLLocationDegrees minLon = 180;

    for(int idx = 0; idx < arrRoutePoints.count; idx++)
    {
        CLLocation* currentLocation = [arrRoutePoints objectAtIndex:idx];

        if(currentLocation.coordinate.latitude > maxLat)
            maxLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.latitude < minLat)
            minLat = currentLocation.coordinate.latitude;
        if(currentLocation.coordinate.longitude > maxLon)
            maxLon = currentLocation.coordinate.longitude;
        if(currentLocation.coordinate.longitude < minLon)
            minLon = currentLocation.coordinate.longitude;
    }

    region.center.latitude     = (maxLat + minLat) / 2;
    region.center.longitude    = (maxLon + minLon) / 2;
    region.span.latitudeDelta  = maxLat - minLat;
    region.span.longitudeDelta = maxLon - minLon;

    [objMapView setRegion:region animated:YES];
}

Я надеюсь, что это поможет кому-то.

Andiih получил это право. MapKit не позволит вам сделать это. К сожалению, Google не позволит вам делать то, что вы хотите делать.

когда Apple объявила MapKit и все, они также явно заявили, что любые навигационные приложения будут BYOM: принесите свои собственные карты, поэтому любое навигационное приложение использует свой собственный набор инструментов отображения.

условия предоставления услуг Google ограничивают вас даже от отображения маршрутов поверх их карты:

http://code.google.com/intl/de/apis/maps/iphone/terms.html

Лицензионные Ограничения:

10.9 используйте сервис или контент с любыми продуктами, системами или приложениями за или в связи с:

(a) навигация или маршрут в реальном времени рекомендации, включая, но не ограничиваясь пошаговые указания маршрута синхронизируется на должность пользователя сенсорное устройство;

(b) любые системы или функции для автоматическое или автономное управление поведение транспортного средства; или

(c) диспетчеризация, управление автопарком, отслеживание бизнес-активов, или аналогичные корпоративные приложения (Google Maps API можно использовать для отслеживания активов (как автомобили, автобусы или другое транспортных средств) до тех пор, как отслеживание приложение стало доступно общественных местах без оплаты. Например, вы можете предложить бесплатный, общедоступный API Карт Реализация, которая отображает в режиме реального времени общественным транспортом или другими видами транспорта информация о состоянии.

к сожалению, это включает в себя то, что вы хотели бы сделать. Надеюсь, однажды MapKit будет расширен, чтобы позволить такие функции... хотя вряд ли.

удачи.

возможно, вы захотите взглянуть на https://github.com/leviathan/nvpolyline это решение особенно ориентировано на версии iPhone OS до V. 4. 0

хотя он также может быть использован в v. 4. 0 надеюсь, что это поможет.

попробовать MapKit-Route-Directions (GitHub).

MapQuest имеет SDK, который является заменой для MapKit. В настоящее время он находится в бета-версии, но в активной разработке.

Он позволяет накладывать, маршрутизировать и геокодировать.

MapQuest iOS Maps API

просто чтобы уточнить, похоже, что есть несколько вещей, которые обсуждаются. Один из них-это способ получить вершины маршрута, а другой-нарисовать наложение на карте, используя эти вершины. Я знаю API MapQuest, поэтому у меня есть некоторые ссылки для тех, кто ниже - Google и Bing есть аналоги, я думаю.

1) Получение вершин маршрута
Если вы ищете новые координаты маршрута, чтобы нарисовать наложение маршрута, вы можете использовать вызов веб-службы веб-служба маршрутизации-я предполагаю, что вы используете JavaScript здесь для отображения карты. Если вы используете собственный код, вы все равно можете попасть в веб-службу или использовать собственный вызов (то есть в MapQuest iPhone SDK есть собственный вызов маршрута).

большинство сервисов направлений должны возвращать "точки формы" маршрута, чтобы вы могли рисовать.

вот несколько примеров использования MapQuest- Направления веб-службы для получения точек формы (см. Объект возврата формы) - http://www.mapquestapi.com/directions/

2) рисование оверлея
Как только у вас есть свои вершины, вам нужно их нарисовать. Я думаю, что большинство API Карт JavaScript будут иметь какой-то класс наложения. Вот один из MapQuest: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) делать это с одного звонка
MapQuest также имеет некоторые функции удобства, чтобы сделать вызов маршрута и нарисовать линию для вы - я не могу разместить больше двух ссылок! Поэтому перейдите по ссылке выше и найдите "маршрутизацию" в панели навигации слева.

получение и рисование маршрута на карте очень легко с iOS 7 API:

MKDirectionsRequest *directionsRequest = [[MKDirectionsRequest alloc] init];

// Set the origin of the route to be current user location
[directionsRequest setSource:[MKMapItem mapItemForCurrentLocation]];

// Set the destination point of the route
CLLocationCoordinate2D destinationCoordinate = CLLocationCoordinate2DMake(34.0872, 76.235);
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoordinate addressDictionary:nil];
[directionsRequest setDestination:[[MKMapItem alloc] initWithPlacemark:destinationPlacemark]];

MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];

// Requesting route information from Apple Map services
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
    if (error) {
        NSLog(@"Cannot calculate directions: %@",[error localizedDescription]);
    } else {
        // Displaying the route on the map
        MKRoute *route = [response.routes firstObject];
        [mapView addOverlay:route.polyline];
    }
}];

чтобы обновить этот вопрос, нет необходимости во внешнем apk с iOS7.

здесь очень простое и эффективное решение :

http://technet.weblineindia.com/mobile/draw-route-between-2-points-on-map-with-ios7-mapkit-api/2/

Я знаю, что вопрос был об iOS 6, но я считаю, что это решение будет полезно для многих людей.

единственное, что отсутствует в этом решении, - это реализация следующего метода делегирования отображение начала и конца pin

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation