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

голоса
53

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

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

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

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

Предоставляет ли IOS 6 любой прямой путь для этой проблемы?

Задан 14/05/2010 в 14:37
источник пользователем
На других языках...                            


9 ответов

голоса
61

Далее viewDidLoadбудет (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];
}

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

Ответил 12/08/2012 в 18:21
источник пользователем

голоса
24

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

Я играл с cloudmade.com API. Поток сервер вектора должен вернуть то , что вам нужно, а затем вы можете сделать , что над вашей картой. Однако расхождения между картами Google и OSM карты , используемые CloudMade может сделать вы хотите использовать CloudMade отображает все пути: они имеют эквивалент MapKit.

PS: Другие провайдеры картирования - Google, Bing и т.д., могут также предоставлять каналы эквивалента данных. Я просто смотрел на OSM / CloudMade недавно.

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

Ответил 14/05/2010 в 14:59
источник пользователем

голоса
12

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

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

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

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

Ограничения лицензии:

10,9 использовать Услуги или Содержание с любыми продуктами, системами или приложениями , или в связи с:

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

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

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

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

Удачи.

Ответил 14/05/2010 в 19:54
источник пользователем

голоса
5

Вы можете захотеть взглянуть на https://github.com/leviathan/nvpolyline Это решение особенно ориентирован на версии iPhone OS до v.4.0

Хотя он также может быть использован в v.4.0 Надеюсь, что это помогает.

Ответил 01/07/2010 в 15:22
источник пользователем

голоса
4

Попробуйте MapKit-Route-направление ( GitHub ).

Ответил 05/01/2011 в 08:06
источник пользователем

голоса
3

Получение и составление маршрута на карте супер просто с прошивкой 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];
    }
}];
Ответил 14/02/2015 в 16:46
источник пользователем

голоса
3

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

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

Большинство услуг направлений должны вернуть «shapepoints» маршрута, так что вы можете сделать.

Вот некоторые примеры использования MapQuest- направления веб - службы , чтобы получить shapepoints (см возвратной Формы объекта) - http://www.mapquestapi.com/directions/

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

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

Ответил 12/03/2012 в 17:09
источник пользователем

голоса
3

MapQuest есть SDK, что это капля в замене MapKit. Это в настоящее время в бета-версии, но при активном развитии.

Это позволяет накладки, маршрутизацию и геокодирование.

MapQuest IOS API Карт

Ответил 05/03/2012 в 00:45
источник пользователем

голоса
2

Чтобы обновить этот вопрос, нет необходимости внешнего APK, так как iOS7.

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

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

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

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

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Ответил 25/02/2015 в 08:30
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more