Reputation: 1897
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?
Upvotes: 9
Views: 26896
Reputation: 81
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];
}
Upvotes: 7
Reputation: 5183
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"
Upvotes: 13
Reputation:
You can refer this code, it does exactly what you want.
EDIT: and this also
Upvotes: 2
Reputation: 3284
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
Upvotes: 0
Reputation: 15213
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...
Upvotes: 1