2010-05-14 50 views
53

我想繪製地圖上兩個位置之間的路線。像導遊一樣。當遊客點擊另一個地點時,我希望能夠繪製路線;並告知距離當前位置的距離。在iPhone SDK中的MapKit中繪製路線

我知道互聯網上的網站,它告訴如何在地圖上繪製多段線。但是,大多數示例都有一個帶有各種座標的預加載的.csv文件。

是否有另一種方式從Google或任何其他提供商處獲取座標,因爲該位置是動態選擇的。

如果否,我如何獲得中間座標信息?

iOS 6是否提供瞭解決此問題的任何直接方法?

+0

試試這個,唯一希望這將有助於ühttps://github.com/Surya121/SBMapWithRoute – iCoder4777 2011-12-26 07:26:38

+0

HTTP://iphonegeeksworld.wordpress。COM/2010/09/08 /繪圖路線 - 到 - 使用 - 非官方谷歌,地圖,方向-API的MKMapView-/ – viral 2012-08-12 08:52:22

+0

如果您正在使用的代碼此更新neccessary 的http://計算器.COM /問題/ 8166179 /正則表達式和-的iOS5-stringbymatching-nsregularexpression – 2013-06-26 08:49:57

回答

24

這是一個棘手的問題。 MapKit沒有辦法做到這一點:在知道座標時很容易繪製線條,但MapKit不會讓您訪問道路或其他路線信息。我想說你需要調用一個外部API來獲取你的數據。

我一直在玩cloudmade.com API。矢量流服務器應該返回你需要的東西,然後你可以在你的地圖上繪製它。但是,Google地圖與Cloudmade使用的地圖之間的差異可能會讓您想要一路使用cloudmade地圖:它們與MapKit具有相同的效果。

P.S .:其他地圖提供商 - Google,Bing等也可能提供等效的數據提要。我剛剛在OSM/Cloudmade上看過。

P.P.S .:這些都不是新鮮的東西!祝你好運!

12

Andiih說得對。 MapKit不會讓你這樣做。不幸的是,Google不會讓你做你想做的事情。

當蘋果宣佈MapKit和所有的,他們還明確指出,任何導航應用將是BYOM:帶上你自己的地圖,所以任何導航的應用程序使用他們自己的一套製圖工具。

谷歌的服務條款的限制,你甚至從他們的地圖,上面顯示的路線:

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

許可限制:

10。9使用服務或內容的任何產品,系統,或應用 用於或與連接:

的(a)實時導航或路徑 指導,包括但不限於: 反過來由轉動路線引導即 同步到 用戶的啓用傳感器的設備的位置; (b) 自動或自主控制車輛行爲的任何系統或功能;或

(c)調度,車隊管理, 公司資產跟蹤或類似 企業應用程序(谷歌 地圖API可以 (如汽車,公交車或其他 車輛)只要用於跟蹤資產跟蹤 應用程序提供給公衆 不收費。例如, 你也可以提供一個免費的公共地圖API 實現,顯示實時 公共交通或其他交通 狀態信息。

不幸的是,這包括你想要做的事情。希望有一天MapKit將被擴展以允許這些功能......儘管不太可能。

好運。

+1

PRN不說他試圖做任何事情或轉彎轉彎:只是他想覆蓋方向。您可以使用Google Maps JavaScript API(我認爲)這樣做,但不能使用MapKit。你顯然比我更熟悉Google API--如果它沒有輪到我們,有什麼辦法可以獲得道路向量? [看到這個問題讓我感興趣吧!] – Andiih 2010-05-15 06:51:30

+1

它不是輪流轉,而是它的路線指引,不是嗎? – Daniel 2012-04-13 18:19:39

5

你可能想看看https://github.com/leviathan/nvpolyline讓該溶液在之前iPhone OS版本,特別是有針對性地V.4.0

雖然它也可以在4.0版希望這有助於使用。

+0

嗨柯林斯,都對不起延遲迴復的 第一......但與上述的例子中,座標是在應用程序中硬編碼的,我想是拿到座標作爲被選擇的位置和時......不是預先安裝座標的地方。例如,遊客可以選擇城市中的任意位置,並且應該根據他/她當前的座標提供路線。此選定的位置座標可能未預先加載。 – PRN 2010-07-29 06:19:44

+0

PRN請轉到polyline GitHub項目並打開問題報告(http://github.com/mobilemelting/nvpolyline/issues)。我會盡力爲您的問題整合一個解決方案。 – leviathan 2010-07-29 07:23:55

+0

正確的URL是https://github.com/leviathan/nvpolyline – leviathan 2012-01-10 22:54:17

3

MapQuest有一個SDK,它是MapKit的直接替代品。它目前處於測試階段,但正在積極開發中。

它允許覆蓋,路由和地理編碼。

MapQuest iOS Maps API

3

只是爲了澄清,它看起來像有正在討論兩件事情。一種是獲取路線頂點的方法,另一種是使用這些頂點在地圖上繪製覆蓋圖。我知道MapQuest的API,所以我有一些鏈接的谷歌和Bing有我認爲的等值。

1)路線
如果你正在尋找一個路線的新座標繪製的路線重疊,您可以使用Web服務調用路由Web服務的獲取頂點 - 我假設你'在這裏使用JavaScript來顯示地圖。如果您使用的是本地代碼,您仍然可以訪問Web服務,或者您可以使用本地調用(即MapQuest iPhone SDK具有本地路由調用)。

大多數路線服務應返回路線的「形狀點」,以便繪製。

下面是使用MapQuest- 路線網絡服務來獲取shapepoints一些例子(見形狀返回對象) - http://www.mapquestapi.com/directions/

2)繪製一個覆蓋
一旦你有你的頂點,你需要吸引他們。我認爲大多數JavaScript地圖API都會有某種重疊類。這裏的MapQuest的一個: http://developer.mapquest.com/web/documentation/sdk/javascript/v7.0/overlays#line

3)與一個呼叫做這
的MapQuest也有一些方便的功能,使呼叫路由和劃清界線你 - 我不能發佈兩個以上的鏈路!因此,轉到上面的鏈接並在左側的導航欄中查找「路由」。

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]; 
} 

以下是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; 
} 

以下函數將獲取位置和準備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]]; 
} 

下面的代碼是真正的魔術(我們從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; 
} 

此功能將以此爲途徑,將增加的覆蓋。

- (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]; 
    } 
} 

以下代碼將居中對齊地圖。

- (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]; 
} 

我希望這會幫助別人。

+0

希望你的繪圖路線方法正常工作。我使用了幾乎相同的函數,就像你的decodePolyLine函數。我CLLocations的數組,但我之後卡住,因爲該方法「polylineWithCordinates」採取CLLocationCordinate2D的arrray,我不知道怎麼我的數組轉換爲CLLocationCordinate2D陣列。我明天將在我的工作場所嘗試你的抽籤方法。順便說一句,你可以解釋這一行'CLLocationCoordinate2D * coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));' – Nil 2012-12-16 09:30:11

+1

@ rd4code CLLocationCoordinate2D * coords = malloc(numPoints * sizeof(CLLocationCoordinate2D));' - 它在內存中分配的塊大小與我們的'arrRoutePoints'的大小相等,每個索引對象都是'CLLocationCoordinate2D'。希望你明白。 – viral 2012-12-17 04:47:12

+0

你的方法今天工作:)。謝謝你的解釋。 。另外我想問問是否有另一種方式創建CLLocationCoordinate2D數組?我的意思是如果malloc是必要的? – Nil 2012-12-17 05:09:09

3

獲取和在地圖上繪製的路線與iOS 7 API超級簡單:

MKDirectionsRequest *directionsRequest = [[MKDirectionsRequest alloc] init]; 

// Set the origin of the route to be current user location 
[directionsRequest setSource:[MKMapItem mapItemForCurrentLocation]]; 

// Set the destination point of the route 
CLLocationCoordinate2D destinationCoordinate = CLLocationCoordinate2DMake(34.0872, 76.235); 
MKPlacemark *destinationPlacemark = [[MKPlacemark alloc] initWithCoordinate:destinationCoordinate addressDictionary:nil]; 
[directionsRequest setDestination:[[MKMapItem alloc] initWithPlacemark:destinationPlacemark]]; 

MKDirections *directions = [[MKDirections alloc] initWithRequest:directionsRequest]; 

// Requesting route information from Apple Map services 
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) { 
    if (error) { 
     NSLog(@"Cannot calculate directions: %@",[error localizedDescription]); 
    } else { 
     // Displaying the route on the map 
     MKRoute *route = [response.routes firstObject]; 
     [mapView addOverlay:route.polyline]; 
    } 
}]; 
+1

您如何爲MapKit中沒有方向支持的國家做同樣的事情? – madLokesh 2015-03-09 08:35:53

2

要更新這個問題,就沒有必要以來iOS7外部APK。

這裏一個非常簡單而有效的解決方案:

http://technet.weblineindia.com/mobile/draw-route-between-2-points-on-map-with-ios7-mapkit-api/2/

我知道這個問題是關於iOS 6的,但我相信這個解決方案將是有益的很多人。

在這種解決方案缺少的是執行以下的委託方法來顯示起止銷

-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation