road map from location A to location B by latitude and longitude - iphone

I am doing work with map and location. I want to have road map from one location to another location. I am providing latitude and longitude of both the location(destination and source). So please help me to have this map.
I read about Google map api but I didn't find perfect answer.

Use below URL of google map API to find the road map route between two locations
http://maps.google.com/?saddr=STARTINGADDRESS&daddr=DESTINATIONADDRESS

First you have to take the directions from Google. Like this:
NSError *error = nil;
NSString *directionsInJSON = [NSString stringWithContentsOfURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/directions/json?origin=%f,%f&destination=%f,%f&sensor=true",start.coordinate.latitude , start.coordinate.longitude , destination.coordinate.latitude, destination.coordinate.longitude]]encoding:NSUTF8StringEncoding error:&error];
After that , parse the JSON you got above:
if (error == nil)
{
NSError *JSONError = nil;
SBJsonParser *JSONParser = [[SBJsonParser alloc] init];
id directions = [JSONParser objectWithString:directionsInJSON error:&JSONError];
if (JSONError == nil)
{
directions = (NSDictionary*)directions;
NSString *status = [directions objectForKey:#"status"];
if ([status isEqualToString:#"OK"])
{
NSArray *routes = [directions objectForKey:#"routes"];
NSDictionary *route = [routes objectAtIndex:0];
NSDictionary *polylineOverview = [route objectForKey:#"overview_polyline"];
NSString *polylinePoints = [polylineOverview objectForKey:#"points"];
NSArray *decodedPolyline = [self decodePolyLine:polylinePoints];
[self loadRouteWithPoints:decodedPolyline];
}
else
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:#"No routes found" message:#"Sorry , we couldn't find any routes between you two." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil] autorelease];
[alert show];
}
}
}
else
{
NSLog(#"error: %#",error.description);
}
Now you need these methods:
-(void) loadRouteWithPoints:(NSArray *) routes
{
CLLocationCoordinate2D coords[[routes count]];
for(int i = 0; i < routes.count; i++)
{
CLLocation* loc = (CLLocation*)[routes objectAtIndex:i];//[NSKeyedUnarchiver unarchiveObjectWithData:[routes objectAtIndex:i]];
CLLocationCoordinate2D c;
c.latitude = loc.coordinate.latitude;
c.longitude = loc.coordinate.longitude;
coords[i] = c;
}
MKPolyline *line = [[MKPolyline polylineWithCoordinates:(CLLocationCoordinate2D*)coords count:[routes count]] retain];
[self.mapsView addOverlay:line];
}
And:
- (NSMutableArray *)decodePolyLine: (NSString *)encoded
{
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;
}
Voila!
Cheers!

Related

Drawing a route on Apple map (iOS 6+)

I was looking for many code samples of how to draw a polyline on MKMapView like the second answer (from above) in this link. However, will that solution work on iOS 6 Apple maps? If not, can you provide a link to a sample code that draws the route on Apple maps?
Yes, it'll work.
Google maps and apple maps are different a little bit, could be some little inaccuracies.
All the API's are almost same.
P.S. I use google routes in my app since iOS5 and haven't got any problems when updated app for iOS6.
-(void)load_mapView{
Place* home = [[[Place alloc] init] autorelease];
home.name = strAdd;
CLLocationCoordinate2D loc=[self geoCodeUsingAddress:strAdd Status:1];
home.latitude =loc.latitude;
home.longitude =loc.longitude;
Place* office = [[[Place alloc] init] autorelease];
office.name = endAdd;
CLLocationCoordinate2D loc2=[self geoCodeUsingAddress:endAdd Status:2];;
office.latitude = loc2.latitude;
office.longitude = loc2.longitude;
//*******
routeView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, mapView.frame.size.width, mapView.frame.size.height)];
routeView.userInteractionEnabled = NO;
[mapView addSubview:routeView];
lineColor = [UIColor colorWithWhite:0.2 alpha:0.5];
[self showRouteFrom:home to:office];
[activityIndicator stopAnimating];
}
- (CLLocationCoordinate2D) geoCodeUsingAddress:(NSString *)address Status:(NSInteger )sts
{
double latitude = 0, longitude = 0;
NSString *esc_addr = [address stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *req = [NSString stringWithFormat:#"http://maps.google.com/maps/api/geocode/json?sensor=false&address=%#", esc_addr];
NSString *result = [NSString stringWithContentsOfURL:[NSURL URLWithString:req] encoding:NSUTF8StringEncoding error:NULL];
if (result) {
NSScanner *scanner = [NSScanner scannerWithString:result];
if ([scanner scanUpToString:#"\"lat\" :" intoString:nil] && [scanner scanString:#"\"lat\" :" intoString:nil]) {
[scanner scanDouble:&latitude];
if ([scanner scanUpToString:#"\"lng\" :" intoString:nil] && [scanner scanString:#"\"lng\" :" intoString:nil]) {
[scanner scanDouble:&longitude];
}
}
}
CLLocationCoordinate2D center;
center.latitude = latitude;
center.longitude = longitude;
return center;
}
-(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];
// printf("[%f,", [latitude doubleValue]);
// printf("%f]", [longitude doubleValue]);
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];
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable){
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];
// NSLog(#"encodedPoints.....%#",encodedPoints);
// NSLog(#"self decodePolyLine:[encodedPoints mutableCopy].....%#",[self decodePolyLine:[encodedPoints mutableCopy]]);
NSLog(#"return %# ",[encodedPoints mutableCopy]);
return [self decodePolyLine:[encodedPoints mutableCopy]];
}else{
[activityIndicator stopAnimating];
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:#"Oops!" message:#"Railway server is either busy or not responding at the moment. Try again later." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
return 0;
}
}
-(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) showRouteFrom: (Place*) f to:(Place*) t {
if(routes) {
[mapView removeAnnotations:[mapView annotations]];
[routes release];
}
PlaceMark* from = [[[PlaceMark alloc] initWithPlace:f] autorelease];
PlaceMark* to = [[[PlaceMark alloc] initWithPlace:t] autorelease];
[mapView addAnnotation:from];
[mapView addAnnotation:to];
Reachability *reachability = [Reachability reachabilityForInternetConnection];
NetworkStatus internetStatus = [reachability currentReachabilityStatus];
if (internetStatus != NotReachable){
routes = [[self calculateRoutesFrom:from.coordinate to:to.coordinate] retain];
[self drawRoute];
[self centerMap];
}else{
[activityIndicator stopAnimating];
UIAlertView *alert =[[UIAlertView alloc]initWithTitle:#"Oops!" message:#"Railway server is either busy or not responding at the moment. Try again later." delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil, nil];
[alert show];
}
}
- (void)drawRoute
{
int numPoints = [routes count];
if (numPoints > 1)
{
CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
for (int i = 0; i < numPoints; i++)
{
CLLocation* current = [routes objectAtIndex:i];
coords[i] = current.coordinate;
}
objPolyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
free(coords);
[mapView addOverlay:objPolyline];
[mapView setNeedsDisplay];
}
}
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *thePolylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
thePolylineView.strokeColor = [UIColor colorWithRed:((float) 204.0 / 255.0f)green:((float) 7.0 / 255.0f)blue:((float) 40.0 / 255.0f)alpha:1.0f]; // <-- So important stuff here
thePolylineView.lineWidth = 5.0;
return thePolylineView;
}

potential leak issues

Firstly Please tell me what is potential leak and why it comes.
Potential leak is coming...
Here is My code
-(NSArray*)calculateRoutesFrom:(CLLocationCoordinate2D) f to: (CLLocationCoordinate2D) t
{
//NSLog(#"maproute....5..");
NSString* saddr = [NSString stringWithFormat:#"%f,%f", f.latitude, f.longitude];
NSString* daddr = [NSString stringWithFormat:#"%f,%f", t.latitude, t.longitude];
NSError* error;
NSString* apiUrlStr = [NSString stringWithFormat:#"http://maps.google.com/maps?output=dragdir&saddr=%#&daddr=%#&dirflg=w", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
NSLog(#"api url: %#", apiUrl);
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
NSLog(#"what is this");
NSString* encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
NSLog(#"maproute....4..");
return [self decodePolyLine:[encodedPoints mutableCopy]]; // Here is The potential leak
}
I tried doing this
return [self decodePolyLine:[encodedPoints mutableCopy]autorelease];
but it send to many time autorelease message.
What to do Please help.
-(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];
printf("[%f,", [latitude doubleValue]);
printf("%f]", [longitude doubleValue]);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]] autorelease];
[array addObject:loc];
}
return array;
}
You correctly diagnosed the problem, that your mutableCopy is never getting released. But you said [self decodePolyLine:[encodedPoints mutableCopy] autorelease] didn't work. It can't, though, because you're missing a set of brackets in there. The correct solution, which does the autorelease on the string, is:
return [self decodePolyLine:[[encodedPoints mutableCopy] autorelease]];
You will get your too many releases if you did the autorelease on the resulting NSMutableArray, though, via something like this:
return [[self decodePolyLine:[encodedPoints mutableCopy]] autorelease];
This latter use of autorelease is problematic. But, the first proposed change should fix the problem.
Having said that, I'd suggest a further simplification of the code. I'd be wary about methods that change mutable parameters that I pass to them (unless that behavior is needed for some reason, which it doesn't appear to be the case here). I'd rather see:
-(NSMutableArray *)decodePolyLine:(NSString *)encodedInput {
{
NSString *encoded = [encodedInput stringByReplacingOccurrencesOfString:#"\\\\"
withString:#"\\"];
NSInteger len = [encoded length];
// the rest of your method here
}
Then you can invoke this simply as:
return [self decodePolyLine:encodedPoints];
This also has the coincidental virtue of completely eliminating the problematic statement.
Unrelated to your problem, you could simplify your lines that say:
NSNumber *latitude = [[[NSNumber alloc] initWithFloat:lat * 1e-5] autorelease];
NSNumber *longitude = [[[NSNumber alloc] initWithFloat:lng * 1e-5] autorelease];
to be:
NSNumber *latitude = [NSNumber numberWithFloat:lat * 1e-5];
NSNumber *longitude = [NSNumber numberWithFloat:lng * 1e-5];
Or even better, maybe retire NSNumber altogether with just
float latitude = lat * 1e-5;
float longitude = lng * 1e-5;
printf("[%f,", latitude);
printf("%f]", longitude);
CLLocation *loc = [[[CLLocation alloc] initWithLatitude:latitude
longitude:longitude] autorelease];

Finding Path/Route Between two points on MapKit in iPhone

I am trying to find the path between two locations on Mapkit. All I have is two locations. Now I have to find the exact path between these points and draw a line between these points using MapKit. I have gone through several examples in which they are using .csv files. In that .csv file they have stored the latitude and longitude values of the full path and drawing line based on those values.
But here I am trying to draw a line without knowing the path. So is there any way to find the path dynamically and draw a line?
Below is the code to finds path & draws line between two locations.
To implement below class:
_mapRecord = [[PSMapDirection alloc] initWithFrame:CGRectMake(0.0, 49.0, 320.0, 411.0)];
[self.view addSubview:_mapRecord];
MapDirection.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "RegexKitLite.h"
#interface MapDirection : UIView<MKMapViewDelegate>
{
MKMapView* mapView;
NSArray* routes;
BOOL isUpdatingRoutes;
}
-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t;
#end
MapDirection.m
#import "MapDirection.h"
#interface MapDirection()
-(NSArray*) calculateRoutesFrom:(CLLocationCoordinate2D) from to: (CLLocationCoordinate2D) to;
-(void) centerMap;
#end
- (id) initWithFrame:(CGRect) frame
{
self = [super initWithFrame:frame];
if (self != nil)
{
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, frame.size.width, frame.size.height)];
mapView.showsUserLocation = NO;
[mapView setDelegate:self];
[self addSubview:mapView];
}
return self;
}
- (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.google.com/maps?output=dragdir&saddr=%#&daddr=%#", saddr, daddr];
NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];
//NSLog(#"api url: %#", apiUrl);
NSError* error = nil;
NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSASCIIStringEncoding error:&error];
NSString *encodedPoints = [apiResponse stringByMatching:#"points:\\\"([^\\\"]*)\\\"" capture:1L];
return [self decodePolyLine:[encodedPoints mutableCopy]];
}
-(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];
}
-(void) showRouteFrom: (MKAnnotation*) f to:(MKAnnotation*) t
{
if(routes)
{
[mapView removeAnnotations:[mapView annotations]];
}
[mapView addAnnotation:f];
[mapView addAnnotation:t];
routes = [self calculateRoutesFrom:f.coordinate to:t.coordinate];
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];
[mapView addOverlay:polyLine];
[self centerMap];
}
#pragma mark MKPolyline delegate functions
- (MKOverlayView *)mapView:(MKMapView *)mapView viewForOverlay:(id <MKOverlay>)overlay
{
MKPolylineView *polylineView = [[MKPolylineView alloc] initWithPolyline:overlay];
polylineView.strokeColor = [UIColor purpleColor];
polylineView.lineWidth = 5.0;
return polylineView;
}
#end
Sample Map Route for starting points - "41.967659,-87.627869" and destination points - "41.574361,-91.083069"
Here The way in which I am able to draw direction between two points(Location).
First of all download GoogleMap sdk from this link and integrate into your application.
Now API key required and you can create as par given guidelines on this link.
Below are Code that draw direction on google map between two location.
-(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];
NSURL *url=[NSURL URLWithString:[NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false&avoid=highways&mode=driving",saddr,daddr]];
NSError *error=nil;
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init] ;
[request setURL:url];
[request setHTTPMethod:#"POST"];
NSURLResponse *response = nil;
NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error: &error];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSDictionary * dic = [NSJSONSerialization JSONObjectWithData:[responseString dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONWritingPrettyPrinted error:nil];
return [self decodePolyLine:[self parseResponse:dic]];
}
- (NSString *)parseResponse:(NSDictionary *)response {
NSArray *routes = [response objectForKey:#"routes"];
NSDictionary *route = [routes lastObject];
if (route) {
NSString *overviewPolyline = [[route objectForKey:
#"overview_polyline"] objectForKey:#"points"];
return overviewPolyline;
}
return #"";
}
-(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 *latitude = [[NSNumber alloc] initWithFloat:lat * 1e-5];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
CLLocation *location = [[CLLocation alloc] initWithLatitude:
[latitude floatValue] longitude:[longitude floatValue]];
[array addObject:location];
}
return array;
}
- (void)loadMapViewWithDirection {
float lat = 23.050671;
float lng = 72.541351;
GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:lat
longitude:lng
zoom:10];
GMSMapView * mapView = [GMSMapView mapWithFrame:CGRectMake(0, 75, 320, self.view.frame.size.height-kHeaderRect.size.height) camera:camera];
self.mapView.myLocationEnabled = YES;
float sourceLatitude = 23.050671;
float sourceLongitude = 72.541351;
float destLatitude = 23.036138;
float destLongitude = 72.603836;
GMSMarker *sourceMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude);
marker.map = self.mapView;
GMSMarker *destMarker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(destLatitude, destLongitude);
marker.map = self.mapView;
self.mapView.delegate = self;
[self drawDirection:CLLocationCoordinate2DMake(sourceLatitude, sourceLongitude) and:CLLocationCoordinate2DMake(destLatitude, destLongitude)];
[self.view addSubview:self.mapView];
}
- (void) drawDirection:(CLLocationCoordinate2D)source and:(CLLocationCoordinate2D) dest {
GMSPolyline *polyline = [[GMSPolyline alloc] init];
GMSMutablePath *path = [GMSMutablePath path];
NSArray * points = [self calculateRoutesFrom:source to:dest];
NSInteger numberOfSteps = points.count;
for (NSInteger index = 0; index < numberOfSteps; index++)
{
CLLocation *location = [points objectAtIndex:index];
CLLocationCoordinate2D coordinate = location.coordinate;
[path addCoordinate:coordinate];
}
polyline.path = path;
polyline.strokeColor = [UIColor redColor];
polyline.strokeWidth = 2.f;
polyline.map = self.mapView;
// Copy the previous polyline, change its color, and mark it as geodesic.
polyline = [polyline copy];
polyline.strokeColor = [UIColor greenColor];
polyline.geodesic = YES;
polyline.map = self.mapView;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self loadMapViewWithDirection];
}
You can refer this code, it does exactly what you want.EDIT: and this also
I don't think you can do this locally. Implementing an algoritm for finding a path between two gps points requires a lot of input data (data from the maps) and you don't have this. Only a map provider can afford to implement such algoritm and expose an API for using it. I think Google have routing API, but I haven't played around with it...
https://developers.google.com/maps/documentation/directions/
Note that the TOS say that you have to display the results on a Google map, so you'll have to disable the functionality on the next iOS release

Drawing route partially not getting required output in iPhone MapView

I am trying to draw route between two points using polyline . I got somewhat route but not correct and I think it will get confused at the turn . I am using google api for getting points of route .Following is code what i tried please check .
- (IBAction)onclickDrawButton:(id)sender
{
flag=TRUE;
NSString *startpoint=[satrtTextfield text];
NSString *endpoint=[endTextfield text];
NSMutableString *urlString=[NSMutableString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=false",startpoint,endpoint];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request
delegate:self];
if(connection)
{
NSLog(#"connectin done");
}
}
-(void)connection:(NSURLConnection*)connection didReceiveResponse: (NSURLResponse*)response
{
if(flag)
{
recievedRoutes=[[NSMutableData alloc]init];
}
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
if(flag){
NSString *jsonResult = [[NSString alloc] initWithData:recievedRoutes encoding:NSUTF8StringEncoding];
NSLog(#"json response %#",jsonResult);
NSDictionary *partialJsonDict=[jsonResult JSONValue];
NSArray *items=[partialJsonDict valueForKey:#"routes"];
//NSLog(#"responsed valued %#",[[items objectAtIndex:0]valueForKey:#"legs"]);
NSArray *aary=[[items objectAtIndex:0]valueForKey:#"legs"];
NSLog(#"legs array wuth polyline %#",[[aary objectAtIndex:0]valueForKey:#"steps"]);
NSArray *steps=[[aary objectAtIndex:0]valueForKey:#"steps"];
NSLog(#"steps %#",[[steps objectAtIndex:1]objectForKey:#"polyline"]);
NSMutableString *string=[[NSMutableString alloc]init];
for(int i=0;i<[steps count];i++)
{
//NSLog(#"steps i value %#",[[[steps objectAtIndex:i]objectForKey:#"polyline"]objectForKey:#"sttpoints"]);
[string appendString:[[[steps objectAtIndex:i]objectForKey:#"polyline"]objectForKey:#"points"]];
}
NSLog(#"final %#",string);
MKPolyline *polyline=[self polylineWithEncodedString:string];
[mapView addOverlay:polyline];
[self zoomToFitMapAnnotations:mapView];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
if(flag){
[recievedRoutes appendData:data];
}
}
//to decode polyline and retrives coordintes i have used following method
-(MKPolyline *)polylineWithEncodedString:(NSString *)encodedString {
const char *bytes = [encodedString UTF8String];
NSUInteger length = [encodedString lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
NSUInteger idx = 0;
NSUInteger count = length / 4;
CLLocationCoordinate2D *coords = calloc(count, sizeof(CLLocationCoordinate2D));
NSUInteger coordIdx = 0;
float latitude = 0;
float longitude = 0;
while (idx < length) {
char byte = 0;
int res = 0;
char shift = 0;
do {
byte = bytes[idx++] - 63;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1));
latitude += deltaLat;
shift = 0;
res = 0;
do {
byte = bytes[idx++] - 0x3F;
res |= (byte & 0x1F) << shift;
shift += 5;
} while (byte >= 0x20);
float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1));
longitude += deltaLon;
float finalLat = latitude * 1E-5;
float finalLon = longitude * 1E-5;
CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(finalLat, finalLon);
coords[coordIdx++] = coord;
NSLog(#"in encoding %f %f ",latitude,longitude);
if (coordIdx == count) {
NSUInteger newCount = count + 10;
coords = realloc(coords, newCount * sizeof(CLLocationCoordinate2D));
count = newCount;
}
}
MKPolyline *polyline = [MKPolyline polylineWithCoordinates:coords count:coordIdx];
free(coords);
return polyline;
}
// to draw actual route
- (MKOverlayView *)mapView:(MKMapView *)mapView
viewForOverlay:(id<MKOverlay>)overlay {
MKPolylineView *overlayView = [[MKPolylineView alloc] initWithOverlay:overlay];
overlayView.lineWidth = 2;
overlayView.strokeColor = [UIColor purpleColor];
overlayView.fillColor = [[UIColor purpleColor] colorWithAlphaComponent:0.1f];
return overlayView;
}
After your line
NSArray *steps=[[aary objectAtIndex:0]valueForKey:#"steps"];
replace lines with this may work
NSMutableArray *polyLinesArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [steps count]; i++)
{
NSString* encodedPoints = [[[steps objectAtIndex:i] objectForKey:#"polyline"] valueForKey:#"points"];
MKPolyline *route = [self polylineWithEncodedString:encodedPoints];
[polyLinesArray addObject:route];
}
[self.mapView addOverlays:polyLinesArray];
[polyLinesArray release];

Calculating driving distance to a particular coordinate

Is there a way where i could get the driving distance to a particular geo-cordinate ? I am aware that i have to use http://maps.googleapis.com/maps/api/directions/output?parameters and get a JSON output to get the results.
Is there a tutorial that explains how to get this done? or any sample code where i start on?
You may try the following. This code fetches all directions (even the alternate ones) returned by Google Directions Services. You can get the distance in step 2 (parsing response)
Step 1: Enter the From and To Locations
NSMutableString *googleURL = [[NSMutableString alloc] initWithString:[NSString stringWithFormat:#"http://maps.googleapis.com/maps/api/directions/json?origin=%#&destination=%#&sensor=true&alternatives=true", searchFrom.text, searchTo.text]];
NSURL *url = [NSURL URLWithString:googleURL];
[googleURL release];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
[NSURLConnection connectionWithRequest:request delegate:self];
request = nil;
responseData = [[NSMutableData alloc] init];
Step 2: When you get the response of the query made, parse the result
- (id)parseResponseWithDictionary:(NSDictionary *)dictResponse {
if ([[dictResponse objectForKey:#"status"] isEqualToString:kGoogleDirectionsStatusOK]) {
NSArray *listRoutes = (NSArray *)[dictResponse objectForKey:#"routes"];
NSMutableString *result = nil;
NSMutableArray *listPolylines = nil;
for (NSDictionary *dictRouteValues in listRoutes) {
NSDictionary *dictPolyline = [dictRouteValues objectForKey:#"overview_polyline"];
if (!result) {
result = [[NSMutableString alloc] init];
}
[result appendString:[dictPolyline objectForKey:#"points"]];
if (!listPolylines) {
listPolylines = [[NSMutableArray alloc] init];
}
[listPolylines addObject:result];
[result release];
result = nil;
}
return [listPolylines autorelease];
}
else {
NSString *error = #"No result found. Please check start and end location again!";
return error;
}
return nil;
}
Step 3: Decode each polyline in the polyline list. This will give the path coordinates.
-(NSMutableArray *)decodePolyLine:(NSMutableString *)encoded {
[encoded replaceOccurrencesOfString:#"\\\\" withString:#"\\"
options:NSLiteralSearch
range:NSMakeRange(0, [encoded length])];
NSInteger len = [encoded length];
NSInteger index = 0;
NSMutableArray *listCoordinates = [[[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];
NSNumber *longitude = [[NSNumber alloc] initWithFloat:lng * 1e-5];
//CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
[listCoordinates addObject:[NSString stringWithFormat:#"%f,%f", [latitude floatValue], [longitude floatValue]]];
//[loc release];
[latitude release];
[longitude release];
}
return listCoordinates;
}
this newer tutorial/sample code using CoreLocation and MapKit helped me a bunch.