Drawing a route in MapKit on iOS

I want to draw a route between two locations on a map. Something like a guide. When a tourist clicks on another place, I want to be able to conduct a route; and also report the distance from your current location.

I know sites on the Internet that tell you how to draw polylines on a map. But most of the examples had a pre-loaded CSV file with different coordinates.

Is there an alternative way to get coordinates from Google or any other provider, since the location is selected dynamically.

If not, how do I get information for intermediate coordinates?

Does iOS 6 provide a direct way for this problem?

+53
ios iphone mapkit
May 14, '10 at 13:37
source share
9 answers

It's complicated. There is no way to do this with MapKit: it's easy enough to draw lines when you know the coordinates, but MapKit will not give you access to roads or other routing information. I would say you need to call an external API to get your data.

I played with the cloudmade.com API. The vector stream server should return what you need, and then you can draw it on the map. However, discrepancies between Google maps and maps

+24
May 14, '10 at 13:59
source share

The next viewDidLoad will (1) set two locations, (2) delete all previous annotations, and (3) call custom helper functions (to get waypoints and draw a route).

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

Below is the MKMapViewDelegate method, which imposes an overlay (iOS 4.0 and later).

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

The following function will get both places and prepare the URL to get all the waypoints. And of course, will call 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]]; } 

The following code is real magic (decoder for the response we received from the API). I would not change this code if I do not know what I am doing :)

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

This function will draw a route and add an overlay.

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

The following code centers the alignment of the 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]; } 

Hope this helps someone.

+61
Aug 12 2018-12-12T00:
source share

And everything turned out right. MapKit will not allow you to do this. Unfortunately, Google will not allow you to do what you want to do.

When Apple announced MapKit and all, they also explicitly stated that any navigation application would be BYOM: Bring your own maps, so any navigation application uses its own set of tools for mapping.

Googleโ€™s terms of service even restrict the display of routes on top of their maps:

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

License Limitations:

10.9 use the Service or Content with any products, systems or applications for or in connection with:

(a) real-time navigation or route guidance, including, but not limited to, step-by-step route guidance that is synchronized with the position of the touch-screen device;

(b) any systems or functions for the automatic or autonomous control of vehicle behavior; or

(c) sending, fleet management, tracking of business assets or similar corporate applications (Google Maps API can be used to track assets (for example, cars, buses or other vehicles) until the tracking application is made available to the public for free. For example , you can offer a free public Maps API Implementation that displays real-time status of public transport or other transport status information.

Unfortunately, this includes what you would like to do. Hopefully one day MapKit will be expanded to allow such features ... albeit unlikely.

Good luck.

+12
May 14 '10 at 18:54
source share

Maybe you should take a look at https://github.com/leviathan/nvpolyline. This solution is especially targeted at iPhone OS versions up to version 4.0

Although it can also be used in v.4.0 Hope this helps.

+5
Jul 01 '10 at 14:22
source share
+4
Jan 05 2018-11-11T00:
source share

MapQuest has an SDK that replaces the MapKit replacement. It is currently in beta testing, but is under active development.

It allows overlays, routing and geocoding.

MapQuest Maps API for iOS

+3
Mar 04 '12 at 23:45
source share

Just to clarify, there seem to be a couple of issues being discussed. One of them is a way to get the top of the route, and the other is to draw an overlay on the map using these vertices. I know the MapQuest API, so I have some links for below: Google and Bing have equivalents that I think.

1) Getting the tops of the route
If you are looking for new route coordinates for route mapping, you can either use the web service call for the routing web service - I assume that you use JavaScript here to display the map. If you use your own code, you can still access the web service or use your own call (that is, the MapQuest iPhone SDK has its own route call).

Most referral services should return โ€œshapepointsโ€ of the route so that you can draw.

Here are some examples of using MapQuest- Web Service Directions to get shapepoints (see Form Return Object) - http://www.mapquestapi.com/directions/

2) Overlay overlay
When you have your vertices, you need to draw them. I think most API maps APIs will have an overlay class. Here's MapQuest: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3) Performing this with a single call
MapQuest also has some handy features to call along the route and draw a line for you - I cannot post more than two links! Therefore, follow the link above and find "routing" in the navigation panel on the left.

+3
Mar 12 2018-12-12T00:
source share

Getting and drawing a route on a map is very simple using the 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]; } }]; 
+3
Feb 14 '15 at 16:46
source share

To update this question, there is no need for an external apk with iOS7.

Here is a very simple and effective solution:

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

I know that the question was about iOS 6, but I believe that this solution will be useful for many people.

The only thing missing in this solution is to implement the following delegate method to display the start and end contacts

 -(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation 
+2
Feb 25 '15 at 8:30
source share



All Articles