vba - 我的 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
解决方案
好消息和坏消息。好消息是您的代码几乎可以完美运行,坏消息是 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
推荐阅读
- c - 如何限制对 FILE 的访问被 C 中的另一个进程或函数使用(写入/读取)?
- sql - 两次加入同一个表时得到重复值
- npm - 在 npm 包中使用 postinstall 是否安全?
- javascript - SAPUI5中元素绑定中的元素绑定
- php - 无法编辑页面正在迁移 wordpress 托管和域 - Error-post.php
- google-analytics - 如何在没有 gtag.js 库的情况下使用 Google Analytics
- android - Android Studio中4个图像按钮的两个ConstraintLayout有什么不同?
- android - 如何使用改造和 kotlin 协程发送获取请求的参数。?
- networking - 网络启动命令
- python - 在整个站点范围内显示查询集计数?