iOS : How to plot polyline on existing route? - ios

I plot the route between source and destination using the following piece of code. After plotting the route sucessfully, I get a list of coordinates where I wanted to plot another route on top of existing one with different color.
The use case I am trying to code is, we set source and destination, plot the dotted route once, then plot the actual line based on the list of locations
From the code, I can see the dotted line but can not see the another line overlapping on it.
My code is:
-(void) getDirection {
CLLocationCoordinate2D sourceCoords = CLLocationCoordinate2DMake(42.130655, -71.041158);
MKPlacemark *sourcePlacemark = [[MKPlacemark alloc] initWithCoordinate:sourceCoords addressDictionary:nil];
MKMapItem *source = [[MKMapItem alloc] initWithPlacemark:sourcePlacemark];
// Make the destination location
CLLocationCoordinate2D destinationCoords = CLLocationCoordinate2DMake(42.128121, -70.936151); MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoords addressDictionary:nil];
MKMapItem *destination = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];
MKDirectionsRequest *directionsRequest = [MKDirectionsRequest new];
[directionsRequest setSource:source];
[directionsRequest setDestination:destination];
[self sourceMarker:sourcePlacemark];
[self destinationMarker:destinationPlacemark];
//
//routeCoords
NSInteger nuberOfStesps = routeCoords.count;
CLLocationCoordinate2D *pointsCoordinate = (CLLocationCoordinate2D *)malloc(sizeof(CLLocationCoordinate2D) * nuberOfStesps);
for (NSInteger index=0; index < nuberOfStesps; index++) {
CLLocation *location = [routeCoords objectAtIndex:index];
coordinate2 = location.coordinate;
//NSLog(#"Location Latitide : %f", coordinate2.latitude);
//NSLog(#"Location Longitude : %f", coordinate2.longitude);
pointsCoordinate[index] = CLLocationCoordinate2DMake(coordinate2.latitude, coordinate2.longitude);
}
routeLine = [MKPolyline polylineWithCoordinates:pointsCoordinate count:nuberOfStesps];
// free(pointsCoordinate);
routeLine.title = #"New points";
[self.mapView addOverlay:routeLine];
//
MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(#"There was an error getting your directions");
return;
}else {
[self showRoute:response];
}
}];
}
- (void) showRoute:(MKDirectionsResponse * ) response {
_currentRoute = [response.routes firstObject];
[self.mapView setVisibleMapRect:_currentRoute.polyline.boundingMapRect animated:NO];
[self.mapView removeOverlays:self.mapView.overlays];
[self.mapView addOverlay:_currentRoute.polyline level:MKOverlayLevelAboveRoads];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithOverlay:overlay];
[renderer setStrokeColor:[UIColor redColor]];
[renderer setLineWidth:4.0];
[renderer setLineDashPattern:#[#2, #5]];
[renderer setStrokeColor:[UIColor redColor]];
return renderer;
}
return nil;
}
I followed this thread iOS Maps draw route (line) between several points (geopoints)
But it did not work for me. What am I doing wrong?

Related

How can I show start location at top and end location at bottom on mapview for route?

I am showing route between start location and end location on map for iPhone app, i want to show start location at top in map and end location at bottom, also make sure that all route should be visible on map. Below is code i tried.
-(void) viewDidLoad {
MKPointAnnotation *myAnnotation = [[MKPointAnnotation alloc] init];
myAnnotation.coordinate = CLLocationCoordinate2DMake(42.110532,
-87.912126);
myAnnotation.title = #"Start point";
[self.mapView addAnnotation:myAnnotation];
MKPointAnnotation *destinatioAnnotation = [[MKPointAnnotation alloc]
init];
destinatioAnnotation.coordinate = CLLocationCoordinate2DMake(42.105948,
-87.870664);
destinatioAnnotation.title = #"End Point";
[self.mapView addAnnotation:destinatioAnnotation];
CLLocationCoordinate2D startCoord1 =
CLLocationCoordinate2DMake(42.110532, -87.912126);
MKCoordinateRegion adjustedRegion1 = [self.mapView
regionThatFits:MKCoordinateRegionMakeWithDistance(startCoord1, 300000,
300000)];
[self.mapView setRegion:adjustedRegion1 animated:YES];
self.mapView.showsCompass = NO;
MKDirectionsRequest *directionsRequest = [MKDirectionsRequest new];
directionsRequest.requestsAlternateRoutes = NO;
// Make the destination
CLLocationCoordinate2D sourceCoords =
CLLocationCoordinate2DMake(42.110532, -87.912126);
MKPlacemark *sourcePlacemark = [[MKPlacemark alloc]
initWithCoordinate:sourceCoords addressDictionary:nil];
MKMapItem *sourceLoc = [[MKMapItem alloc]
initWithPlacemark:sourcePlacemark];
// Set the source and destination on the request
// Make the destination
CLLocationCoordinate2D destinationCoords = CLLocationCoordinate2DMake(42.105948, -87.870664);
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoords addressDictionary:nil];
MKMapItem *destination = [[MKMapItem alloc] initWithPlacemark:destinationPlacemark];
// Set the source and destination on the request
[directionsRequest setSource:sourceLoc];
[directionsRequest setDestination:destination];
MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *
_Nullable response, NSError * _Nullable error) {
// Now handle the result
if (error) {
NSLog(#"There was an error getting your directions");
return;
}
// So there wasn't an error - let's plot those routes
_currentRoute = [response.routes firstObject];
[self plotRouteOnMap:_currentRoute];
}];
}
- (void)plotRouteOnMap:(MKRoute *)route {
if(_routeOverlay) {
[self.mapView removeOverlay:_routeOverlay];
}
// Update the ivar
_routeOverlay = route.polyline;
self.routePolyline = route.polyline;
self.mapView.tag = 1;
// Add it to the map
[self.mapView setVisibleMapRect:[route.polyline boundingMapRect] edgePadding:UIEdgeInsetsMake(50, 50, 50, 40) animated:YES];
/*[self.mapView setRegion:MKCoordinateRegionForMapRect([route.polyline
boundingMapRect])
animated:YES];*/
[self.mapView addOverlay:_routeOverlay level:MKOverlayLevelAboveRoads];
[self performSelector:#selector(changeHeading) withObject:nil
afterDelay:1.2];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
NSLog(#"called");
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
if (mapView.tag == 1) {
renderer.strokeColor = [UIColor redColor];
}if (mapView.tag == 2) {
renderer.strokeColor = [UIColor blueColor];
}else{
renderer.strokeColor = [UIColor blueColor];
}
renderer.lineWidth = 4.0;
NSLog(#"x: %f, y:%f, widht: %f, height: %f",[overlay boundingMapRect].origin.x,[overlay
boundingMapRect].origin.y,[overlay
boundingMapRect].size.width,[overlay boundingMapRect].size.height);
return renderer;
}
-(void) changeHeading {
MKMapCamera *camera = self.mapView.camera;
CLLocationDistance altitude = camera.altitude;
NSLog(#"altitude: %f",altitude);
CLLocationDirection mapAngle = camera.heading;
NSLog(#"mapAngle: %f",mapAngle);
if (altitude < 3000 && altitude > 1000) {
// do something
}
if (self.mapView.camera.heading != 257) {
MKMapCamera *newCamera = [MKMapCamera camera];
newCamera.centerCoordinate = self.mapView.camera.centerCoordinate;
newCamera.heading = 257;
newCamera.altitude = self.mapView.camera.altitude;
[self.mapView setCamera:newCamera animated:YES];
}
/*MKMapCamera *turnCam = [MKMapCamera cameraLookingAtCenterCoordinate:CLLocationCoordinate2DMake(42.110532,
-87.912126)
fromEyeCoordinate:CLLocationCoordinate2DMake(42.105948, -87.870664)
eyeAltitude:self.mapView.camera.altitude];
self.mapView.camera = turnCam;*/
}

How to show the path between two location in mapkit

I want to show two location's distance in mapkit, I have tried my process its not showing the distance between the location. tried below codes its not working, can any one help me in coding.
MKMapView * mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 294, 320, 122)];
mapView.showsUserLocation = YES;
mapView.delegate = self;
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
MKPlacemark *placemark1 = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(9.9176458, 78.1228237) addressDictionary:nil];
[request setSource:[[MKMapItem alloc] initWithPlacemark:placemark1]];
MKPlacemark *placemark = [[MKPlacemark alloc] initWithCoordinate:CLLocationCoordinate2DMake(13.0475604, 80.2089535) addressDictionary:nil];
request.destination = [[MKMapItem alloc] initWithPlacemark:placemark];
// [request setDestination:myMapItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile]; // This can be limited to automobile and walking directions.
[request setRequestsAlternateRoutes:YES]; // Gives you several route options.
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (!error) {
for (MKRoute *route in [response routes]) {
[mapView addOverlay:[route polyline] level:MKOverlayLevelAboveRoads]; // Draws the route above roads, but below labels.
// You can also get turn-by-turn steps, distance, advisory notices, ETA, etc by accessing various route properties.
}
}
}];
[self.view addSubview:mapView];
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id < MKOverlay >)overlay
{
MKPolylineRenderer *renderer =
[[MKPolylineRenderer alloc] initWithOverlay:overlay];
renderer.strokeColor = [UIColor blueColor];
renderer.lineWidth = 5.0;
return renderer;
}
Please any help me .
If you check error in the -calculateDirectionsWithCompletionHandler:
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (!error) {
for (MKRoute *route in [response routes]) {
[mapView addOverlay:[route polyline] level:MKOverlayLevelAboveRoads]; // Draws the route above roads, but below labels.
// You can also get turn-by-turn steps, distance, advisory notices, ETA, etc by accessing various route properties.
}
}
else {
NSLog(#"%#", error);
}
}];
You will probably see
Error Domain=MKErrorDomain Code=5 "Directions Not Available" UserInfo=0x7fefe3bb5660 {NSLocalizedFailureReason=A route to the nearest road cannot be determined., MKErrorGEOError=-403, MKDirectionsErrorCode=6, NSLocalizedDescription=Directions Not Available}
Which means that it is not possible to calculate directions from given location.
Here is my code; I use CLLocationManager Delegate to compute distance between two location and MKMapView Delegate. here is my code, it may help you.
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)location{
float distance = 0.0f;
NSMutableArray *locationArray = [[NSMutableArray alloc] init];
for (CLLocation *newLocation in location) {
[locationArray addObject:newLocation];
}
for (int i = 0 ; i < locationArray.count; i++) {
CLLocation *newLocation = [locationArray objectAtIndex:i];
distance += [newLocation distanceFromLocation:[locationArray objectAtIndex:i+1]];
}
NSLog(#"%f",distance);
CLLocationCoordinate2D cordinates [locationsArray.count];
MKPolyline *userLocationsPolyLine = [MKPolyline polylineWithCoordinates:cordinates count:locationsArray.count];
[userMapView setDelegate:self];
[userMapView addOverlay:userLocationsPolyLine];
}
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay{
if ([overlay isKindOfClass:[MKPolyline class]]){
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
renderer.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.7];
renderer.lineWidth = 3;
return renderer;
}
return nil;
}

MKDirections not showing route on map in iOS

I am working on one app, I need to show route directions between two coordinates. I have used MKDirections and have passed two coordinates as source and destination, however on mapView its not showing any route or drawing any polyline. Below is my code. In MKDirections its always showing nil. Please let me know what I am doing wrong.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.activityIndicator.hidden = YES;
self.routeDetailsButton.hidden = YES;
self.routeDetailsButton.enabled = NO;
self.mapView.delegate = self;
self.mapView.showsUserLocation = YES;
self.navigationItem.title = #"RouteMaster";
}
#pragma mark - MapKit delegate methods
- (void)mapView:(MKMapView *)aMapView didUpdateUserLocation:(MKUserLocation *)userLocation {
CLLocationCoordinate2D loc = [userLocation.location coordinate];
MKCoordinateRegion region = MKCoordinateRegionMakeWithDistance(loc, 1000.0f, 1000.0f);
[self.mapView setRegion:region animated:YES];
}
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
- (IBAction)handleRoutePressed:(id)sender {
// We're working
CLLocationCoordinate2D sourceCoords = CLLocationCoordinate2DMake(28.6100, 77.2300);
MKPlacemark *sourcePlacemark = [[MKPlacemark alloc] initWithCoordinate:sourceCoords addressDictionary:nil];
MKMapItem *srcMapItem = [[MKMapItem alloc]initWithPlacemark:sourcePlacemark];
CLLocationCoordinate2D destinationCoords = CLLocationCoordinate2DMake(18.9750, 72.8258);
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoords addressDictionary:nil];
MKMapItem *distMapItem = [[MKMapItem alloc]initWithPlacemark:destinationPlacemark];
MKDirectionsRequest *request = [[MKDirectionsRequest alloc]init];
[request setSource:srcMapItem];
[request setDestination:distMapItem];
MKDirections *direction = [[MKDirections alloc]initWithRequest:request];
[direction calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (error)
NSLog(#"Error %#", error.description);
else
NSLog(#"response = %#",response);
NSArray *arrRoutes = [response routes];
[arrRoutes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
MKRoute *rout = obj;
MKPolyline *line = [rout polyline];
[self.mapView addOverlay:line];
NSLog(#"Rout Name : %#",rout.name);
NSLog(#"Total Distance (in Meters) :%f",rout.distance);
NSArray *steps = [rout steps];
NSLog(#"Total Steps : %lu",(unsigned long)[steps count]);
[steps enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSLog(#"Rout Instruction : %#",[obj instructions]);
NSLog(#"Rout Distance : %f",[obj distance]);
}];
}];
}];
}
#pragma mark - Utility Methods
- (void)plotRouteOnMap:(MKRoute *)route
{
if(_routeOverlay) {
[self.mapView removeOverlay:_routeOverlay];
}
// Update the ivar
_routeOverlay = route.polyline;
// Add it to the map
[self.mapView addOverlay:_routeOverlay];
}
#pragma mark - MKMapViewDelegate methods
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
MKPolylineRenderer *renderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
renderer.strokeColor = [UIColor redColor];
renderer.lineWidth = 4.0;
return renderer;
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay {
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolylineView* aView = [[MKPolylineView alloc]initWithPolyline:(MKPolyline*)overlay] ;
aView.strokeColor = [[UIColor blueColor] colorWithAlphaComponent:0.5];
aView.lineWidth = 10;
return aView;
}
return nil;
}
Mostly this error occur if [_mapView setRegion:region] area and polyline route path are not on same region(both should need to display on same screen).
In my case I was searching for USA route path while my region was India. So it wont call to -(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id)overlay; function.
add this method
-(MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay {
MKPolylineRenderer * routeLineRenderer = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
routeLineRenderer.strokeColor = [UIColor blueColor];
routeLineRenderer.lineWidth = 4;
return routeLineRenderer;
}

MapBox polyline not shown on map

I have a problem when trying to add a polyline on the map.
I get directions from MKDirections, and create a RMPolylineAnnotation, but it does not appear on the map.
As I can see, the following method is called just once when the map appears:
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation
Here is the code I am using:
- (void)getRoute {
CLLocation *source = [[CLLocation alloc] initWithLatitude:self.mapView.userLocation.coordinate.latitude longitude:self.mapView.userLocation.coordinate.longitude];
CLLocation *destination = [[CLLocation alloc] initWithLatitude:self.mapView.selectedAnnotation.coordinate.latitude longitude:self.mapView.selectedAnnotation.coordinate.longitude];
[AppleDirectionManager getDirectionsFromPoint:source toPoint:destination transportType:MKDirectionsTransportTypeAutomobile withCompletion:^(MKDirectionsResponse *result) {
self.routeStepsArray = [[result.routes firstObject] steps];
for (MKRoute *route in result.routes) {
NSMutableArray *points = [NSMutableArray array];
for (int i = 0; i < route.polyline.pointCount; i++) {
MKMapPoint point = route.polyline.points[i];
CLLocation *location = [[CLLocation alloc] initWithLatitude:point.x longitude:point.y];
[points addObject:location];
}
dispatch_async(dispatch_get_main_queue(), ^{
NSArray *arr = [points copy];
RMPolylineAnnotation *polyline = [[RMPolylineAnnotation alloc] initWithMapView:self.mapView points:arr];
[self.mapView addAnnotation:polyline];
});
}
}];
}
- (RMMapLayer *)mapView:(RMMapView *)mapView layerForAnnotation:(RMAnnotation *)annotation {
if (annotation.isUserLocationAnnotation)
return nil;
RMMarker *marker = [[RMMarker alloc] initWithUIImage:[UIImage imageNamed:#"blabla.png"]];
[marker setCanShowCallout:YES];
[marker setName:#"blabla"];
return marker;
}
Also I can not show a custom callout for a RMPointAnnotation.
For RMPointAnnotation it's easily.
_polylineAnnotation = [[RMPolylineAnnotation alloc] initWithMapView:_mapView points:#[Location,Location]];
_polylineAnnotation.lineColor = [UIColor redColor];
_polylineAnnotation.lineWidth = 10.0f;
[_mapView addAnnotation:_polylineAnnotation];

display route on iOS 7 maps: addOverlay has no effect

i want display a point to point route inside my mapView, i use this code for create the route:
- (IBAction)backToYourCar {
MKPlacemark *sourcePlacemark = [[MKPlacemark alloc] initWithCoordinate:self.annotationForCar.coordinate addressDictionary:nil];
NSLog(#"coordiante : locationIniziale %f", sourcePlacemark.coordinate.latitude);
MKMapItem *carPosition = [[MKMapItem alloc] initWithPlacemark:sourcePlacemark];
MKMapItem *actualPosition = [MKMapItem mapItemForCurrentLocation];
NSLog(#"coordiante : source %f, ActualPosition %f", carPosition.placemark.coordinate.latitude ,actualPosition.placemark.coordinate.latitude);
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
request.source = actualPosition;
request.destination = carPosition;
request.requestsAlternateRoutes = YES;
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if (error) {
NSLog(#"Error : %#", error);
}
else {
[self showDirections:response]; //response is provided by the CompletionHandler
}
}];
}
and this for show the route on the map:
- (void)showDirections:(MKDirectionsResponse *)response
{
for (MKRoute *route in response.routes) {
[self.mapView addOverlay:route.polyline level:MKOverlayLevelAboveRoads];
}
}
actually this code does nothing.
if i try to print the the distance of route i get the correct value:
route distance: 1910.000000
then the route is right, but i can't understand why it doesn't appear on the map!
Any suggestions?
after a day of research i have solved with this 3 steps:
Set the delegate (self.mapView.delegate = self).
import the MKMapViewDelegate
Implemente the new iOS7 MapView delegate method:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay(id<MKOverlay>)overlay:
this is my implementation:
- (MKOverlayRenderer *)mapView:(MKMapView *)mapView rendererForOverlay:(id<MKOverlay>)overlay
{
if ([overlay isKindOfClass:[MKPolyline class]]) {
MKPolyline *route = overlay;
MKPolylineRenderer *routeRenderer = [[MKPolylineRenderer alloc] initWithPolyline:route];
routeRenderer.strokeColor = [UIColor blueColor];
return routeRenderer;
}
else return nil;
}
this method is automatically called by the delegate when you add the polyline on the map.

Resources