Disegnare un percorso in MapKit in iPhone SDK

voti
53

Voglio disegnare un itinerario tra due posizioni sulla mappa. Qualcosa di simile a una guida turistica. Quando il turista scatta un'altra posizione, voglio essere in grado di disegnare un percorso; così come, informare circa la distanza dalla posizione corrente.

Sono consapevole di siti su Internet che raccontano come disegnare polilinee sulla mappa. Ma, la maggior parte degli esempi aveva un file .csv precaricato con varie coordinate.

C'è un modo alternativo per ottenere le coordinate da Google o qualsiasi altro fornitore, come la posizione è selezionato in modo dinamico.

Se no, come faccio ad ottenere le informazioni per le coordinate intermedi?

Ha iOS 6 fornisce alcun modo diretto per questo problema?

È pubblicato 14/05/2010 alle 14:37
fonte dall'utente
In altre lingue...                            


9 risposte

voti
61

Di seguito viewDidLoadvi (1) impostare due località, (2) rimuovere tutte le annotazioni precedenti, e funzioni di supporto (3) dall'utente chiamata definito (per ottenere punti di rotta e disegnano il percorso).

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

Quanto segue è il MKMapViewDelegatemetodo, che attira overlay (iOS 4.0 e versioni successive).

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

La seguente funzione otterrà entrambe le posizioni e preparare URL per ottenere tutti i punti del percorso. E, naturalmente, chiamerà 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]];
}

Il codice seguente è la vera magia (decoder per la risposta che abbiamo ottenuto dal API). Non vorrei modificare il codice se non so quello che sto facendo :)

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

Questa funzione disegnerà un percorso e aggiungerà una sovrapposizione.

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

Il seguente codice centrerà allineare la mappa.

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

Spero che questo avrebbe aiutato qualcuno.

Risposto il 12/08/2012 a 18:21
fonte dall'utente

voti
24

Questo è un ingannevole. Non c'è modo di farlo con MapKit: è abbastanza facile per disegnare le linee quando si conoscono le coordinate, ma MapKit non darà l'accesso alle strade o altre informazioni di routing. Direi che è necessario chiamare un'API esterna per ottenere i dati.

Ho giocato con cloudmade.com API. Il server flusso vettore deve restituire ciò che è necessario, e poi si può disegnare quella sopra la vostra mappa. Tuttavia, le discrepanze tra le mappe di Google e gli OSM mappe utilizzate da CloudMade potrebbero farvi desiderare di utilizzare le mappe CloudMade tutta la strada: hanno un equivalente a MapKit.

PS: Altri fornitori di mappatura - Google, Bing, ecc possono anche fornire dati equivalenti feed. Ho appena stato a guardare OSM / CloudMade di recente.

PPS: Niente di tutto questo è roba newbie banale! Buona fortuna!

Risposto il 14/05/2010 a 14:59
fonte dall'utente

voti
12

Andiih ce l'ha proprio. MapKit non ti consente di farlo. Purtroppo, Google non ti consente di fare ciò che si vuole fare neanche.

Quando Apple ha annunciato MapKit e tutto, ma anche esplicitamente dichiarato che tutte le applicazioni di navigazione sarebbero BYOM: Da portare Maps, in modo che qualsiasi applicazione di navigazione utilizza il proprio set di strumenti di mappatura.

di Google Termini di servizio si limitano da anche la visualizzazione di percorsi in cima alla loro mappe:

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

Restrizioni della licenza:

10.9 utilizzare il Servizio o contenuti con eventuali prodotti, sistemi o applicazioni per o in connessione con:

(A) navigazione in tempo reale o pilota automatico, compreso ma non limitato a passo-guida stradale che è sincronizzato alla posizione del dispositivo sensore abilitato di un utente;

(B) qualsiasi sistema o funzione per il controllo automatico o autonomo del comportamento del veicolo; o

(C) la spedizione, la gestione della flotta, monitoraggio delle attività di asset, o applicazioni aziendali simili (l'API di Google Maps può essere utilizzato per tenere traccia delle risorse (come le automobili, autobus o altri veicoli) fino a quando l'applicazione di monitoraggio è reso disponibile al pubblico senza carica. Per esempio, si potrebbe offrire un libero, Implementazione public API di Google Maps che consente di visualizzare in tempo reale i mezzi pubblici o di altre informazioni di stato del trasporto.

Purtroppo, questo include ciò che si vorrebbe fare. Speriamo che un giorno MapKit sarà ampliato per consentire tali caratteristiche ... anche se improbabile.

In bocca al lupo.

Risposto il 14/05/2010 a 19:54
fonte dall'utente

voti
5

Si potrebbe desiderare di avere uno sguardo a https://github.com/leviathan/nvpolyline Questa soluzione è particolarmente rivolto a versioni iPhone OS precedenti a v.4.0

Anche se può essere utilizzato anche in v.4.0 Spero che questo aiuti.

Risposto il 01/07/2010 a 15:22
fonte dall'utente

voti
4

Prova MapKit-Route-Sensi ( GitHub ).

Risposto il 05/01/2011 a 08:06
fonte dall'utente

voti
3

Ottenere e disegnando un percorso sulla mappa è super facile con 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];
    }
}];
Risposto il 14/02/2015 a 16:46
fonte dall'utente

voti
3

Giusto per chiarire, sembra che ci sono un paio di cose in discussione. Uno è un modo per ottenere i vertici di un percorso e l'altro è quello di disegnare un overlay sulla mappa usando quei vertici. So che le API di MapQuest, quindi ho alcuni collegamenti per quelle al di sotto - Google e Bing hanno equivalenti credo.

1) Ottenere vertici di un percorso
Se siete alla ricerca per le nuove coordinate di un percorso per disegnare un percorso di sovrapposizione, è possibile utilizzare una chiamata di servizio Web a un servizio Web di routing - sto supponendo che si sta utilizzando JavaScript qui per visualizzare la mappa. Se si sta utilizzando codice nativo, è ancora possibile colpire un servizio web oppure è possibile utilizzare una chiamata nativa (cioè il MapQuest iPhone SDK ha un percorso di chiamata nativa in esso).

La maggior parte dei servizi di indicazioni dovrebbero restituire il "shapepoints" del percorso in modo da poter disegnare.

Ecco alcuni esempi che utilizzano MapQuest- Indicazioni Web Service per ottenere shapepoints (vedere l'oggetto di ritorno Shape) - http://www.mapquestapi.com/directions/

2) Disegno di una sovrapposizione
Una volta che avete i vostri vertici, è necessario disegnare loro. Penso che la maggior parte della mappa API JavaScript avranno una classe sovrapposizione di qualche tipo. Ecco il MapQuest uno: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Farlo con una sola chiamata
MapQuest ha anche alcune funzioni di convenienza per effettuare la chiamata percorso e tracciare la linea per voi - non posso postare più di due link! Quindi, andare al link di cui sopra e cercare "di routing" nella barra di navigazione a sinistra.

Risposto il 12/03/2012 a 17:09
fonte dall'utente

voti
3

MapQuest ha uno SDK che è un rimpiazzo per MapKit. E 'attualmente in versione beta, ma in fase di sviluppo attivo.

Esso consente sovrapposizioni, routing e geocodifica.

MapQuest IOS Maps

Risposto il 05/03/2012 a 00:45
fonte dall'utente

voti
2

Per aggiornare a questa domanda, non v'è alcuna necessità di apk esterni dal iOS7.

Ecco una soluzione molto semplice ed efficace:

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

So che la questione era di circa iOS 6 ma credo che questa soluzione sarà utile per molte persone.

L'unica cosa che manca in questa soluzione sta attuando il seguente metodo delegato per visualizzare il perno inizio e la fine

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Risposto il 25/02/2015 a 08:30
fonte dall'utente

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