Dessin d'une route en MapKit dans l'iPhone SDK

voix
53

Je veux tracer une route entre deux emplacements sur la carte. Quelque chose comme un guide touristique. Lorsque le touriste clique sur un autre emplacement, je veux être en mesure de tracer une route; ainsi que, informer sur la distance de l'emplacement actuel.

Je suis conscient des sites sur Internet qui racontent comment dessiner polylignes sur la carte. Mais, la plupart des exemples avaient un fichier .csv préchargé avec diverses coordonnées.

Y at-il un autre moyen pour obtenir les coordonnées de Google ou tout autre fournisseur, que l'emplacement est sélectionné dynamiquement.

Si non, comment puis-je obtenir les informations pour les coordonnées intermédiaires?

Est-ce que iOS 6 fournit une manière directe à ce problème?

Créé 14/05/2010 à 14:37
source utilisateur
Dans d'autres langues...                            


9 réponses

voix
61

Ce qui suit viewDidLoadva (1) mis en deux endroits, (2) supprimer toutes les annotations précédentes, et (3) l' utilisateur d'appel des fonctions d'assistance définies (pour obtenir des points de route et de tracer le parcours).

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

Ce qui suit est la MKMapViewDelegateméthode, qui tire overlay (iOS 4.0 et versions ultérieures).

/* 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 fonction suivante obtenir à la fois les lieux et préparer URL pour obtenir tous les points de l'itinéraire. Et bien sûr, appellera 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]];
}

Le code suivant est la vraie magie (décodeur pour la réponse que nous avons obtenu de l'API). Je ne modifierait pas ce code à moins que je sais ce que je fais :)

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

Cette fonction dessinera un itinéraire et ajoutera une superposition.

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

Le code suivant Centrer la carte.

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

J'espère que cela aiderait quelqu'un.

Créé 12/08/2012 à 18:21
source utilisateur

voix
24

Ceci est une question délicate. Il n'y a aucun moyen de le faire avec MapKit: il est assez facile de tracer des lignes lorsque vous connaissez les coordonnées, mais MapKit ne vous donnera pas accès aux routes ou d'autres informations de routage. Je dirais que vous avez besoin d'appeler une API externe pour obtenir vos données.

Je joue avec l' API de cloudmade.com. Le serveur de flux de vecteur doit retourner ce dont vous avez besoin, et vous pouvez dessiner sur votre carte que. Cependant, les écarts entre les cartes Google et les OSM cartes utilisées par CloudMade peuvent vous donner envie d'utiliser des cartes CloudMade tout le chemin: ils ont un équivalent à MapKit.

PS: D'autres fournisseurs de cartographie - Google, Bing, etc. peuvent également fournir des flux de données équivalentes. Je viens de regardé OSM / Cloudmade récemment.

PPS: Rien de tout cela est quelque chose de trivial débutant! Bonne chance!

Créé 14/05/2010 à 14:59
source utilisateur

voix
12

Andiih se terminant bientôt droit. MapKit ne vous laissera pas faire. Malheureusement, Google ne vous laissera pas faire ce que vous voulez faire non plus.

Quand Apple a annoncé MapKit et tout, ils ont aussi explicitement déclaré que toutes les applications de navigation seraient BYOM: Apportez vos propres cartes, de sorte que toute application de navigation utilise son propre ensemble d'outils de cartographie.

Conditions d'utilisation de Google vous empêche de même afficher l'itinéraire au-dessus de leurs cartes:

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

Restrictions de licence:

10.9 utiliser le service ou le contenu avec des produits, systèmes ou applications pour ou en relation avec:

(A) la navigation en temps réel ou le guidage d'itinéraire, y compris, mais sans s'y limiter, tour-par-tour le guidage d'itinéraire qui est synchronisé sur la position du dispositif activé par capteur d'un utilisateur;

(B) les systèmes ou fonctions pour la commande automatique ou autonome de comportement de véhicule; ou

(C) l'expédition, la gestion de la flotte, le suivi des actifs d'entreprise ou des applications d'entreprise similaires (l'API Google Maps peut être utilisé pour suivre les actifs (tels que les voitures, les autobus ou autres véhicules) tant que l'application de suivi est mis à la disposition du public sans frais. Par exemple, vous pouvez offrir une API publique gratuite qui affiche Plans la mise en œuvre du transport en commun en temps réel ou d'autres informations d'état de transport.

Malheureusement, cela inclut ce que vous voulez faire. Espérons qu'un jour MapKit sera élargi pour permettre à ces caractéristiques ... bien que peu probable.

Bonne chance.

Créé 14/05/2010 à 19:54
source utilisateur

voix
5

Vous pouvez jeter un oeil à https://github.com/leviathan/nvpolyline Cette solution est spécialement destiné aux versions iPhone OS avant v.4.0

Bien qu'il puisse également être utilisé dans v.4.0 Hope this helps.

Créé 01/07/2010 à 15:22
source utilisateur

voix
4

Essayez MapKit-Route-Directions ( GitHub ).

Créé 05/01/2011 à 08:06
source utilisateur

voix
3

L'obtention et le dessin d'un itinéraire sur la carte est super facile avec l'API iOS 7:

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];
    }
}];
Créé 14/02/2015 à 16:46
source utilisateur

voix
3

Juste pour clarifier, il semble qu'il y ait une ou deux choses en cours de discussion. L' un est un moyen d'obtenir les sommets d'un itinéraire et l'autre est d'établir une superposition sur la carte en utilisant ces sommets. Je sais que les API MapQuest, j'ai donc quelques liens pour ceux ci - dessous - Google et Bing ont des équivalents je pense.

1) Obtenir sommets d'un itinéraire
Si vous cherchez les nouvelles coordonnées d'un itinéraire pour dessiner une superposition d'itinéraire, vous pouvez utiliser un service de routage appel de service Web à un Web - Je suppose que vous utilisez JavaScript ici pour afficher la carte. Si vous utilisez le code natif, vous pouvez toujours frapper un service Web ou vous pouvez utiliser un appel natif (qui est, l'iPhone SDK MapQuest a un appel d'itinéraire natif dedans).

La plupart des services directions doivent retourner les « shapepoints » de la route afin que vous puissiez tirer.

Voici quelques exemples utilisant les directions Web Service MapQuest- pour obtenir shapepoints (voir l'objet de retour de forme) - http://www.mapquestapi.com/directions/

2) Dessiner une superposition
Une fois que vous avez vos sommets, vous devez les dessiner. Je pense que la plupart des API de carte JavaScript ont une classe de superposition d'une sorte. Voici le MapQuest un: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Faire avec un appel
MapQuest ont également des fonctions de commodité pour faire l'appel d'itinéraire et tracer la ligne pour vous - je ne peux pas poster plus de deux liens! Alors , allez sur le lien ci - dessus et recherchez « routage » dans la barre de navigation à gauche.

Créé 12/03/2012 à 17:09
source utilisateur

voix
3

MapQuest a un SDK qui est un remplacement de halte-accueil pour MapKit. Il est actuellement en version bêta, mais en cours de développement.

Il permet des superpositions, le routage et le géocodage.

MapQuest API iOS Plans

Créé 05/03/2012 à 00:45
source utilisateur

voix
2

Pour mettre à jour cette question, il n'y a pas besoin de apk externe depuis iOS 7.

Voici une solution très simple et efficace:

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

Je sais que la question était sur iOS 6 mais je crois que cette solution sera utile pour beaucoup de gens.

La seule chose qui manque dans cette solution met en œuvre la méthode déléguée suivante pour afficher le début et la fin broche

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Créé 25/02/2015 à 08:30
source utilisateur

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