首页 > 解决方案 > 我的 MS ACCESS VBA 函数计算新的纬度/经度坐标的错误在哪里?

问题描述

我已经编写了一个 MS Access VBA 函数来根据方位和距离计算新的纬度/经度坐标。但是它返回了错误的结果,我不明白为什么。我使用了https://www.movable-type.co.uk/scripts/latlong.html上的公式但是当我针对该页面上的计算器进行测试时,它给出了错误的结果。例如NewLatLong(0, 0, 500, "K", 45)给出纬度5.54656612024095E-02,经度0。纬度转换成度后与页面上的计算器比较是正确的,但是为什么经度返回为零?NewLatLong 的参数是以度为单位的原始纬度和经度、距离、距离单位 (K = 公里) 和从北顺时针方向以度为单位的方位。

MS Access 没有所需的所有三角函数。我提供了新的。这些已经过单独测试,并且似乎功能正确。

我看不出我的代码有什么问题。任何人都可以帮忙。

Public Function NewLatLong(latD As Double, longD As Double, distance As Double, unit As String, bearingD As Double) As Double()
    Dim latlong(2) As Double
    Dim latR As Double, bearingR As Double
    latR = Radians(latD)
    bearingR = Radians(bearingD)
    Dim cosAngDistance As Double, sinAngDistance As Double
    cosAngDistance = Cos(distance / EarthRadius(unit))
    sinAngDistance = Sin(distance / EarthRadius(unit))
    latlong(0) = ArcSine(Sin(latR) * cosAngDistance + Cos(latR) * sinAngDistance * Cos(bearingR))
    latlong(1) = (Radians(longD) + ArcTan2(Sin(bearingR) * sinAngDistance * Cos(latR), cosAngDistance - Sin(latR) * Sin(latlong(0))) + 540) Mod 360 - 180
    NewLatLong = latlong
    Debug.Print latlong(0) & " " & latlong(1)
End Function

Public Function EarthRadius(unit As String) As Double
    If (unit = "M") Then
        EarthRadius = 3963
    ElseIf (unit = "K") Then
        EarthRadius = 6371
    Else
        EarthRadius = 3443.753
    End If
End Function


Public Function Pi() As Double
    Pi = 4 * Atn(1)
End Function

Public Function ArcCosine(value As Double) As Double
    ArcCosine = Atn(-value / Sqr(-value * value + 1)) + 2 * Atn(1)
End Function

Public Function ArcSine(value As Double) As Double
    ArcSine = Atn(value / Sqr(-value * value + 1))
End Function

Public Function ArcTan2(y As Double, x As Double) As Double
    If x > 0 Then
        ArcTan2 = Atn(y / x)
    ElseIf x < 0 Then
        ArcTan2 = Sgn(y) * (Pi() - Atn(Abs(y / x)))
    ElseIf y = 0 Then
        ArcTan2 = 0
    Else
        ArcTan2 = Sgn(y) * Pi() / 2
    End If
End Function

Public Function Radians(degrees As Double) As Double
    Radians = degrees * Pi() / 180
End Function

标签: vbams-access

解决方案


好消息和坏消息。好消息是您的代码几乎可以完美运行,坏消息是 Mod 运算符总是返回一个整数,而不管其参数的类型如何(为什么是 Microsoft!?为什么!?)。

而不是latlong(1) = (Radians(longD) + ArcTan2(Sin(bearingR) * sinAngDistance * Cos(latR), cosAngDistance - Sin(latR) * Sin(latlong(0))) + 540) Mod 360 - 180,使用下面的代码来查找经度

Dim tempLong As Double
tempLong = Radians(longD) + ArcTan2(Sin(bearingR) * sinAngDistance * Cos(latR), cosAngDistance - Sin(latR) * Sin(latlong(0)))
' set longitude if calculated value less than 1
If tempLong < 1 Then
    latlong(1) = tempLong
' if greater than 1, add decimal part back to modulus result
Else
    Dim decLong As Double
    decLong = tempLong
    While decLong > 1
        decLong = decLong - 1
    Wend
    latlong(1) = ((tempLong + 540) Mod 360 - 180) + decLong
End If

推荐阅读