GoogleMap API 为两点之间的方向提供了错误的坐标
Posted
技术标签:
【中文标题】GoogleMap API 为两点之间的方向提供了错误的坐标【英文标题】:GoogleMap API Gives Wrong Coordinates for Direction between two Points 【发布时间】:2014-04-01 05:24:50 【问题描述】:我正在使用 GoogleMap API 来显示 GoogleMap 上两点之间的绘制方向。
我想在 ios 6.1 上提供支持,所以我使用 GoogleMap 我知道 iOS7 恢复这个。
使用以下代码解析并获取坐标在地图上绘制折线的步骤:
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_;
它只给出了 24 个步骤意味着只有 24 个坐标用于在地图上创建点和绘制线,如下图所示:
您可以看到该线路不在正确的道路上,那么我该怎么做才能解决这个问题? 我也想在地图上显示方向。
【问题讨论】:
【参考方案1】:下面的答案是在@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;
此代码的屏幕截图,您可以将其与我在提问时使用的先前屏幕截图进行比较:
【讨论】:
在某些情况下,应用程序在 characterAtIndex 的 decodePolyLine 方法中崩溃 *** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“-[__NSCFString characterAtIndex:]: Range or index out of bounds”如果在decodePolyLine 方法的 while 循环我将 while (index 我在我的应用中添加了这段代码,但地图没有出现在我的应用中【参考方案2】:我确实将 GMSMarker 添加到步骤数组上的每个点,并且我确定使用步骤数组 start_location 和 end_location 不足以在地图中显示方向。这是我从您的代码中编辑的代码
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_;
您可以看到点 12 和点 13 之间的距离很远(60.2 公里)。但它只是一条路。我确实发现如果你想显示结果方向的近似(平滑)路径。您需要使用“overview_polyline”字段。 overview_polyline:包含一个对象,该对象包含一个编码点数组,这些编码点表示结果方向的近似(平滑)路径。这个link google map develop 对你有帮助。因此,为您工作的是找到从“overview_polyline”解码数据以获得两点之间正确路径的方法。我绝对是解决您的问题的真正方法,因为我确实在Encoded Polyline Algorithm Format 上检查了解码“overview_polyline”的工具 我从解码中得到的这张图片:
要解码 polyne 字符串,您可以在此块找到 http://objc.id.au/post/9245961184/mapkit-encoded-polylines
继续,使用来自@jayraj m.g. 的代码。下面的答案是两个位置之间的平滑路径-(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;
此代码的屏幕截图,您可以将其与我在提问时使用的先前屏幕截图进行比较:
感谢@jayraj m.g.
【讨论】:
检查我编辑的有问题的代码部分,了解我用来画线的内容以及 google api 给我的内容 @jayrajm.g.我对你的问题很感兴趣,我确实找到了解决它。我希望你会对我所做的这个答案感到满意 @A Báo :多么巧合,我尝试了相同的“overview_polyline”来获得所有正确的路径,它提供了平滑的路径。感谢您对我的问题感兴趣,如果您使用“Overview_Polyline”更新您的答案,我会接受您的回答,因为现在这个答案没有显示平滑线.. @jayrajm.g.我确实编辑了答案,对于任何关心这个问题的人来说都是非常清楚的。感谢您的代码:) @jayrajm.g.我们可以根据用户当前位置设置相机位置吗以上是关于GoogleMap API 为两点之间的方向提供了错误的坐标的主要内容,如果未能解决你的问题,请参考以下文章