找到朝向坐标的航向

Finding a heading towards a coordinate

我有我的位置(坐标)和航向(罗盘),我正在尝试计算朝向给定其他坐标的航向,以便我可以在屏幕上显示指向该位置的箭头。我正在建造的基本上是一个不指向北方的美化罗盘,而是指向一个特定的坐标,因此它需要考虑到该坐标的方位和用户的罗盘航向。

我原以为 CoreLocation 会包含必要的构建块,但除了获取两个坐标之间的距离外,似乎什么也没有。

不幸的是,我尝试手动计算这个结果并不是很成功,而且很难猜出我哪里出错了。从那以后,我尝试调整我发现的内容 here,并且我在那里的示例数据得到了相同的结果,但是一旦我使用自己的坐标,它就完全出错了。

extension Double {
    var radians: Double {
        self * .pi / 180
    }
}


let A = CLLocationCoordinate2D(latitude: 51.0295437, longitude: 13.7277793)
let B = CLLocationCoordinate2D(latitude: 51.026819, longitude: 13.726348)

let ΔL = abs(A.longitude) - abs(B.longitude)
let X = cos(B.latitude.radians) * sin(ΔL.radians)
let Y = cos(A.latitude.radians) * sin(B.latitude.radians) - sin(A.latitude.radians) * cos(B.latitude.radians) * cos(ΔL.radians)
let bearing = atan2(X, Y)
let heading = bearing - userHeading

一旦我将设备的航向合并到此(末尾的减法)中,就好像我的值以某种方式沿 W-E 轴翻转(指向左而不是右,反方向),但是 N-S -轴似乎是正确的。轴承的计算必须以某种方式关闭。 我对地理坐标系的了解真的不多。

我们这样试试吧。首先我需要建立一些转换:

extension Double {
    var toRadians : Double {
        var m = Measurement(value: self, unit: UnitAngle.degrees)
        m.convert(to: .radians)
        return m.value
    }
    var toDegrees : Double {
        var m = Measurement(value: self, unit: UnitAngle.radians)
        m.convert(to: .degrees)
        return m.value
    }
}

现在我来做一个公式; a是我所在的位置,b是我要的远方的方位:

let a = // some CLLocationCoordinate2D
let b = // some CLLocationCoordinate2D

let deltaL = b.longitude.toRadians - a.longitude.toRadians
let thetaB = b.latitude.toRadians
let thetaA = a.latitude.toRadians
let x = cos(thetaB) * sin(deltaL)
let y = cos(thetaA) * sin(thetaB) - sin(thetaA) * cos(thetaB) * cos(deltaL)
let bearing = atan2(x,y)
let bearingInDegrees = bearing.toDegrees
print(bearingInDegrees) // sanity check

现在我将测试一些实际的轴承。我将给出 ab,然后是打印的内容 (bearingInDegrees)。我将从我们从中获得公式的页面开始:

let a = CLLocationCoordinate2D(latitude: 39.099912, longitude: -94.581213)
let b = CLLocationCoordinate2D(latitude:  38.627089, longitude: -90.200203)
// 96.51262423499941, yep, that's the answer given on example page

好的,成功了。现在我将尝试自己和我在各个方向的一些观点:

let a = CLLocationCoordinate2D(latitude: 34.439931, longitude: -119.263984)
let b = CLLocationCoordinate2D(latitude: 34.489290, longitude: -119.221670)
// 35 degrees, about right

let a = CLLocationCoordinate2D(latitude: 34.439931, longitude: -119.263984)
let b = CLLocationCoordinate2D(latitude: 34.484479, longitude: -119.308273)
// -40 degrees, about right
        
let a = CLLocationCoordinate2D(latitude: 34.439931, longitude: -119.263984)
let b = CLLocationCoordinate2D(latitude: 34.376978, longitude: -119.329645)
// -139, about right

好的,让我们在其他经度值为正的位置尝试一下:

let a = CLLocationCoordinate2D(latitude: 52.518044, longitude: 13.374602) // Berlin
let b = CLLocationCoordinate2D(latitude: 53.444748, longitude: 14.534668) // Szczecin
// 36, looks good to me

很好!现在让我们填写拼图的最后一块,即我实际面对的方位角。我以度数来思考,所以让我们继续使用度数。我将以最后一个结果为例。我在柏林,但现在面朝东方。将我设备的顶部调零。针应该指向什么角度,才能指向什切青?

let myHeading = 90.0 // (I'm facing east)
let bearingFromMe = bearingInDegrees - myHeading
print(bearingFromMe) // -53, sounds good

-53 表示向前和向左。果然,我面向东方,所以这就是我们要去的方向。