簡體   English   中英

我的 MS ACCESS VBA 函數計算新緯度/經度坐標的錯誤在哪里?

[英]Where is the error in my MS ACCESS VBA function to calculate a new latitude/longitude co-ordinate?

我編寫了一個 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

好消息和壞消息。 好消息是您的代碼幾乎可以完美運行,壞消息是 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

我添加了我自己的 mod 函數,它可以與雙打一起正常工作。

Public Function ModDouble(dividend As Double, divisor As Double) As Double
    Dim x As Double
    x = Int(dividend / divisor)
    ModDouble = dividend - (x * divisor)
End Function

這使得原始代碼可以正常工作,使用

latlong(1) = ModDouble(radians(longD) + ArcTan2(Sin(bearingR) * sinAngDistance * Cos(latR), cosAngDistance - Sin(latR) * Sin(latlong(0))) + 540, 360) - 180

但我會將 BankBuilder 的答案標記為正確,因為他基本上發現了我永遠不會發現的錯誤。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM