[英]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.