Dibujar una ruta en MapKit en iPhone SDK

votos
53

Quiero dibujar una ruta entre dos ubicaciones en el mapa. Algo así como un guía turístico. Cuando el turista hace clic en otro lugar, quiero ser capaz de trazar una ruta; así como, informar acerca de la distancia desde la ubicación actual.

Soy consciente de los sitios en Internet que indican cómo dibujar polilíneas en el mapa. Sin embargo, la mayoría de los ejemplos tenían un archivo .csv precargado con varias coordenadas.

¿Hay una forma alternativa para obtener las coordenadas de Google o cualquier otro proveedor, como la ubicación se selecciona dinámicamente.

Si no, ¿cómo puedo obtener la información de coordenadas intermedias?

IOS 6 no proporciona ninguna forma directa para este problema?

Publicado el 14/05/2010 a las 14:37
fuente por usuario
En otros idiomas...                            


9 respuestas

votos
61

El siguiente viewDidLoadserá (1) establecer dos lugares, (2) eliminar todas las anotaciones anteriores, y funciones de ayuda (3) llamada definido por el usuario (para obtener puntos de ruta y dibujar la ruta).

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

El siguiente es el MKMapViewDelegatemétodo, que se basa superposición (iOS 4.0 y posterior).

/* 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 siguiente función obtendrá tanto los lugares y preparar URL para obtener todos los puntos de la ruta. Y, por supuesto, va a llamar 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]];
}

El código siguiente es la verdadera magia (decodificador para la respuesta que obtuvimos de la API). Yo no modificar ese código a menos que sepa lo que estoy haciendo :)

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

Esta función será trazar una ruta y añadirá una superposición.

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

El código siguiente se centrará alinear el mapa.

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

Espero que esto ayudaría a alguien.

Respondida el 12/08/2012 a las 18:21
fuente por usuario

votos
24

Este es un asunto difícil. No hay manera de hacer eso con MapKit: es bastante fácil dibujar líneas cuando conoce las coordenadas, pero no MapKit le dará acceso a las carreteras u otra información de enrutamiento. Yo diría que es necesario llamar a una API externa para obtener sus datos.

He estado jugando con la API cloudmade.com. El servidor de flujo de vector debe devolver lo que necesita, y entonces se puede sacar que en su mapa. Sin embargo, las discrepancias entre los mapas de Google y los OSM mapas utilizados por CloudMade pueden hacer que usted quiera usar mapas CloudMade todo el camino: no tienen un equivalente a MapKit.

PS: Otros proveedores de mapeo - Google, Bing, etc., también pueden proporcionar fuentes de datos equivalente. He estado buscando en OSM / Cloudmade recientemente.

PPS: Nada de esto es algo trivial novato! ¡La mejor de las suertes!

Respondida el 14/05/2010 a las 14:59
fuente por usuario

votos
12

Andiih lo tiene derecho. MapKit no va a dejar que hagas eso. Desafortunadamente, Google no le permitirá hacer lo que quiere hacer cualquiera.

Cuando Apple anunció MapKit y todo, ellos también declararon explícitamente que todas las aplicaciones de navegación serían BYOM: llevar sus propios mapas, por lo que cualquier aplicación de navegación utiliza su propio conjunto de herramientas de mapeo.

Condiciones del servicio de Google que restringen incluso de mostrar rutas en la parte superior de sus mapas:

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

Restricciones de la licencia:

10.9 utilizar el Servicio o Contenido con productos, sistemas o aplicaciones para o relacionados con:

(A) navegación en tiempo real o la guía de ruta, incluyendo, pero no limitado a turn-by-turn guía de ruta que se sincroniza con la posición del dispositivo sensor habilitado de un usuario;

(B) cualquier sistema o función para el control automático o autónomo del comportamiento del vehículo; o

(C) el envío, gestión de flotas, seguimiento de activos de negocios, o las aplicaciones empresariales similares (la API de Google Maps se puede utilizar para realizar un seguimiento de los activos (tales como coches, autobuses u otros vehículos) siempre y cuando la aplicación de seguimiento se pone a disposición del público sin cargo. Por ejemplo, es posible ofrecer una implementación libre Mapas pública, API que muestra el transporte público en tiempo real u otra información del estado de transporte.

Lamentablemente, esto incluye lo que le gustaría hacer. Esperemos que algún día MapKit se ampliará para permitir que tales características ... aunque poco probable.

Buena suerte.

Respondida el 14/05/2010 a las 19:54
fuente por usuario

votos
5

Es posible que desee echar un vistazo a https://github.com/leviathan/nvpolyline Esta solución está especialmente dirigido a las versiones de iPhone OS anteriores a v.4.0

Aunque también se puede utilizar en la esperanza de que esto ayude a v.4.0.

Respondida el 01/07/2010 a las 15:22
fuente por usuario

votos
4

Pruebe MapKit-Route-Direcciones ( GitHub ).

Respondida el 05/01/2011 a las 08:06
fuente por usuario

votos
3

La obtención y elaboración de una ruta en el mapa es muy fácil 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];
    }
}];
Respondida el 14/02/2015 a las 16:46
fuente por usuario

votos
3

Solo para aclarar, parece que hay un par de cosas en discusión. Una de ellas es una manera de conseguir los vértices de una ruta y el otro es para dibujar una superposición en el mapa usando los vértices. Sé que las API de MapQuest, así que tengo algunos enlaces para los de abajo - Google y Bing tienen equivalentes, creo.

1) Obtención de vértices de una ruta
Si usted está buscando las nuevas coordenadas de una ruta para trazar una ruta de superposición, puede utilizar una llamada de servicio web para un servicio web de enrutamiento - Estoy asumiendo que usted está utilizando JavaScript para visualizar el mapa. Si está utilizando código nativo, todavía puede golpear un servicio web o puede utilizar una llamada nativa (es decir, el iPhone SDK MapQuest tiene una llamada ruta nativa en ella).

La mayor parte de los servicios de instrucciones se trata de devolver los "shapepoints" de la ruta para que pueda dibujar.

He aquí algunos ejemplos que utilizan MapQuest- Servicio llegar Web para obtener shapepoints (ver el objeto de retorno Forma) - http://www.mapquestapi.com/directions/

2) Dibujar una superposición
vez que tenga sus vértices, lo que necesita para atraerlos. Creo que la mayoría de los mapas API de JavaScript tendrán una clase de superposición de algún tipo. Aquí está la MapQuest uno: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Si lo hace con una llamada
MapQuest también tiene algunas funciones de confort para hacer la llamada ruta y trazar la línea para usted - no puedo publicar más de dos enlaces! Así que ir al enlace de arriba y busque "enrutamiento" en la barra de navegación a la izquierda.

Respondida el 12/03/2012 a las 17:09
fuente por usuario

votos
3

MapQuest tiene un SDK que es una gota en el reemplazo para MapKit. Es actualmente en fase beta, pero bajo desarrollo activo.

Permite superposiciones, enrutamiento y geocodificación.

MapQuest iOS Maps API

Respondida el 05/03/2012 a las 00:45
fuente por usuario

votos
2

Para actualizar esta pregunta, no hay necesidad de apk externo, ya iOS7.

Aquí una solución muy simple y eficaz:

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

Sé que la pregunta era sobre iOS 6 pero creo que esta solución será útil para muchas personas.

La única cosa que falta en esta solución está llevando a cabo el siguiente método delegado para mostrar el comienzo y el final pin

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
Respondida el 25/02/2015 a las 08:30
fuente por usuario

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