我编写了一个函数,从方位和距离计算新的纬度/经度坐标。然而,它正在返回错误的结果,我不明白为什么。我在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
发布于 2019-04-14 06:47:51
好消息和坏消息。好消息是您的代码工作得几乎完美,坏消息是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
发布于 2019-04-14 12:58:29
我添加了我自己的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的答案是正确的,因为他基本上发现了错误,这是我永远也找不到的。
https://stackoverflow.com/questions/55673582
复制相似问题