在iOS中的MapKit中绘制路线

PRN*_*PRN 54 iphone mapkit ios

我想在地图上的两个位置之间绘制一条路线.像导游一样的东西.当游客点击另一个位置时,我希望能够绘制一条路线; 以及通知当前位置的距离.

我知道互联网上的网站告诉我们如何在地图上绘制折线.但是,大多数示例都有一个带有各种坐标的预加载.csv文件.

是否有其他方法可以从Google或任何其他提供商处获取坐标,因为该位置是动态选择的.

如果否,我如何获取中间坐标的信息?

iOS 6是否提供了解决此问题的直接方法?

vir*_*ral 61

以下viewDidLoad将(1)设置两个位置,(2)删除所有先前的注释,以及(3)调用用户定义的辅助函数(获取路径点并绘制路径).

-(void)viewDidLoad
{
    [super viewDidLoad];

    // Origin Location.
    CLLocationCoordinate2D loc1;
    loc1.latitude = 29.0167;
    loc1.longitude = 77.3833;
    Annotation *origin = [[Annotation alloc] initWithTitle:@"loc1" subTitle:@"Home1" andCoordinate:loc1];
    [objMapView addAnnotation:origin];

    // Destination Location.
    CLLocationCoordinate2D loc2;
    loc2.latitude = 19.076000;
    loc2.longitude = 72.877670;
    Annotation *destination = [[Annotation alloc] initWithTitle:@"loc2" subTitle:@"Home2" andCoordinate:loc2];
    [objMapView addAnnotation:destination];

    if(arrRoutePoints) // Remove all annotations
        [objMapView removeAnnotations:[objMapView annotations]];

    arrRoutePoints = [self getRoutePointFrom:origin to:destination];
    [self drawRoute];
    [self centerMap];
}
Run Code Online (Sandbox Code Playgroud)

以下是MKMapViewDelegate绘制叠加层的方法(iOS 4.0及更高版本).

/* MKMapViewDelegate Meth0d -- for viewForOverlay*/
- (MKOverlayView*)mapView:(MKMapView*)theMapView viewForOverlay:(id <MKOverlay>)overlay
{
    MKPolylineView *view = [[MKPolylineView alloc] initWithPolyline:objPolyline];
    view.fillColor = [UIColor blackColor];
    view.strokeColor = [UIColor blackColor];
    view.lineWidth = 4;
    return view;
}
Run Code Online (Sandbox Code Playgroud)

以下函数将获取位置并准备URL以获取所有路径点.当然,会调用stringWithURL.

/* This will get the route coordinates from the Google API. */
- (NSArray*)getRoutePointFrom:(Annotation *)origin to:(Annotation *)destination
{
    NSString* saddr = [NSString stringWithFormat:@"%f,%f", origin.coordinate.latitude, origin.coordinate.longitude];
    NSString* daddr = [NSString stringWithFormat:@"%f,%f", destination.coordinate.latitude, destination.coordinate.longitude];

    NSString* apiUrlStr = [NSString stringWithFormat:@"http://maps.google.com/maps?output=dragdir&saddr=%@&daddr=%@", saddr, daddr];
    NSURL* apiUrl = [NSURL URLWithString:apiUrlStr];

    NSError *error;
    NSString *apiResponse = [NSString stringWithContentsOfURL:apiUrl encoding:NSUTF8StringEncoding error:&error];
    NSString* encodedPoints = [apiResponse stringByMatching:@"points:\\\"([^\\\"]*)\\\"" capture:1L];

    return [self decodePolyLine:[encodedPoints mutableCopy]];
}
Run Code Online (Sandbox Code Playgroud)

以下代码是真正的魔术(我们从API获得的响应的解码器).我不会修改那段代码,除非我知道我在做什么:)

- (NSMutableArray *)decodePolyLine:(NSMutableString *)encodedString
{
    [encodedString replaceOccurrencesOfString:@"\\\\" withString:@"\\"
                                  options:NSLiteralSearch
                                    range:NSMakeRange(0, [encodedString length])];
    NSInteger len = [encodedString 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 = [encodedString 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 = [encodedString 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("\n[%f,", [latitude doubleValue]);
        printf("%f]", [longitude doubleValue]);
        CLLocation *loc = [[CLLocation alloc] initWithLatitude:[latitude floatValue] longitude:[longitude floatValue]];
        [array addObject:loc];
    }
    return array;
}
Run Code Online (Sandbox Code Playgroud)

此功能将绘制路线并添加叠加.

- (void)drawRoute
{
    int numPoints = [arrRoutePoints count];
    if (numPoints > 1)
    {
        CLLocationCoordinate2D* coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));
        for (int i = 0; i < numPoints; i++)
        {
            CLLocation* current = [arrRoutePoints objectAtIndex:i];
            coords[i] = current.coordinate;
        }

        self.objPolyline = [MKPolyline polylineWithCoordinates:coords count:numPoints];
        free(coords);

        [objMapView addOverlay:objPolyline];
        [objMapView setNeedsDisplay];
    }
}
Run Code Online (Sandbox Code Playgroud)

以下代码将居中对齐地图.

- (void)centerMap
{
    MKCoordinateRegion region;

    CLLocationDegrees maxLat = -90;
    CLLocationDegrees maxLon = -180;
    CLLocationDegrees minLat = 90;
    CLLocationDegrees minLon = 180;

    for(int idx = 0; idx < arrRoutePoints.count; idx++)
    {
        CLLocation* currentLocation = [arrRoutePoints 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;

    [objMapView setRegion:region animated:YES];
}
Run Code Online (Sandbox Code Playgroud)

我希望这会对某人有所帮助.


And*_*iih 24

这是一个棘手的问题.使用MapKit无法做到这一点:当您知道坐标时,绘制线条很容易,但MapKit不会让您访问道路或其他路线信息.我要说你需要调用外部API来获取数据.

我一直在玩cloudmade.com API.矢量流服务器应该返回您需要的内容,然后您可以在地图上绘制它.但是,Google地图与cloudmade使用的OSM地图之间的差异可能会让您想要一直使用cloudmade地图:它们与MapKit相同.

PS:其他地图提供商 - Google,Bing等也可能提供相应的数据Feed.我最近一直在关注OSM/Cloudmade.

PPS:这些都不是琐碎的新手!祝你好运!


Dan*_*tay 12

Andiih说得对.MapKit不允许你这样做.不幸的是,谷歌不会让你做你想做的事情.

当Apple宣布推出MapKit时,他们还明确表示任何导航应用程序都是BYOM:自带地图,因此任何导航应用程序都使用自己的一套映射工具.

Google的服务条款限制您甚至在地图上显示路线:

http://code.google.com/intl/de/apis/maps/iphone/terms.html

许可限制:

10.9将服务或内容与任何产品,系统或应用程序一起使用或与之相关:

(a)实时导航或路线引导,包括但不限于与用户的传感器使能设备的位置同步的逐向路线引导;

(b)自动或自动控制车辆行为的任何系统或功能; 要么

(c)调度,车队管理,业务资产跟踪或类似的企业应用程序(只要跟踪应用程序可供公众使用,Google Maps API可用于跟踪资产(例如汽车,公共汽车或其他车辆)例如,您可以提供免费的公共Maps API实施,其中显示实时公共交通或其他交通状态信息.

可悲的是,这包括你想做的事情.希望有一天MapKit会扩展到允许这样的功能......虽然不太可能.

祝好运.


lev*_*han 5

您可能需要查看https://github.com/leviathan/nvpolyline此解决方案特别针对v.4.0之前的iPhone OS版本

虽然它也可以在v.4.0中使用希望这会有所帮助.