用起始位置和距离计算新坐标

Posted

技术标签:

【中文标题】用起始位置和距离计算新坐标【英文标题】:Calculate new coordinates with starting position and distance 【发布时间】:2016-02-18 15:41:23 【问题描述】:

我正在尝试获取一个点的坐标,即距起始位置一定距离,但最终结果是错误的。

首先,我计算起始位置和所需目的地之间的角度:

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 是结果(脚是起始位置,蓝色标记是目的地,红色标记是新计算点的位置)。我尝试过以米和公里为单位的距离以及所有其他浮点位置,但从未得到正确的结果。有任何想法吗?

【问题讨论】:

coordinatesForMovement 似乎是混合维度。 currentCoordinate.latitude 是角度(以度为单位?),distance 是长度,cos() 是无量纲的。所以程序在长度上加上一个角度,这总是错误的。角度增加角度,长度增加长度。 好的,那我该如何解决呢? 【参考方案1】:

好的,经过一番挖掘,我找到了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

【讨论】:

以上是关于用起始位置和距离计算新坐标的主要内容,如果未能解决你的问题,请参考以下文章

如何将距离(以公里为单位)添加到以度和分钟为单位的位置坐标中,以获得 Java 中的新位置坐标?

使用 iphone 核心位置数据计算距离

从坐标数组到表格中的位置之间的距离

在数组中存储坐标(地理位置)以计算距离

如何计算一组 x、y 坐标和位置变量之间的距离?

如何使用 Haversine 公式计算行驶距离(不是位移)?