Stuart McLachlan
stuart at lexacorp.com.pg
Fri Mar 23 01:28:17 CDT 2007
On 23 Mar 2007 at 10:01, pcs at AZIZAZ.com wrote: > John, > Alternatively you can use the following function in your > query: Here's my toolkit which gives distances in nautical miles and great circle bearings between places which are held in tblLocations: LocKey - PK - Autonumber .... Lat - Double - Latitude in decimal degrees (S = Negative) Long - Double - Longitude in decimal degrees (W = Negative) Of course, JC would use a Location class which he could pass to the functions Bearing() and DistanceNm() to avoid the DLookup()s <g> ........................................................ Option Compare Database Option Explicit Function DegToRad(angle_degrees As Double) As Double DegToRad = (3.14159265358979 / 180) * angle_degrees End Function Function RadToDeg(angle_radians As Double) As Double RadToDeg = (180 / 3.14159265358979) * angle_radians End Function Function arcsin(X As Double) As Double arcsin = Atn(X / Sqr(-X * X + 1)) End Function Function acos(angle As Double) As Double acos = Atn(-angle / Sqr(-angle * angle + 1)) + 2 * Atn(1) End Function Function NmToRad(distance_nm As Long) As Double NmToRad = (3.14159265358979 / (180 * 60)) * distance_nm End Function Function RadToNm(distance_radians As Double) As Long RadToNm = ((180 * 60) / 3.14159265358979) * distance_radians End Function Function DistanceNm(pos1 As Long, pos2 As Long) As Double Dim lat1 As Double, lat2 As Double, lon1 As Double, lon2 As Double lat1 = DegToRad(DLookup("lat", "tblLocations", "LocKey = " & pos1)) lon1 = DegToRad(DLookup("long", "tblLocations", "LocKey = " & pos1)) lat2 = DegToRad(DLookup("lat", "tblLocations", "LocKey = " & pos2)) lon2 = DegToRad(DLookup("long", "tblLocations", "LocKey = " & pos2)) DistanceNm = RadToNm(2 * arcsin(Sqr((Sin((lat1 - lat2) / 2)) ^ 2 + Cos(lat1) * Cos(lat2) * (Sin((lon1 - lon2) / 2)) ^ 2))) End Function Function Bearing(pos1 As Long, pos2 As Long) As Long If pos1 = pos2 Then Exit Function Dim lat1 As Double, lat2 As Double, lon1 As Double, lon2 As Double Dim Dist As Double lat1 = DegToRad(DLookup("lat", "tblLocations", "LocKey = " & pos1)) lon1 = DegToRad(DLookup("long", "tblLocations", "LocKey = " & pos1)) lat2 = DegToRad(DLookup("lat", "tblLocations", "LocKey = " & pos2)) lon2 = DegToRad(DLookup("long", "tblLocations", "LocKey = " & pos2)) If (Abs(Cos(lat1)) < 0.0000001) Then ' a small number ~ machine precision If (lat1 > 0) Then Bearing = 180 ' starting from N pole Else Bearing = 0 ' starting from S pole End If Exit Function End If Dist = NmToRad(DistanceNm(pos1, pos2)) If Sin(lon1 - lon2) < 0 Then Bearing = RadToDeg(acos((Sin(lat2) - Sin(lat1) * Cos(Dist)) / (Sin(Dist) * Cos(lat1)))) Else Bearing = RadToDeg(2 * 3.14159265358979 - acos((Sin(lat2) - Sin(lat1) * Cos(Dist)) / (Sin(Dist) * Cos(lat1)))) End If End Function