MapKit route over custom pin & callout - iphone

I have customized pins in my mapview with custom callout.
While drawing path on map, the route is coming over callout & pins. Image Attached.
I have used google API to get polylines and drawing it after decoding it.
Here is the code:
if(!routeView)
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.mapView.frame.origin.y, mapView.frame.size.width, self.mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
[self.lat1 resignFirstResponder];
[self.long1 resignFirstResponder];
[self.lat2 resignFirstResponder];
[self.long2 resignFirstResponder];
NSString* saddr = [NSString stringWithFormat:#"%#,%#",self.lat1.text,self.long1.text];
NSString* daddr = [NSString stringWithFormat:#"%#,%#",self.lat2.text,self.long2.text];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.apple.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSData *responseData = [apiResponse dataUsingEncoding:NSUTF8StringEncoding];
NSError* error1;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&error1];
NSLog(#"Error: %#\n%#",[error1 localizedDescription],[error1 localizedFailureReason]);
if([[json objectForKey:#"status"] isEqualToString:#"OK"])
{
NSArray *routes1 = [json objectForKey:#"routes"];
NSDictionary *route = [routes1 lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
routes = [self decodePolyLine:overviewPolyline];
//NSLog(#"%#",[routes objectAtIndex:0]);
[self updateRouteView];
[self centerMap];
}
}
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}

I think your problem is that you add your routeView after adding your pin, so the routeview is the first subview. What happens if you try to add the routeView first, in your viewDidLoad method for example ?

Thanks for the responses. I have figure this out using MKPolylines. Refer code below
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++) {
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
MKPolyline *polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyLine];

Related

Draw Map Path among multiple location

I am new in iphone development, i want to draw path between 5 location how i can draw path in google map.
I want path from location1 to location2 , location2 to location3, location3 to location4 and location4 to location5.
here is my code
- (void)viewDidLoad {
[super viewDidLoad];
NSDictionary *d1,*d2,*d3,*d4,*d5;
d1=[NSDictionary dictionaryWithObjectsAndKeys:#"location1",#"comments",#"1",#"id",#"23.02941395",#"latitude",#"72.54620655",#"longitude",nil];
d2=[NSDictionary dictionaryWithObjectsAndKeys:#"location2",#"comments",#"2",#"id",#"23.028359049999995",#"latitude",#"72.54537318333334",#"longitude",nil];
d3=[NSDictionary dictionaryWithObjectsAndKeys:#"location3",#"comments",#"3",#"id",#"23.029545",#"latitude",#"72.546036",#"longitude",nil];
d4=[NSDictionary dictionaryWithObjectsAndKeys:#"location4",#"comments",#"4",#"id",#"23.030050",#"latitude",#"72.546226",#"longitude",nil];
d5=[NSDictionary dictionaryWithObjectsAndKeys:#"location5",#"comments",#"5",#"id",#"23.030050",#"latitude",#"72.546022",#"longitude",nil];
self.reports=[NSArray arrayWithObjects:d1,d2,d3,d4,d5,nil];
for (NSDictionary *d in self.reports) {
float latitude=[[d valueForKey:#"latitude"] floatValue];
float longitude=[[d valueForKey:#"longitude"] floatValue];
Place* home = [[[Place alloc] init] autorelease];
home.name = [d valueForKey:#"comments"];
home.latitude = latitude;
home.longitude = longitude;
PlaceMark *from = [[[PlaceMark alloc] initWithPlace:home] autorelease];
[mapView addAnnotation:from];
}
[self centerMap];
}
-(void) centerMap
{
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90;
CLLocationDegrees maxLon = -180;
CLLocationDegrees minLat = 120;
CLLocationDegrees minLon = 150;
NSMutableArray *temp=[NSArray arrayWithArray:self.reports];
NSLog(#"%#",temp);
for (int i=0; i<[temp count];i++) {
Place* home = [[[Place alloc] init] autorelease];
home.latitude = [[[temp objectAtIndex:i] valueForKey:#"latitude"]floatValue];
home.longitude =[[[temp objectAtIndex:i] valueForKey:#"longitude"]floatValue];
PlaceMark* from = [[[PlaceMark alloc] initWithPlace:home] autorelease];
CLLocation* currentLocation = (CLLocation*)from ;
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;
}
[mapView setRegion:region animated:YES];
}
- (MKAnnotationView *)mapView:(MKMapView *)map viewForAnnotation:(id <MKAnnotation>)annotation
{
if (annotation == mapView.userLocation)
return nil;
MKPinAnnotationView *pin = (MKPinAnnotationView *) [mapView dequeueReusableAnnotationViewWithIdentifier: #"asdf"];
if (pin == nil)
pin = [[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier: #"asdf"] autorelease];
else
pin.annotation = annotation;
pin.userInteractionEnabled = YES;
UIButton *disclosureButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[disclosureButton setFrame:CGRectMake(0, 0, 30, 30)];
pin.rightCalloutAccessoryView = disclosureButton;
pin.pinColor = MKPinAnnotationColorRed;
//pin.animatesDrop = YES;
[pin setEnabled:YES];
[pin setCanShowCallout:YES];
return pin;
}
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control
{
NSString *strTitle = [NSString stringWithFormat:#"%#",[view.annotation title]];
NSMutableDictionary *d;
NSMutableArray *temp=[NSArray arrayWithArray:self.reports];
for (int i = 0; i<[temp count]; i++)
{
d = (NSMutableDictionary*)[temp objectAtIndex:i];
NSString *strAddress = [NSString stringWithFormat:#"%#",[d valueForKey:#"comments"]];
if([strAddress isEqualToString:strTitle]) {
[self presentModalViewController:self.nxtDetailsVCtr animated:YES];
[self.nxtDetailsVCtr.lblDetail setText:strAddress];
break;
}
}
}
You can use NVPlolineAnnotation to draw line inside the map. Here is the Source Code.
Frameworks needed
QuartzCore.framework
CoreLocation.framework
MapKit.framework
Files Needed
JSONKit.h
JSONKit.m
Set -fno-objc-arc in compile source for JSON in case of ARC.
In header File
__block IBOutlet MKMapView *__mapView;
NSArray* routes;
MKPointAnnotation *startLocation;
MKPointAnnotation *endLocation;
MKPolyline *polyLine;
Implementation piece of code...
- (void)viewDidLoad
{
// [__mapView setShowsUserLocation:YES];
[__mapView setZoomEnabled:YES];
[__mapView setScrollEnabled:YES];
[__mapView setMapType:MKMapTypeStandard];
[__mapView setDelegate:self];
routes=[[NSArray alloc] init];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (IBAction)drawPath:(id)sender {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
[self showRouteFrom:startLocation to:endLocation];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
if (polyLine) {
[__mapView setVisibleMapRect:[polyLine boundingMapRect]];
[__mapView addOverlay:polyLine];
[self centerMap];
}
NSLog(#"drawing path completed");
});
});
}
-(void) showRouteFrom: (id<MKAnnotation>)source to:(id<MKAnnotation>)destination;
{
if(routes)
{
[__mapView removeAnnotations:[__mapView annotations]];
}
[__mapView addAnnotation:source];
[__mapView addAnnotation:destination];
NSLog(#"source title is %#",source.title);
NSLog(#"destination title is %#",destination.title);
routes = [self calculateRoutesFrom:source.coordinate to:destination.coordinate];
NSLog(#"routes are %#",routes);
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
NSLog(#"poly line to be added as ovelay is %#",polyLine);
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t
{
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false&avoid=highways&mode=",saddr,daddr];
NSLog(#"Fired API %#",apiUrlStr);
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSDictionary *dic=[apiResponse objectFromJSONString];
if (dic!=nil) {
NSArray *routPoints=[[NSArray alloc] initWithArray:[dic valueForKey:#"routes"]];
NSDictionary *polylineOverview=[[routPoints objectAtIndex:0] valueForKey:#"overview_polyline"];
NSString *polylinePoints = [polylineOverview objectForKey:#"points"];
return [self decodePolyLine:[polylinePoints mutableCopy]];
}
return nil;
}
- (NSMutableArray *)decodePolyLine: (NSMutableString *)encoded
{
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\" options:NSLiteralSearch range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded 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 = [encoded 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 = [encoded 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("[%f,", [latitude doubleValue]);
//printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
#pragma mark- MKMapView delegate method
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor purpleColor];
polylineView.lineWidth = 5.0;
NSLog(#"polyline in viewFor overlay: %#",polylineView);
return polylineView;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"did update user location called ");
MKCoordinateRegion region;
region.span.latitudeDelta = .005;
region.span.longitudeDelta = .005;
region.center = userLocation.coordinate;
[mapView setRegion:region animated:YES];
}
-(void) centerMap
{
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees maxLon = -180.0;
CLLocationDegrees minLat = 90.0;
CLLocationDegrees minLon = 180.0;
for(int idx = 0; idx < routes.count; idx++)
{
CLLocation* currentLocation = [routes 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.0;
region.center.longitude = (maxLon + minLon) / 2.0;
region.span.latitudeDelta = 0.01;
region.span.longitudeDelta = 0.01;
region.span.latitudeDelta = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);
[__mapView setRegion:region animated:YES];
}
#pragma mark- UITextField delegate method
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
{
[self.view bringSubviewToFront:textField];
CGRect rect=textField.frame;
[[NSUserDefaults standardUserDefaults] setValue:NSStringFromCGRect(rect) forKey:#"textFieldRect"];
rect.origin.y=self.view.frame.size.height-260;
[UIView animateWithDuration:0.3 animations:^{
[textField setFrame:rect];
}];
return YES;
}
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
NSString *rectStr=[[NSUserDefaults standardUserDefaults] valueForKey:#"textFieldRect"];
NSArray *rectArray=[rectStr componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:#"{,} "]];
CGRect rect;
rect.origin.x=[[rectArray objectAtIndex:2] floatValue];
rect.origin.y=[[rectArray objectAtIndex:4] floatValue];
rect.size.width=[[rectArray objectAtIndex:8] floatValue];
rect.size.height=[[rectArray objectAtIndex:10] floatValue];
[UIView animateWithDuration:0.3 animations:^{
[textField setFrame:rect];
}];
[textField resignFirstResponder];
return YES;
}
- (void)textFieldDidEndEditing:(UITextField *)textField
{
NSDictionary *locationDic=[self getLatLongOfPlace:[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
NSDictionary *latLongDic=[[[[[locationDic valueForKey:#"results"] objectAtIndex:0] valueForKey:#"geometry"]valueForKey:#"viewport"] valueForKey:#"northeast"];
if (textField.tag==0) {
startLocation=[[MKPointAnnotation alloc] init];
[startLocation setCoordinate:CLLocationCoordinate2DMake([[latLongDic valueForKey:#"lat"] floatValue], [[latLongDic valueForKey:#"lng"] floatValue])];
startLocation.title=[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}else{
endLocation=[[MKPointAnnotation alloc] init];
[endLocation setCoordinate:CLLocationCoordinate2DMake([[latLongDic valueForKey:#"lat"] floatValue], [[latLongDic valueForKey:#"lng"] floatValue])];
endLocation.title=[textField.text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
}
NSLog(#"object at index is viewport %#",[[[[[locationDic valueForKey:#"results"] objectAtIndex:0] valueForKey:#"geometry"]valueForKey:#"viewport"] valueForKey:#"northeast"]);
}
#pragma mark Getting lat long from place name.
-(NSDictionary*)getLatLongOfPlace:(NSString*)place
{
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true",place];
NSLog(#"Fired URL:- %#",apiUrlStr);
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSDictionary *dic=[apiResponse objectFromJSONString];
return dic;
}
Here is SampleCode I made
NOTE:--- In case if sample doesn't work for u jsut this line in viewDidLoad Method
// [__mapView setShowsUserLocation:YES];
Screenshot
#import "ViewController.h"
#import "JSONKit.h"
#interface ViewController ()
#end
#implementation ViewController
NSMutableArray *locationarry ;
NSMutableDictionary * citywiselatlong ;
- (void)viewDidLoad
{
locationarry = [[NSMutableArray alloc]initWithObjects:#"Ahmedabad",#"Rajkot",#"Baroda",#"Surat", nil];
citywiselatlong = [[NSMutableDictionary alloc]init];
[self locationfind];
NSMutableString* TotalXMLString = [[NSMutableString alloc]init];
[TotalXMLString appendFormat:#"http://maps.googleapis.com/maps/api/distancematrix/json?origins="];
[TotalXMLString appendFormat:#"%#,%#&destinations=",[[citywiselatlong valueForKey:[locationarry objectAtIndex:0]] valueForKey:#"lat"] ,[[citywiselatlong valueForKey:[locationarry objectAtIndex:0]] valueForKey:#"lng"]];
for (int i = 1; i < [locationarry count]; i++) {
[TotalXMLString appendFormat:#"%#,%#",[[citywiselatlong valueForKey:[locationarry objectAtIndex:i]] valueForKey:#"lat"] ,[[citywiselatlong valueForKey:[locationarry objectAtIndex:i]] valueForKey:#"lng"]];
if (i != [locationarry count] -1 ) {
[TotalXMLString appendFormat:#"|"];
}
else
{
[TotalXMLString appendFormat:#"&mode=driving&sensor=false"];
}
}
NSURL* apiUrl = [NSURL URLWithString:[TotalXMLString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSDictionary *dic=[apiResponse objectFromJSONString];
NSLog(#"%#",dic);
NSMutableArray * distance = [[NSMutableArray alloc]initWithArray:[[[[dic valueForKey:#"rows"] objectAtIndex:0] valueForKey:#"elements"]valueForKey:#"distance"]];
for (int j= 0 ; j < [distance count]; j++) {
NSMutableDictionary *data = [[NSMutableDictionary alloc]initWithDictionary:[distance objectAtIndex:j]];
}
NSLog(#"%#",distance);
[__mapView setShowsUserLocation:YES];
[__mapView setZoomEnabled:YES];
[__mapView setScrollEnabled:YES];
[__mapView setMapType:MKMapTypeHybrid];
[__mapView setDelegate:self];
routes=[[NSArray alloc] init];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark- MKMapView delegate method
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor purpleColor];
polylineView.lineWidth = 5.0;
NSLog(#"polyline in viewFor overlay: %#",polylineView);
return polylineView;
}
- (void)mapView:(MKMapView *)mapView didUpdateUserLocation:(MKUserLocation *)userLocation
{
NSLog(#"did update user location called ");
MKCoordinateRegion region;
region.span.latitudeDelta = .005;
region.span.longitudeDelta = .005;
region.center = userLocation.coordinate;
[mapView setRegion:region animated:YES];
}
- (NSMutableArray *)decodePolyLine: (NSMutableString *)encoded
{
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\" options:NSLiteralSearch range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded 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 = [encoded 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 = [encoded 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("[%f,", [latitude doubleValue]);
//printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:loc];
}
return array;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t
{
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false&avoid=highways&mode=",saddr,daddr];
NSLog(#"Fired API %#",apiUrlStr);
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSDictionary *dic=[apiResponse objectFromJSONString];
if (dic!=nil) {
NSArray *routPoints=[[NSArray alloc] initWithArray:[dic valueForKey:#"routes"]];
NSDictionary *polylineOverview=[[routPoints objectAtIndex:0] valueForKey:#"overview_polyline"];
NSString *polylinePoints = [polylineOverview objectForKey:#"points"];
return [self decodePolyLine:[polylinePoints mutableCopy]];
}
return nil;
}
- (IBAction)drawPath:(id)sender {
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
[self showRouteFrom:startLocation to:endLocation];
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
if (polyLine) {
[__mapView setVisibleMapRect:[polyLine boundingMapRect]];
[__mapView addOverlay:polyLine];
}
NSLog(#"drawing path completed");
});
});
}
-(void) showRouteFrom: (id<MKAnnotation>)source to:(id<MKAnnotation>)destination;
{
routes = [self calculateRoutesFrom:source.coordinate to:destination.coordinate];
NSLog(#"routes are %#",routes);
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[polyLineArray addObject:polyLine];
}
- (IBAction)drawMultiple:(id)sender
{
polyLineArray=[[NSMutableArray alloc] init];
MKPointAnnotation *start=[[MKPointAnnotation alloc] init];
MKPointAnnotation *end=[[MKPointAnnotation alloc] init];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
for (int i=0;i<locationarry.count-1;i++)
{
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i] componentsSeparatedByString:#","]];
NSDictionary *dic=[citywiselatlong objectForKey:[part objectAtIndex:0]];
[start setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"lat"] floatValue], [[dic valueForKey:#"lng"] floatValue])];
part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i +1 ] componentsSeparatedByString:#","]];
dic=[citywiselatlong objectForKey:[part objectAtIndex:0]];
[end setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"lat"] floatValue], [[dic valueForKey:#"lng"] floatValue])];
[self showRouteFrom:start to:end];
}
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:0] componentsSeparatedByString:#","]];
NSDictionary *tempDic=[[NSDictionary alloc] initWithDictionary:[citywiselatlong objectForKey:[part objectAtIndex:0]]];
[start setCoordinate:CLLocationCoordinate2DMake([[tempDic valueForKey:#"lat"] floatValue], [[tempDic valueForKey:#"lng"] floatValue])];
if (polyLine) {
[__mapView setVisibleMapRect:[polyLine boundingMapRect]];
for (MKPolyline *pLine in polyLineArray) {
[__mapView addOverlay:pLine];
}
}
for (int i =0 ; i< [locationarry count]; i ++)
{
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i] componentsSeparatedByString:#","]];
NSDictionary *dic=[citywiselatlong objectForKey:[part objectAtIndex:0]];
MKPointAnnotation *first=[[MKPointAnnotation alloc] init];
MKPointAnnotation *second=[[MKPointAnnotation alloc] init];
[first setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"lat"] floatValue], [[dic valueForKey:#"lng"] floatValue])];
if(i+1<[locationarry count])
{
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i + 1] componentsSeparatedByString:#","]];
dic=[citywiselatlong objectForKey:[part objectAtIndex:0]];
[second setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"lat"] floatValue], [[dic valueForKey:#"lng"] floatValue])];
}
else
{
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i] componentsSeparatedByString:#","]];
dic=[citywiselatlong objectForKey:[part objectAtIndex:0]];;
[second setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"lat"] floatValue], [[dic valueForKey:#"lng"] floatValue])];
}
if (i==0)
{
[__mapView addAnnotation:first];
[__mapView addAnnotation:second];
}
else
{
[__mapView addAnnotation:second];
}
}
NSLog(#"drawing path completed");
});
});
}
-(void) centerMap
{
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90.0;
CLLocationDegrees maxLon = -180.0;
CLLocationDegrees minLat = 90.0;
CLLocationDegrees minLon = 180.0;
for(int idx = 0; idx < routes.count; idx++)
{
CLLocation* currentLocation = [routes 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.0;
region.center.longitude = (maxLon + minLon) / 2.0;
region.span.latitudeDelta = 0.01;
region.span.longitudeDelta = 0.01;
region.span.latitudeDelta = ((maxLat - minLat)<0.0)?100.0:(maxLat - minLat);
region.span.longitudeDelta = ((maxLon - minLon)<0.0)?100.0:(maxLon - minLon);
[__mapView setRegion:region animated:YES];
}
#pragma mark- UITextField delegate method
-(void)locationfind
{
for (int i = 0; i < [locationarry count]; i++) {
NSDictionary *locationDic=[self getLatLongOfPlace:[[locationarry objectAtIndex:i] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
NSDictionary *latLongDic=[[[[locationDic valueForKey:#"results"] objectAtIndex:0] valueForKey:#"geometry"]valueForKey:#"location"];
NSArray *part = [[NSArray alloc]initWithArray:[[locationarry objectAtIndex:i] componentsSeparatedByString:#","]];
[citywiselatlong setObject:latLongDic forKey:[part objectAtIndex:0]];
NSLog(#"%#",citywiselatlong);
}
}
#pragma mark Getting lat long from place name.
-(NSDictionary*)getLatLongOfPlace:(NSString*)place
{
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/geocode/json?address=%#&sensor=true",place];
NSLog(#"Fired URL:- %#",apiUrlStr);
NSURL* apiUrl = [NSURL URLWithString:[apiUrlStr stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSDictionary *dic=[apiResponse objectFromJSONString];
return dic;
}
#end
For drawing multiple points you can use it as
need to declare mutable array in header file
NSMutableArray *polyLineArray;
Implementation file need minor changes as ===
-(void) showRouteFrom: (id<MKAnnotation>)source to:(id<MKAnnotation>)destination;
{
NSLog(#"source title is %#",source.title);
NSLog(#"destination title is %#",destination.title);
routes = [self calculateRoutesFrom:source.coordinate to:destination.coordinate];
NSLog(#"routes are %#",routes);
NSInteger numberOfSteps = routes.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [routes objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyLine = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[polyLineArray addObject:polyLine];
// NSLog(#"poly line to be added as ovelay is %#",polyLine);
}
- (IBAction)drawMultiple:(id)sender
{
polyLineArray=[[NSMutableArray alloc] init];
NSDictionary *kolkata,*delhi,*chennai,*mumbai,*pune;
kolkata=[NSDictionary dictionaryWithObjectsAndKeys:#"location1",#"comments",#"1",#"id",#"23.0083321",#"latitude",#"88.54276659999",#"longitude",nil];
delhi=[NSDictionary dictionaryWithObjectsAndKeys:#"location2",#"comments",#"2",#"id",#"28.889816",#"latitude",#"77.3418147",#"longitude",nil];
chennai=[NSDictionary dictionaryWithObjectsAndKeys:#"location3",#"comments",#"3",#"id",#"13.23339843",#"latitude",#"80.3322912",#"longitude",nil];
mumbai=[NSDictionary dictionaryWithObjectsAndKeys:#"location4",#"comments",#"4",#"id",#"19.2716339",#"latitude",#"72.9864994",#"longitude",nil];
pune=[NSDictionary dictionaryWithObjectsAndKeys:#"location5",#"comments",#"5",#"id",#"18.6346965",#"latitude",#"73.9894867",#"longitude",nil];
NSArray *arrayOfLocations=[[NSArray alloc] initWithObjects:kolkata,delhi,chennai,mumbai,pune,nil];
MKPointAnnotation *start=[[MKPointAnnotation alloc] init];
MKPointAnnotation *end=[[MKPointAnnotation alloc] init];
dispatch_async(dispatch_get_global_queue( DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){
//Background Thread
for (int i=0;i<arrayOfLocations.count-1;i++)
{
NSDictionary *dic=[arrayOfLocations objectAtIndex:i];
[start setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"latitude"] floatValue], [[dic valueForKey:#"longitude"] floatValue])];
dic=[arrayOfLocations objectAtIndex:i+1];
[end setCoordinate:CLLocationCoordinate2DMake([[dic valueForKey:#"latitude"] floatValue], [[dic valueForKey:#"longitude"] floatValue])];
[self showRouteFrom:start to:end];
}
dispatch_async(dispatch_get_main_queue(), ^(void){
//Run UI Updates
NSDictionary *tempDic=[[NSDictionary alloc] initWithDictionary:[arrayOfLocations objectAtIndex:0]];
[start setCoordinate:CLLocationCoordinate2DMake([[tempDic valueForKey:#"latitude"] floatValue], [[tempDic valueForKey:#"longitude"] floatValue])];
[__mapView addAnnotation:start];
[__mapView addAnnotation:end];
if (polyLine) {
[__mapView setVisibleMapRect:[polyLine boundingMapRect]];
for (MKPolyline *pLine in polyLineArray) {
[__mapView addOverlay:pLine];
}
}
NSLog(#"drawing path completed");
});
});
}
If u need sample code here it is
Output is --------
Use BreadCrumbs here is the sample code ..it is very useful ...u can customize the code according to ur requirement
https://developer.apple.com/library/ios/samplecode/Breadcrumb/Introduction/Intro.html

Mapkit draw route problems

I am developing an application in which I need to draw a route between two points using lat/long.
I have used google API to get polylines and drawing it after decoding it.
Problems:
Route is not in the middle of the road (Attached image_1)
While zooming in/out route doesn't draw completely (Attached image_2)
Below is the code:
if(!routeView)
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, self.mapView.frame.origin.y, mapView.frame.size.width, self.mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
[self.lat1 resignFirstResponder];
[self.long1 resignFirstResponder];
[self.lat2 resignFirstResponder];
[self.long2 resignFirstResponder];
NSString* saddr = [NSString stringWithFormat:#"%#,%#",self.lat1.text,self.long1.text];
NSString* daddr = [NSString stringWithFormat:#"%#,%#",self.lat2.text,self.long2.text];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.apple.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSError *error;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSData *responseData = [apiResponse dataUsingEncoding:NSUTF8StringEncoding];
NSError* error1;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&error1];
NSLog(#"Error: %#\n%#",[error1 localizedDescription],[error1 localizedFailureReason]);
if([[json objectForKey:#"status"] isEqualToString:#"OK"])
{
NSArray *routes1 = [json objectForKey:#"routes"];
NSDictionary *route = [routes1 lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
routes = [self decodePolyLine:overviewPolyline];
//NSLog(#"%#",[routes objectAtIndex:0]);
[self updateRouteView];
[self centerMap];
}
}
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
One possible reason that your route is misaligned is that your route is coming rom Google (http://maps.apple.com/maps redirects to http://maps.google.com/maps) and you are drawing it on Apple's maps. Their data is slightly different.
The partially drawn route I can't solve, but I would suggest you add an MKPolyline rather than a static image overlay. They invented that line drawing tool for a good reason.

Draw Route on google Map in iphone

I want to draw route on mapview using latitude and longitude. how is it possible to draw?
Here is my code. but it is not working. i have added location in points Mutable array. and after that called drawRoute function to draw route between that location.
- (void)viewDidLoad {
[super viewDidLoad];
CLLocationCoordinate2D location;
location.latitude = (double) 23.00000;
location.longitude = (double) 73.00000;
CLLocationCoordinate2D location2;
location2.latitude = (double) 73.00000;
location2.longitude = (double) 23.00000;
CLLocation *locationPoint1 = [[CLLocation alloc]initWithLatitude:location.latitude longitude:location.longitude];
CLLocation *locationPoint2 = [[CLLocation alloc]initWithLatitude:location2.latitude longitude:location2.longitude];
[self.points addObject:locationPoint1];
[self.points addObject:locationPoint2];
[self performSelector:#selector(drowRoute)];
}
-(void)drowRoute{
CGContextRef context = UIGraphicsGetCurrentContext();
// CGContextSetStrokeColorWithColor(context, [[UIColor blueColor]CGColor]);
CGContextSetLineWidth(context, 2.0);
for(int idx = 0; idx < self.points.count; idx++)
{
CLLocation* location = [self.points objectAtIndex:idx];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:self.view];
if(idx == 0)
{
// move to the first point
CGContextMoveToPoint(context, point.x, point.y);
}
else
{
CGContextAddLineToPoint(context, point.x, point.y);
}
}
CGContextStrokePath(context);
}
I use it using Goggle Map Services. You just have to pass longitude and latitude as a parameter to URL and rest is taken care by Google maps.
- (void)viewDidLoad
{
[super viewDidLoad];
locationManager = [[CLLocationManager alloc] init];
locationManager.delegate = self;
locationManager.distanceFilter = kCLDistanceFilterNone;
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters;
[locationManager startUpdatingLocation];
NSString *url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=%f,%f&daddr=%f,%f",c_lat,c_long,lat,lat];
//saddr= we pass source address long, lat.
//daddr= we pass destination address long, lat.
//--------use this if you have current long,lat and destination's address or street name etc...
NSString* url = [NSString stringWithFormat: #"http://maps.google.com/maps?saddr=%f,%f&daddr=%#",
currentLocation.latitude, currentLocation.longitude,
[address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
//------------------------------------------------------------------------------
[[UIApplication sharedApplication] openURL: [NSURL URLWithString:url]]; // this line will open Google map on Maps application on device and in Safari in Simulator.
}
- (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation
{
curntloc = [[CLLocation alloc] initWithLatitude:newLocation.coordinate.latitude longitude:newLocation.coordinate.longitude];
NSLog(#"in func--> %f %f",curntloc.coordinate.latitude, curntloc.coordinate.longitude);
}
Use following code:
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index < len) {
NSInteger b;
NSInteger shift = 0;
NSInteger result = 0;
do {
b = [encoded 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 = [encoded 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] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(void) centerMap {
MKCoordinateRegion region;
CLLocationDegrees maxLat = -90;
CLLocationDegrees maxLon = -180;
CLLocationDegrees minLat = 90;
CLLocationDegrees minLon = 180;
for(int idx = 0; idx < routes.count; idx++)
{
CLLocation* currentLocation = [routes 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;
[mapView setRegion:region animated:YES];
}
-(void) calculate_distance{
float target = [location1 distanceFromLocation:location2]/1000;
text2=[NSString stringWithFormat:#"%fkm",target];
routes = [[self calculateRoutesFrom:location1.coordinate to:location2.coordinate] retain];
if([routes count]!=0){
[self updateRouteView];
[self centerMap];
UIAlertView* alert1=[[UIAlertView alloc]initWithTitle:#"MESSAGE" message:text2 delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert1 show];
[alert1 release];
}
else{
UIAlertView* alert=[[UIAlertView alloc]initWithTitle:#"MESSAGE" message:#"We could not draw direction between your desired locations" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alert show];
[alert release];
}
location1=0;
location2=0;
}
-(void) updateRouteView {
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i < routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [mapView convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
CGContextRelease(context);
}
Here is an example source code for drawing route on the map using lat,long coordinates.
http://developer.apple.com/library/ios/#samplecode/Breadcrumb/Introduction/Intro.html
This is how i learnt to do the very task.
Besides, to draw lines, in this post you will find classes for annotation. Check out the source code in the post, it will be more then sufficient to help you i hope.
By using the classes in the second link i have post, you will just have to provide the coordinates (lat,long) and the classes will do the rest :)
I use the code given below to draw a route between two locations:
- (void)fetchPolylineWithOrigin:(CLLocation *)origin destination:(CLLocation *)destination {
NSString *originString = [NSString stringWithFormat:#"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
NSString *destinationString = [NSString stringWithFormat:#"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];
NSString *directionsAPI = #"https://maps.googleapis.com/maps/api/directions/json?";
NSString *directionsUrlString = [NSString stringWithFormat:#"%#&origin=%#&destination=%#&mode=driving", directionsAPI, originString, destinationString];
NSURL *directionsUrl = [NSURL URLWithString:directionsUrlString];
NSURLSessionDataTask *fetchDirectionsTask = [[NSURLSession sharedSession] dataTaskWithURL:directionsUrl completionHandler:
^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
if(error) {
//Error in fetching poline
return;
}
NSArray *routesArray = [json objectForKey:#"routes"];
if ([routesArray count] > 0) {
NSDictionary *routeDict = [routesArray objectAtIndex:0];
NSDictionary *routeOverviewPolyline = [routeDict objectForKey:#"overview_polyline"];
NSString *points = [routeOverviewPolyline objectForKey:#"points"];
GMSPath *path = [GMSPath pathFromEncodedPath:points];
[self drawPath:path];
}
}];
[fetchDirectionsTask resume];
}
- (void)drawPath:(GMSPath *)newPath {
GMSPolyline *polyline = [GMSPolyline polylineWithPath:newPath];
polyline.strokeColor =PathColor;
polyline.strokeWidth = 2.5;
polyline.geodesic = YES;
NSArray *styles = #[[GMSStrokeStyle solidColor:PathColor],
[GMSStrokeStyle solidColor:PathColor]];
NSArray *lengths = #[#100000, #50000];
polyline.spans = GMSStyleSpans(polyline.path, styles, lengths, kGMSLengthRhumb);
polyline.map = _mapView;
}

How to draw lines on a google maps

I want to draw lines over google maps, the lines may be straight or curve, but i want to draw lines such that they connect two points, that may be at any geographical locations.
Thanks.
GuruPrasad R Gujjar.
Here is the example code, please try with this.
EDIT:Also you have to download "RegexKitLite" header file and class file.
// This method will calculate the routes and return an array with point
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t {
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl];
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(NSMutableArray *)decodePolyLine: (NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease];
NSInteger lat=0;
NSInteger lng=0;
while (index = 0x20);
NSInteger dlat = ((result & 1) ? ~(result >> 1) : (result >> 1));
lat += dlat;
shift = 0;
result = 0;
do {
b = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) = 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
// This method will draw the route with array of points.
-(void) updateRouteView
{
CGContextRef context = CGBitmapContextCreate(nil,
routeView.frame.size.width,
routeView.frame.size.height,
8,
4 * routeView.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context, lineColor.CGColor);
CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context, 3.0);
for(int i = 0; i &ls; routes.count; i++) {
CLLocation* location = [routes objectAtIndex:i];
CGPoint point = [map convertCoordinate:location.coordinate toPointToView:routeView];
if(i == 0) {
CGContextMoveToPoint(context, point.x, routeView.frame.size.height - point.y);
} else {
CGContextAddLineToPoint(context, point.x, routeView.frame.size.height - point.y);
}
}
CGContextStrokePath(context);
CGImageRef image = CGBitmapContextCreateImage(context);
UIImage* img = [UIImage imageWithCGImage:image];
routeView.image = img;
//[self.view addSubview:routeView];
CGContextRelease(context);
//29-07-10
CGContextRef context2 = CGBitmapContextCreate(nil,
routeView2.frame.size.width,
routeView2.frame.size.height,
8,
4 * routeView2.frame.size.width,
CGColorSpaceCreateDeviceRGB(),
kCGImageAlphaPremultipliedLast);
CGContextSetStrokeColorWithColor(context2, lineColor2.CGColor);
CGContextSetRGBFillColor(context2, 0.0, 0.0, 1.0, 1.0);
CGContextSetLineWidth(context2, 3.0);
for(int i = 0; i &ls; routes2.count; i++) {
CLLocation* location2 = [routes2 objectAtIndex:i];
CGPoint point2 = [map convertCoordinate:location2.coordinate toPointToView:routeView2];
if(i == 0) {
CGContextMoveToPoint(context2, point2.x, routeView2.frame.size.height - point2.y);
} else {
CGContextAddLineToPoint(context2, point2.x, routeView2.frame.size.height - point2.y);
}
}
CGContextStrokePath(context2);
CGImageRef image2 = CGBitmapContextCreateImage(context2);
UIImage* img2 = [UIImage imageWithCGImage:image2];
routeView2.image = img2;
//[self.view addSubview:routeView];
CGContextRelease(context2);
}
I think it will help you to complete your task.
Refer this Link1 and Link2. It might be helpful for you.
You'll need to use JavaScript and the Google Maps API - Key is free if I remember right.
Everything else here:
http://code.google.com/apis/maps/documentation/javascript/v2/overlays.html#Drawing_Polylines

how to draw line between two points?

i want to draw line between two points in my view how it possible.?
Edit:ya thax.i have got solution. Line draw perfectly.I want to draw multiple line with different points.I am using for loop and every rotaion i pass the start and end points.but only last point is drawn.how to solve this problem?
You need to use a few CoreGraphics functions:
// get the current context
CGContextRef context = UIGraphicsGetCurrentContext();
// set the stroke color and width
CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 1.0);
CGContextSetLineWidth(context, 2.0);
// move to your first point
CGContextMoveToPoint(context, 10.0, 10.0);
// add a line to your second point
CGContextAddLineToPoint(context, 50.0, 10.0);
// tell the context to draw the stroked line
CGContextStrokePath(context);
This example would draw a horizontal white line with a thickness of 2. Apple has some great sample code and tutorials including the QuartzDemo tutorial: http://developer.apple.com/iPhone/library/samplecode/QuartzDemo/index.html.
The QuartzDemo application has great examples of how to use CoreGraphics, including lines and bezier curves. download here
Take a look at QuartzLineDrawing.m in the sample code. You'll be able to find some great examples there :-)
Since this is 09' answers and whatnot I figure I update the link and code here for anyone looking in 11'.
The link for the Quartz Demo is: http://developer.apple.com/library/ios/#samplecode/QuartzDemo/Introduction/Intro.html
and the code I use to draw multiple lines is:
//Drawing lines
// Set the color that we want to use to draw the line
[ [ UIColor brownColor] set];
//Get the current graphics context (pen)
CGContextRef currentContext = UIGraphicsGetCurrentContext();
// Set the width for the line
CGContextSetLineWidth(currentContext,
5.0f);
// Start the line at this point
CGContextMoveToPoint(currentContext,
20.0f,
20.0f);
// And end it at this point
CGContextAddLineToPoint(currentContext,
100.0f,
100.0f);
// Extend the line to another point
CGContextAddLineToPoint(currentContext,
300.0f,
100.0f);
//Use the context's current color to draw the line
CGContextStrokePath(currentContext);
I recommend reading Graphics and Animation on iOS: A Beginner's Guide to Core Graphics and Core Animation by Vandad Nahavandipoor. It's mostly on graphics than animation though. I recommend checking out his videos on animation if your interested. http://www.youtube.com/watch?v=ybMFPB-Gbsw&feature=player_embedded They're called Animations in iOS using Block Objects Part I and II. Supposedly there are supposed to be more videos at some point. But the videos go with the book.
That's it.
func locationManager(manager: CLLocationManager, didUpdateToLocation newLocation: CLLocation, fromLocation oldLocation: CLLocation)
{
let CurrentLogitude = String(format: "%.8f", newLocation.coordinate.longitude)
//print(CurrentLogitude)
let CurrentLatitude = String(format: "%.8f", newLocation.coordinate.latitude)
// print(CurrentLatitude)
//[self.locationManager stopUpdatingLocation];
}
func locationManager(manager: CLLocationManager, didFailWithError error: NSError)
{
}
func locationManager(manager: CLLocationManager,
didChangeAuthorizationStatus status: CLAuthorizationStatus)
{
var shouldIAllow = false
var locationStatus :String
switch status
{
case CLAuthorizationStatus.Restricted:
locationStatus = "Restricted Access to location"
case CLAuthorizationStatus.Denied:
locationStatus = "User denied access to location"
case CLAuthorizationStatus.NotDetermined:
locationStatus = "Status not determined"
default:
locationStatus = "Allowed to location Access"
shouldIAllow = true
}
NSNotificationCenter.defaultCenter().postNotificationName("LabelHasbeenUpdated", object: nil)
if (shouldIAllow == true)
{
NSLog("Location to Allowed")
// Start location services
locationManager.startUpdatingLocation()
} else {
NSLog("Denied access: \(locationStatus)")
}
}
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
{
let pin = MKAnnotationView(annotation: annotation, reuseIdentifier: "locationpin")
pin.image = UIImage(named: "locationpin.png")
let notationView: UIView = UIView()
notationView.frame = CGRectMake(0, 0, 400, 300)
notationView.backgroundColor = UIColor.grayColor()
pin.leftCalloutAccessoryView = notationView
pin.canShowCallout = true
return pin
}
#pragma mark - Mapview Delegate Method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKPinAnnotationView *pin = (MKPinAnnotationView *) [self.mapView dequeueReusableAnnotationViewWithIdentifier: #"id"];
if (!pin && ![annotation isKindOfClass:[MKUserLocation class]])
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
pin.pinTintColor=[UIColor blueColor];
pin.canShowCallout = true;
}
else
{
if (pin == nil)
{
pin = [[MKPinAnnotationView alloc] initWithAnnotation: annotation reuseIdentifier: #"id"] ;
}
else
{
pin.annotation = annotation;
}
pin.pinTintColor=[UIColor grayColor];
UIView *notationView=[[UIView alloc]init];
notationView.frame=CGRectMake(0, 0, 320, 300);
notationView.backgroundColor = [UIColor grayColor];
UILabel *lbl=[[UILabel alloc]init];
lbl.frame=CGRectMake(5, 5, 300, 25);
lbl.text=#"Current Location";
lbl.textColor=[UIColor whiteColor];
[notationView addSubview:lbl];
UIImageView *img=[[UIImageView alloc]init];
img.frame=CGRectMake(0, 0, 50,50);
img.image=[UIImage imageNamed:#"ios.png"];
// pin.leftCalloutAccessoryView = notationView;
// pin.rightCalloutAccessoryView = img;
//pin.detailCalloutAccessoryView=customView;
pin.animatesDrop = true;
pin.canShowCallout = true;
}
return pin;
}
-(IBAction)btnRoutePathClicked:(id)sender
{
[self.mapView removeAnnotation:point];
[self.mapView removeOverlay:polyline];
[self.mapView reloadInputViews];
MKCoordinateSpan span = MKCoordinateSpanMake(1.0, 1.0);
MKCoordinateRegion region = MKCoordinateRegionMake(currentLocation.coordinate, span);
[self.mapView setRegion:region];
[self.mapView setCenterCoordinate:currentLocation.coordinate animated:YES];
NSString *baseUrl = [NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true",[NSString stringWithFormat:#"%f,%f",currentLocation.coordinate.latitude,currentLocation.coordinate.longitude],[NSString stringWithFormat:#"22.45,72.4545"]];
//http://maps.googleapis.com/maps/api/directions/json?origin=51.194400,4.475816&destination=50.941278,6.958281&sensor=true
NSURL *url = [NSURL URLWithString:[baseUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
NSError *error = nil;
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:0 error:&error];
NSArray *routes = [result objectForKey:#"routes"];
if ([routes count]==0)
{
NSLog(#"Routs:=>%#",routes);
}
else
{
NSDictionary *firstRoute = [routes objectAtIndex:0];
NSDictionary *leg = [[firstRoute objectForKey:#"legs"] objectAtIndex:0];
NSDictionary *end_location = [leg objectForKey:#"end_location"];
double latitudes = [[end_location objectForKey:#"lat"] doubleValue];
double longitudes = [[end_location objectForKey:#"lng"] doubleValue];
CLLocationCoordinate2D coordinate = CLLocationCoordinate2DMake(latitudes, longitudes);
point = [[MKPointAnnotation alloc] init];
point.coordinate = coordinate;
point.title = [leg objectForKey:#"end_address"];
[self.mapView addAnnotation:point];
NSDictionary *route = [routes lastObject];
if (route)
{
NSString *overviewPolyline = [[route objectForKey: #"overview_polyline"] objectForKey:#"points"];
NSMutableArray *_path = [self decodePolyLine:overviewPolyline];
NSInteger numberOfSteps = _path.count;
CLLocationCoordinate2D coordinates[numberOfSteps];
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [_path objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
coordinates[index] = coordinate;
}
polyline = [MKPolyline polylineWithCoordinates:coordinates count:numberOfSteps];
[self.mapView addOverlay:polyline];
}
}
}];
}
-(NSMutableArray *)decodePolyLine:(NSString *)encodedStr
{
NSMutableString *encoded = [[NSMutableString alloc] initWithCapacity:[encodedStr length]];
[encoded appendString:encodedStr];
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded 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 = [encoded 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 = [encoded characterAtIndex:index++] - 63;
result |= (b & 0x1f) << shift;
shift += 5;
} while (b >= 0x20);
NSInteger dlng = ((result & 1) ? ~(result >> 1) : (result >> 1));
lng += dlng;
NSNumber *latitudes = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitudes = [[NSNumber alloc] initWithFloat:lng * 1e-5];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[latitudes floatValue] longitude:[longitudes floatValue]];
[array addObject:location];
}
return array;
}
- (MKPolylineRenderer *)mapView:(MKMapView *)mapView viewForOverlay:(id)overlay{
MKPolylineRenderer *polylineView = [[MKPolylineRenderer alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor redColor];
polylineView.lineWidth = 4.0;
polylineView.alpha = 0.5;
return polylineView;
}