2011-07-09 61 views
29

我必須在文檔丟失的財產以後出來,我想這應該是很容易...計算新的座標x米和y度從一個客場協調

如果我有一個座標,並希望得到一個新的座標在一些方向上離開X米遠。我該怎麼做呢?

我在尋找類似

-(CLLocationCoordinate2D) translateCoordinate:(CLLocationCoordinate2D)coordinate translateMeters:(int)meters translateDegrees:(double)degrees;

謝謝!

回答

29

不幸的是,API中沒有提供這樣的功能,所以你必須自己編寫。

This site給出了一些涉及緯度/經度和JavaScript代碼示例的計算。具體而言,標題爲「給定距離和起始點的方位」的部分顯示瞭如何計算您要求的內容。

的JavaScript代碼是在該頁面的底部,這裏是將其轉換成Objective-C的一個可能的方式:

- (double)radiansFromDegrees:(double)degrees 
{ 
    return degrees * (M_PI/180.0);  
} 

- (double)degreesFromRadians:(double)radians 
{ 
    return radians * (180.0/M_PI); 
} 

- (CLLocationCoordinate2D)coordinateFromCoord: 
     (CLLocationCoordinate2D)fromCoord 
     atDistanceKm:(double)distanceKm 
     atBearingDegrees:(double)bearingDegrees 
{ 
    double distanceRadians = distanceKm/6371.0; 
     //6,371 = Earth's radius in km 
    double bearingRadians = [self radiansFromDegrees:bearingDegrees]; 
    double fromLatRadians = [self radiansFromDegrees:fromCoord.latitude]; 
    double fromLonRadians = [self radiansFromDegrees:fromCoord.longitude]; 

    double toLatRadians = asin(sin(fromLatRadians) * cos(distanceRadians) 
     + cos(fromLatRadians) * sin(distanceRadians) * cos(bearingRadians)); 

    double toLonRadians = fromLonRadians + atan2(sin(bearingRadians) 
     * sin(distanceRadians) * cos(fromLatRadians), cos(distanceRadians) 
     - sin(fromLatRadians) * sin(toLatRadians)); 

    // adjust toLonRadians to be in the range -180 to +180... 
    toLonRadians = fmod((toLonRadians + 3*M_PI), (2*M_PI)) - M_PI; 

    CLLocationCoordinate2D result; 
    result.latitude = [self degreesFromRadians:toLatRadians]; 
    result.longitude = [self degreesFromRadians:toLonRadians]; 
    return result; 
} 

在JS代碼,它包含this link其中顯示了距離的更精確的計算大於地球四分之一的圓周。

另請注意,上面的代碼接受以km爲單位的距離,所以務必在通過之前將儀表除以1000.0。

+0

謝謝你的回答!其實,我找到了一個辦法。看到我自己的答案。 – Nicsoft

+0

好的答案,我喜歡這個,因爲它直接處理座標,並且更全面地回答問題,因爲它考慮了方向。 – johnrechd

12

我發現了一種做法,不得不挖掘以找到正確的結構和功能。我最終沒有使用度數,而是用米和拉來代替。

我是這樣做的:

-(CLLocationCoordinate2D)translateCoord:(CLLocationCoordinate2D)coord MetersLat:(double)metersLat MetersLong:(double)metersLong{ 

    CLLocationCoordinate2D tempCoord; 

    MKCoordinateRegion tempRegion = MKCoordinateRegionMakeWithDistance(coord, metersLat, metersLong); 
    MKCoordinateSpan tempSpan = tempRegion.span; 

    tempCoord.latitude = coord.latitude + tempSpan.latitudeDelta; 
    tempCoord.longitude = coord.longitude + tempSpan.longitudeDelta; 

    return tempCoord; 

} 

當然,如果我真的需要在未來的使用度,這是很容易的(我覺得...)做一些改變,上述獲得它像我實際要求的那樣工作。

+0

簡單而有效的符合我的需求。謝謝! –

+1

那麼你最終如何處理學位呢? –

5

使用MKCoordinateRegion有一些問題 - 返回的區域可以進行調整,以適應兩個增量可能不會精確映射到該緯度的投影,如果您希望某個軸的零增量不成功,等等。

此功能使用MKMapPoint執行座標轉換,它允許您在地圖投影的座標空間中移動點,然後從中提取座標。

CLLocationCoordinate2D MKCoordinateOffsetFromCoordinate(CLLocationCoordinate2D coordinate, CLLocationDistance offsetLatMeters, CLLocationDistance offsetLongMeters) { 
    MKMapPoint offsetPoint = MKMapPointForCoordinate(coordinate); 

    CLLocationDistance metersPerPoint = MKMetersPerMapPointAtLatitude(coordinate.latitude); 
    double latPoints = offsetLatMeters/metersPerPoint; 
    offsetPoint.y += latPoints; 
    double longPoints = offsetLongMeters/metersPerPoint; 
    offsetPoint.x += longPoints; 

    CLLocationCoordinate2D offsetCoordinate = MKCoordinateForMapPoint(offsetPoint); 
    return offsetCoordinate; 
} 
+0

這個答案對我很好,並允許我轉換MapItem.placemark。區域(這是一個CLCircularRegion;它有一個以米爲單位的半徑)放入邊界框區域 –

4

Nicsoft的答案很棒,正是我所需要的。我創建了一個斯威夫特3-Y版本,這是一個小更簡潔,可以在CLLocationCoordinate2D實例直接調用:

public extension CLLocationCoordinate2D { 

    public func transform(using latitudinalMeters: CLLocationDistance, longitudinalMeters: CLLocationDistance) -> CLLocationCoordinate2D { 
    let region = MKCoordinateRegionMakeWithDistance(self, latitudinalMeters, longitudinalMeters) 
    return CLLocationCoordinate2D(latitude: latitude + region.span.latitudeDelta, longitude: longitude + region.span.longitudeDelta) 
    } 

} 
+4

可能會更好地命名爲「translate」,因爲它在技術上不是轉換,而是翻譯。 –

相關問題