Rysowanie trasy w MapKit w iPhone SDK

głosy
53

Chcę narysować trasę pomiędzy dwiema lokalizacjami na mapie. Coś takiego przewodnika. Gdy turysta kliknie inną lokalizację, chcę móc narysować drogę; jak również informuje o odległości od aktualnej pozycji.

Jestem świadomy stron w Internecie, które mówią jak rysować polilinie na mapie. Ale większość przykładów miał załadowane plik .csv z różnych współrzędnych.

Czy istnieje alternatywny sposób, aby uzyskać współrzędne od Google lub innego dostawcy, a lokalizacja jest wybrany dynamicznie.

Jeśli nie, w jaki sposób mogę uzyskać informacje o współrzędnych pośrednich?

Czy iOS 6 dostarczyć jakikolwiek bezpośredni sposób do tego problemu?

Utwórz 14/05/2010 o 14:37
źródło użytkownik
W innych językach...                            


9 odpowiedzi

głosy
61

Dodaje viewDidLoadsię (1) ustawić dwie lokalizacje, (2) Usunąć wszystkie poprzednie adnotacje, oraz (3) połączenia zdefiniowane przez użytkownika funkcje pomocnicze (aby otrzymać punkty trasy i wyciągnąć trasy).

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

Poniżej przedstawiono MKMapViewDelegatesposób, który opiera się nakładkę (iOS 4,0 i później).

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

Poniższa funkcja dostanie obie lokalizacje i przygotować URL, aby wszystkie punkty trasy. I oczywiście, wezwie 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]];
}

Poniższy kod jest prawdziwa magia (dekoder na odpowiedź dostaliśmy od API). I nie byłoby zmodyfikować ten kod, chyba wiem co robie :)

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

Ta funkcja rysowania trasy i doda nakładkę.

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

Poniższy kod skoncentruje ustawić mapę.

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

Mam nadzieję, że to pomoże ktoś.

Odpowiedział 12/08/2012 o 18:21
źródło użytkownik

głosy
24

To jest podchwytliwe. Nie ma sposobu, aby to zrobić z MapKit: to dość łatwe do rysowania linii, gdy wiesz, współrzędne, ale MapKit nie da Ci dostęp do dróg lub innych informacji routingu. Powiedziałbym, że trzeba zadzwonić do zewnętrznego interfejsu API, aby uzyskać dane.

Grałem z cloudmade.com API. Serwer strumień wektora powinien powrócić, co trzeba, a następnie można wyciągnąć, że w ciągu swojej mapie. Jednak rozbieżności pomiędzy mapami Google i OSM map używanych przez CloudMade mogą chcesz użyć CloudMade mapach wszystkie sposób: mają równoważnym do MapKit.

PS: Inni dostawcy map - Google, Bing, itd. Mogą również zapewnić równoważne dane kanałów. Właśnie został patrząc na OSM / CloudMade niedawno.

PPS: Nic z tego nie jest trywialne początkujących rzeczy! Powodzenia!

Odpowiedział 14/05/2010 o 14:59
źródło użytkownik

głosy
12

Andiih got it right. MapKit Nie pozwolę ci tego zrobić. Niestety, Google nie pozwoli Ci robić to, co chcesz zrobić, albo.

Kiedy Apple ogłosiła MapKit i wszystko, ale także wyraźnie zaznaczyć, że wszelkie aplikacje nawigacyjne byłoby BYOM: Przynieś własne mapy, więc każda aplikacja nawigacji wykorzystuje swój własny zestaw narzędzi mapowania.

Warunki korzystania z usług Google ogranicza cię od nawet wyświetlania trasy na szczycie swoich map:

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

Ograniczenia licencyjne:

10,9 korzystania z Usługi lub Treści wszelkich produktów, systemów i aplikacji w celu lub w związku z:

(A) w czasie rzeczywistym lub nawigacja nawigacja, włączając, lecz nie ograniczając się do turn-by-turn prowadzenie, który jest zsynchronizowany z czujnikiem położenia urządzenia obsługujące użytkownika;

(B) ewentualne układy lub funkcje automatycznego lub niezależnego sterowania pojazdem; lub

(C) w sklepie, zarządzanie flotą, śledzenie zasobów firmy, lub podobnej aplikacji korporacyjnych (API Google Maps mogą być wykorzystywane do śledzenia zasobów (takich jak samochody, autobusy i inne pojazdy), o ile aplikacji śledzenia są udostępniane publicznie bez ładunek. Na przykład, można zaoferować bezpłatne, publiczne Maps API Wdrożenie który wyświetla w czasie rzeczywistym transportu publicznego lub inne informacje o stanie transportu.

Niestety, dotyczy to, co chcesz robić. Mam nadzieję, że jeden dzień MapKit zostanie rozszerzony, aby umożliwić takie cechy ... chociaż mało prawdopodobne.

Powodzenia.

Odpowiedział 14/05/2010 o 19:54
źródło użytkownik

głosy
5

Czasami warto spojrzeć na https://github.com/leviathan/nvpolyline To rozwiązanie jest szczególnie ukierunkowana na wersji iPhone OS przed v.4.0

Chociaż może to być również stosowany w v.4.0 nadzieję, że to pomaga.

Odpowiedział 01/07/2010 o 15:22
źródło użytkownik

głosy
4

Try MapKit-Route-Kierunki ( github ).

Odpowiedział 05/01/2011 o 08:06
źródło użytkownik

głosy
3

Uzyskanie i rysując trasę na mapie jest bardzo proste z 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];
    }
}];
Odpowiedział 14/02/2015 o 16:46
źródło użytkownik

głosy
3

Właśnie w celu wyjaśnienia, wygląda na to istnieje kilka rzeczy omawiane. Jednym z nich jest sposób, aby wierzchołki trasy, a drugi jest zwrócenie nakładkę na mapie przy użyciu tych wierzchołków. Wiem API MapQuest, więc mam kilka linków do tych poniżej - Google i Bing mają odpowiedniki myślę.

1) Pierwsze wierzchołki trasy
Jeśli szukasz nowych współrzędnych trasy narysować nakładkę trasy, można użyć wywołanie usługi sieci Web do routingu usługi internetowej - Zakładam, że używasz JavaScript, żeby wyświetlić mapę. Jeśli używasz kodu macierzystego, można jeszcze trafić usługi internetowej lub użyć natywnego połączenia (czyli MapQuest iPhone SDK posiada natywną połączenia trasy w nim).

Większość usług wskazówki powinny zwrócić „shapepoints” w trasie tak, że można narysować.

Oto kilka przykładów z wykorzystaniem MapQuest- usługi sieci Web, aby uzyskać wskazówki shapepoints (patrz obiekt powrotną Shape) - http://www.mapquestapi.com/directions/

2) Rysunek nakładkę
Gdy masz swoje wierzchołki, trzeba je wyciągnąć. Myślę, że większość map JavaScript API będzie mieć klasę nakładki pewnego rodzaju. Oto MapQuest jeden: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Robi to z jednej rozmowy
MapQuest również pewne funkcje convenience, aby nawiązać połączenie trasy i narysować linię dla Ciebie - nie mogę dodawać więcej niż dwa linki! Więc idź do linku powyżej i poszukaj „routing” w pasku nawigacyjnym po lewej stronie.

Odpowiedział 12/03/2012 o 17:09
źródło użytkownik

głosy
3

MapQuest ma SDK, który jest zamiennikiem drop-in dla MapKit. Jest obecnie w fazie beta, ale pod aktywnego rozwoju.

Pozwala to nakładki, routing i geokodowanie.

MapQuest iOS Maps API

Odpowiedział 05/03/2012 o 00:45
źródło użytkownik

głosy
2

Aby zaktualizować to pytanie, nie ma potrzeby, aby apk zewnętrznego od iOS7.

Tutaj bardzo proste i skuteczne rozwiązanie:

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

Wiem, że pytanie było o iOS 6, ale wierzę, że to rozwiązanie będzie przydatne dla wielu ludzi.

Jedyną rzeczą, której brakowało w tym roztworze realizuje następującą metodę delegata, aby wyświetlić rozpoczęcia i zakończenia kołka

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Odpowiedział 25/02/2015 o 08:30
źródło użytkownik

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