问题
I am using GoogleMap API for showing draw direction between two points on GoogleMap.
i want to give support on iOS 6.1 so i use GoogleMap i know about iOS7 recover this.
using below code for parsing and get Steps for coordinates to draw polyline on Map:
NSString *str=@"http://maps.googleapis.com/maps/api/directions/json?origin=bharuch,gujarat&destination=vadodara,gujarat&sensor=false";
NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray* latestRoutes = [json objectForKey:@"routes"];
NSMutableDictionary *legs=[[[latestRoutes objectAtIndex:0] objectForKey:@"legs"] objectAtIndex:0];
NSArray *steps=[legs objectForKey:@"steps"];
NSString *startLocation,*endLocation,*totalDistance,*totalDuration;
CLLocationCoordinate2D startLoc,endLoc;
startLocation = [legs objectForKey:@"start_address"];
endLocation = [legs objectForKey:@"end_address"];
totalDistance = [[legs objectForKey:@"distance"] objectForKey:@"text"];
totalDuration = [[legs objectForKey:@"duration"] objectForKey:@"text"];
startLoc=CLLocationCoordinate2DMake([[[legs objectForKey:@"start_location"] objectForKey:@"lat"] doubleValue], [[[legs objectForKey:@"start_location"] objectForKey:@"lng"] doubleValue]);
endLoc=CLLocationCoordinate2DMake([[[legs objectForKey:@"end_location"] objectForKey:@"lat"] doubleValue], [[[legs objectForKey:@"end_location"] objectForKey:@"lng"] doubleValue]);
NSMutableDictionary *tempDict;
if ([steps count]!=0) {
GMSMutablePath *path = [GMSMutablePath path];
for(int idx = 0; idx < [steps count]+2; idx++){
CLLocationCoordinate2D workingCoordinate;
if (idx==0) {
workingCoordinate=startLoc;
[path addCoordinate:workingCoordinate];
}
else if (idx==[steps count]+1){
workingCoordinate=endLoc;
[path addCoordinate:workingCoordinate];
}
else{
workingCoordinate=CLLocationCoordinate2DMake([[[[steps objectAtIndex:idx-1] objectForKey:@"start_location"] objectForKey:@"lat"] floatValue], [[[[steps objectAtIndex:idx-1] objectForKey:@"start_location"] objectForKey:@"lng"] floatValue]);
[path addCoordinate:workingCoordinate];
}
tempDict = nil;
}
// create the polyline based on the array of points.
GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path];
rectangle.strokeWidth=5.0;
rectangle.map = mapView_;
}
its gives only 24 steps means only 24 Coordinates for create point and draw Line on Map which is shown as below image:
you can see that line is not on proper road so what can i do to solve this? i also want to show direction on map too.
回答1:
Below answer is for smooth path between two location with help of @A Báo:
-(void)viewDidLoad { // Create a GMSCameraPosition that tells the map to display the GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:21.718472 longitude:73.030422 zoom:6]; mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera]; mapView_.delegate=self; mapView_.myLocationEnabled = YES; mapView_.settings.myLocationButton=YES; mapView_.settings.indoorPicker=NO; mapView_.settings.compassButton=YES; self.view = mapView_; NSString *str=@"http://maps.googleapis.com/maps/api/directions/json?origin=Bharuch,gujarat&destination=vadodara,gujarat&sensor=false"; NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSError* error; NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; NSArray* latestRoutes = [json objectForKey:@"routes"]; NSString *points=[[[latestRoutes objectAtIndex:0] objectForKey:@"overview_polyline"] objectForKey:@"points"]; @try { // TODO: better parsing. Regular expression? NSArray *temp= [self decodePolyLine:[points mutableCopy]]; GMSMutablePath *path = [GMSMutablePath path]; for(int idx = 0; idx < [temp count]; idx++) { CLLocation *location=[temp objectAtIndex:idx]; [path addCoordinate:location.coordinate]; } // create the polyline based on the array of points. GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path]; rectangle.strokeWidth=5.0; rectangle.map = mapView_; } @catch (NSException * e) { // TODO: show error } } -(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; }
Screenshot of this code you can compare it with previous screenshot which i used in asking Question:
回答2:
I did add GMSMarker to each point get on steps array and I sure that use steps array start_location and end_location not enough to show direction in your map. here is code I did edit from your code
NSString *str=@"http://maps.googleapis.com/maps/api/directions/json?origin=bharuch,gujarat&destination=vadodara,gujarat&sensor=false";
NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSError *error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSArray* latestRoutes = [json objectForKey:@"routes"];
NSMutableDictionary *legs=[[[latestRoutes objectAtIndex:0] objectForKey:@"legs"] objectAtIndex:0];
NSArray *steps=[legs objectForKey:@"steps"];
NSString *startLocation,*endLocation,*totalDistance,*totalDuration;
CLLocationCoordinate2D startLoc,endLoc;
startLocation = [legs objectForKey:@"start_address"];
endLocation = [legs objectForKey:@"end_address"];
totalDistance = [[legs objectForKey:@"distance"] objectForKey:@"text"];
totalDuration = [[legs objectForKey:@"duration"] objectForKey:@"text"];
startLoc=CLLocationCoordinate2DMake([[[legs objectForKey:@"start_location"] objectForKey:@"lat"] doubleValue], [[[legs objectForKey:@"start_location"] objectForKey:@"lng"] doubleValue]);
NSMutableDictionary *stopLegs=[[[latestRoutes objectAtIndex:0] objectForKey:@"legs"] objectAtIndex:0];
endLoc=CLLocationCoordinate2DMake([[[stopLegs objectForKey:@"end_location"] objectForKey:@"lat"] doubleValue], [[[stopLegs objectForKey:@"end_location"] objectForKey:@"lng"] doubleValue]);
NSMutableDictionary *tempDict;
if ([steps count]!=0) {
// add marker
NSDictionary *step;
for (int i= 0; i < steps.count; i++) {
step = [steps objectAtIndex:i];
NSDictionary *location = [step objectForKey:@"start_location"];
double lat = [[location objectForKey:@"lat"] doubleValue];
double lng = [[location objectForKey:@"lng"] doubleValue];
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(lat, lng);
marker.snippet = [NSString stringWithFormat:@"point (%d)", i+1];
marker.map = mapView_;
}
NSDictionary *location = [step objectForKey:@"end_location"];
double lat = [[location objectForKey:@"lat"] doubleValue];
double lng = [[location objectForKey:@"lng"] doubleValue];
GMSMarker *marker = [[GMSMarker alloc] init];
marker.position = CLLocationCoordinate2DMake(lat, lng);
marker.snippet = [NSString stringWithFormat:@"point (%d)", steps.count];
marker.map = mapView_;
// continue draw map
GMSMutablePath *path = [GMSMutablePath path];
for(int idx = 0; idx < [steps count]+2; idx++){
CLLocationCoordinate2D workingCoordinate;
if (idx==0) {
workingCoordinate=startLoc;
[path addCoordinate:workingCoordinate];
}
else if (idx==[steps count]+1){
workingCoordinate=endLoc;
[path addCoordinate:workingCoordinate];
}
else{
workingCoordinate=CLLocationCoordinate2DMake([[[[steps objectAtIndex:idx-1] objectForKey:@"start_location"] objectForKey:@"lat"] floatValue], [[[[steps objectAtIndex:idx-1] objectForKey:@"start_location"] objectForKey:@"lng"] floatValue]);
[path addCoordinate:workingCoordinate];
}
tempDict = nil;
}
// create the polyline based on the array of points.
GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path];
rectangle.strokeWidth=5.0;
rectangle.map = mapView_;
}
you can see betwen point 12 and point 13 have a big distance (60.2 km). but it just one path. I did find out that if you want to show approximate (smoothed) path of the resulting directions. you need use "overview_polyline" field. overview_polyline: contains an object holding an array of encoded points that represent an approximate (smoothed) path of the resulting directions. this link google map develop helpful for you. So work for you is find method to decode data from "overview_polyline" to get correct path between two point. I definitely it's true way to resolve your problem because I did check tool to decode "overview_polyline" at Encoded Polyline Algorithm Format This Image what I got from decode:
To decode polyne string you can find at this block http://objc.id.au/post/9245961184/mapkit-encoded-polylines
- Continue, with code from @jayraj m.g. Below answer is for smooth path between two location
-(void)viewDidLoad { // Create a GMSCameraPosition that tells the map to display the GMSCameraPosition *camera = [GMSCameraPosition cameraWithLatitude:21.718472 longitude:73.030422 zoom:6]; mapView_ = [GMSMapView mapWithFrame:CGRectZero camera:camera]; mapView_.delegate=self; mapView_.myLocationEnabled = YES; mapView_.settings.myLocationButton=YES; mapView_.settings.indoorPicker=NO; mapView_.settings.compassButton=YES; self.view = mapView_; NSString *str=@"http://maps.googleapis.com/maps/api/directions/json?origin=Bharuch,gujarat&destination=vadodara,gujarat&sensor=false"; NSURL *url=[[NSURL alloc]initWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; NSError* error; NSDictionary* json = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; NSArray* latestRoutes = [json objectForKey:@"routes"]; NSString *points=[[[latestRoutes objectAtIndex:0] objectForKey:@"overview_polyline"] objectForKey:@"points"]; @try { // TODO: better parsing. Regular expression? NSArray *temp= [self decodePolyLine:[points mutableCopy]]; GMSMutablePath *path = [GMSMutablePath path]; for(int idx = 0; idx < [temp count]; idx++) { CLLocation *location=[temp objectAtIndex:idx]; [path addCoordinate:location.coordinate]; } // create the polyline based on the array of points. GMSPolyline *rectangle = [GMSPolyline polylineWithPath:path]; rectangle.strokeWidth=5.0; rectangle.map = mapView_; } @catch (NSException * e) { // TODO: show error } } -(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; }
Screenshot of this code you can compare it with previous screenshot which i used in asking Question:
Thanks @jayraj m.g.
来源:https://stackoverflow.com/questions/22091271/googlemap-api-gives-wrong-coordinates-for-direction-between-two-points