Last Updated 20 May 2022
Four of the most commonly used trigonometric functions are built in to the standard Access VBA reference library:
- atn (arctangent of a number = angle whose tangent is a specified number)
- cos (cosine of an angle)
- sin (sine of an angle)
- tan (tangent of an angle)
However, there are times when additional 'trig' functions are required.
For example, drawing a circle on a map using VBA requires two additional trigonometric functions:
- ASin (arcsine = angle whose sine is a specified value)
- Atn2 (arctangent of two values - latitude/longitude)
For more information, see my article Annotating Google Maps elsewhere on this website.
The GMapCircle function used to draw the circle populates a 'temporary' table with the co-ordinates for the circle of a set radius centred on a specified latitude & longitude.
The remaining columns are used to create encoded values for each co-ordinate.
Encoding significantly reduces the overall length of the URL needed to overlay the map with a circle on a separate map layer.
The reasons for doing this are explained in the article linked above.
The code is provided in a separate article on this website: Encoded Map Path Co-ordinates.
The GMapCircle function code is as follows:
Function GMapCircle(Lat, Lng, Rad, Detail)
'====================================
'modified version of code in PHP by Oliver Beattie / Josh McDonald
'http://jomacinc.com/map-radius/
'====================================
'Set detail = 10 to get records every 10 degrees around circle
Dim R As Long, D As Single, i As Long
Dim brng As Double
Dim Points() As Variant
Dim arrValues As Variant
Dim pLat As Double, pLng As Double
Dim rst As DAO.Recordset
R = 6371000 'earth radius in km
'Rad = radius of circle (metres)
Lat = (Lat * Pi) / 180
Lng = (Lng * Pi) / 180
D = Rad / R 'scaling factor
i = 0
'populate table with circle points
Set rst = CurrentDb.OpenRecordset("tblMapCircle", dbOpenDynaset)
With rst
For i = 0 To 360 Step Detail
brng = i * Pi / 180
pLat = ASin((Sin(Lat) * Cos(D)) + (Cos(Lat) * Sin(D) * Cos(brng)))
pLng = ((Lng + Atn2(Sin(brng) * Sin(D) * Cos(Lat), Cos(D) - Sin(Lat) * Sin(pLat))) * 180) / Pi
pLat = (pLat * 180) / Pi
'Debug.Print i, pLat, pLng
.AddNew
!Bearing = i
!Latitude = pLat
!Longitude = pLng
.Update
Next
.Close
End With
Set rst = Nothing
End Function
Example usage:
'GMapCircle(Lat, Lng, Rad, Detail)
'Circle of radius 500 metres centred on postcode BS25 5NB (lat = 51.340207, long = -2.804762) with 10 degree intervals
GMapCircle 51.340207, -2.804762, 500, 10
'Circle of radius 1000 metres centred on postcode SE1 7PB (lat = 51.50282, long = -0.119252) with 5 degree intervals
GMapCircle 51.50282, -0.119252, 1000, 5
The code below contains 6 missing trigonometric functions:
- ASin (arcsine = angle whose sine is a specified value)
- ACos (arccosine = angle whose cosine is a specified value)
- ACot (arccotangent = angle whose cotangent is a specified value)
NOTE: cotangent = 1 / tangent = adjacent / opposite in right-angled triangle
- ASec (arcsecant = angle whose secant is a specified value)
NOTE: secant = 1 / cosine = hypotenuse / adjacent in right-angled triangle
- ACsc (arccosecant = angle whose cosecant is a specified value)
NOTE: cosecant = 1 / sine = hypotenuse / opposite in right-angled triangle
- Atn2 (arctangent of two values - latitude/longitude)
These functions are based on code adapted from various sources including https://www.devx.com
Place the code in a standard module e.g. modTrigFunctions
Option Compare Database
Option Explicit
'----------------------------
'MISSING TRIG FUNCTIONS
'----------------------------
' arc sine
' error if value is outside the range [-1,1]
Function ASin(Value As Double) As Double
If Abs(Value) <> 1 Then
ASin = Atn(Value / Sqr(1 - Value * Value))
Else
ASin = 1.5707963267949 * Sgn(Value)
End If
End Function
'----------------------------
' arc cosine
' error if NUMBER is outside the range [-1,1]
Function ACos(ByVal Number As Double) As Double
If Abs(Number) <> 1 Then
ACos = 1.5707963267949 - Atn(Number / Sqr(1 - Number * Number))
ElseIf Number = -1 Then
ACos = 3.14159265358979
End If
'elseif number=1 --> Acos=0 (implicit)
End Function
'----------------------------
' arc cotangent
' error if NUMBER is zero
Function ACot(Value As Double) As Double
ACot = Atn(1 / Value)
End Function
'----------------------------
' arc secant
' error if value is inside the range [-1,1]
Function ASec(Value As Double) As Double
' NOTE: the following lines can be replaced by a single call
' ASec = ACos(1 / value)
If Abs(Value) <> 1 Then
ASec = 1.5707963267949 - Atn((1 / Value) / Sqr(1 - 1 / (Value * Value)))
Else
ASec = 3.14159265358979 * Sgn(Value)
End If
End Function
'----------------------------
' arc cosecant
' error if value is inside the range [-1,1]
Function ACsc(Value As Double) As Double
' NOTE: the following lines can be replaced by a single call
' ACsc = ASin(1 / value)
If Abs(Value) <> 1 Then
ACsc = Atn((1 / Value) / Sqr(1 - 1 / (Value * Value)))
Else
ACsc = 1.5707963267949 * Sgn(Value)
End If
End Function
'----------------------------
Public Function Atn2(Y As Double, X As Double) As Double
'Arctangent of 2 values (lat/long)
If X > 0 Then
Atn2 = Atn(Y / X)
ElseIf X < 0 Then
Atn2 = Sgn(Y) * (Pi - Atn(Abs(Y / X)))
ElseIf Y = 0 Then
Atn2 = 0
Else
Atn2 = Sgn(Y) * Pi / 2
End If
End Function
I hope these trig functions will be useful to other developers
Colin Riddington Mendip Data Systems Last Updated 20 May 2022
Return to Code Samples Page
|
Return to Top
|