2016-02-18 108 views
0

我想要獲取一個點的座標,即從起始位置開始設定的距離,但最終結果是錯誤的。用起始位置和距離計算新的座標

首先,我計算的開始位置和期望的目的地之間的角度:

private func calculateAngleBetweenLocations(currentLocation: CLLocationCoordinate2D, targetLocation: CLLocationCoordinate2D) -> Double { 
    let fLat = self.degreesToRadians(currentLocation.latitude); 
    let fLng = self.degreesToRadians(currentLocation.longitude); 
    let tLat = self.degreesToRadians(targetLocation.latitude); 
    let tLng = self.degreesToRadians(targetLocation.longitude); 
    let deltaLng = tLng - fLng 

    let y = sin(deltaLng) * cos(tLat) 
    let x = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaLng) 

    let bearing = atan2(y, x) 

    return self.radiansToDegrees(bearing) 
} 

然後,我計算新的點,在給定距離:

private func coordinatesForMovement(endLocation: CLLocationCoordinate2D, distance: Double) -> CLLocationCoordinate2D { 
    let angle = self.calculateAngleBetweenLocations(self.currentLocation, targetLocation: endLocation) 
    let x = self.currentLocation.latitude + distance * cos(angle) 
    let y = self.currentLocation.longitude + distance * sin(angle) 

    return CLLocationCoordinate2D(latitude: x, longitude: y) 
} 

而且this是結果(腳是起始位置,藍色標記是目的地,紅色標記是新計算點的位置)。我試過以米,公里和其他浮點位置來傳遞距離,但從來沒有得到正確的結果。有任何想法嗎?

+0

'coordinatesForMovement'似乎是混合尺寸。 'currentCoordinate.latitude'是一個角度(度數?),'distance'是一個長度,'cos()'是無量綱的。所以該程序正在增加一個角度,這總是會出錯。角度增加角度,長度增加長度。 – emrys57

+0

好的,我該如何解決它? – smeshko

回答

0

好吧,經過一些挖掘,我發現this答案,這解決了我的問題。這是我在swift中的完整解決方案:

internal func moveToLocation(location: CLLocationCoordinate2D, distance: Double) { 
    let angle = self.calculateAngleBetweenLocations(self.currentLocation, targetLocation: location) 
    let newLocation = self.coordinates(self.currentLocation, atDistance: distance, atAngle: angle) 

    self.moveUser(newLocation: newLocation) 
} 

private func coordinates(startingCoordinates: CLLocationCoordinate2D, atDistance: Double, atAngle: Double) -> CLLocationCoordinate2D { 
    let distanceRadians = atDistance/6371 
    let bearingRadians = self.degreesToRadians(atAngle) 
    let fromLatRadians = self.degreesToRadians(startingCoordinates.latitude) 
    let fromLonRadians = self.degreesToRadians(startingCoordinates.longitude) 

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

    toLonRadians = fmod((toLonRadians + 3 * M_PI), (2 * M_PI)) - M_PI 

    let lat = self.radiansToDegrees(toLatRadians) 
    let lon = self.radiansToDegrees(toLonRadians) 

    return CLLocationCoordinate2D(latitude: lat, longitude: lon) 
} 

private func calculateAngleBetweenLocations(currentLocation: CLLocationCoordinate2D, targetLocation: CLLocationCoordinate2D) -> Double { 
    let fLat = self.degreesToRadians(currentLocation.latitude); 
    let fLng = self.degreesToRadians(currentLocation.longitude); 
    let tLat = self.degreesToRadians(targetLocation.latitude); 
    let tLng = self.degreesToRadians(targetLocation.longitude); 
    let deltaLng = tLng - fLng 

    let y = sin(deltaLng) * cos(tLat) 
    let x = cos(fLat) * sin(tLat) - sin(fLat) * cos(tLat) * cos(deltaLng) 

    let bearing = atan2(y, x) 

    return self.radiansToDegrees(bearing) 
} 

private func degreesToRadians(x: Double) -> Double { 
    return M_PI * x/180.0 
} 

private func radiansToDegrees(x: Double) -> Double { 
    return x * 180.0/M_PI 
}