ios 在 iPhone 中的 MapKit 上寻找两点之间的路径/路线
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12002179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Finding Path/Route Between two points on MapKit in iPhone
提问by Sasi M
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.
我试图在 Mapkit 上找到两个位置之间的路径。我只有两个位置。现在我必须找到这些点之间的确切路径并使用 MapKit 在这些点之间画一条线。我经历了几个他们使用 .csv 文件的例子。在那个 .csv 文件中,他们根据这些值存储了完整路径和绘图线的纬度和经度值。
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?
但在这里我试图在不知道路径的情况下画一条线。那么有没有什么办法可以动态找到路径并画一条线呢?
回答by alloc_iNit
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
地图方向.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
地图方向.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"
起点的示例地图路线- “41.967659,-87.627869”和目的地点 - “41.574361,-91.083069”
回答by Dhaval
Here The way in which I am able to draw direction between two points(Location).
这是我能够在两点(位置)之间绘制方向的方式。
First of all download GoogleMap sdk from thislink and integrate into your application.
首先从所有下载GoogleMap的SDK的这个链接,并集成到应用程序。
Now API key required and you can create as par given guidelines on thislink.
现在需要 API 密钥,您可以在此链接上创建标准给定的指南。
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];
}
回答by Ankur
回答by graver
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...
我不认为你可以在本地做到这一点。实现用于查找两个 gps 点之间路径的算法需要大量输入数据(来自地图的数据),而您没有这些。只有地图提供者才能负担得起实现这种算法并公开使用它的 API。我认为Google
有路由API
,但我没有玩过它......
回答by Nicholas Albion
https://developers.google.com/maps/documentation/directions/
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
请注意,TOS 规定您必须在 Google 地图上显示结果,因此您必须在下一个 iOS 版本中禁用该功能