我的MS ACCESS VBA函数中的错误在哪里计算新的纬度/经度坐标?

问题描述 投票:0回答:2

我编写了一个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
access-vba
2个回答
2
投票

好消息和坏消息。好消息是你的代码几乎完美无缺,坏消息是Mod运算符总是返回一个整数而不管它的参数类型(为什么是微软!?为什么!?)。

而不是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

1
投票

我添加了自己的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的答案标记为正确,因为他基本上发现了错误,这是我永远不会发现的。

© www.soinside.com 2019 - 2024. All rights reserved.