GPS units use co-ordinate systems to calculate their locations.
There are various different co-ordinate grids used around the world as different grids fit different countries better than others.
Each grid uses it's own datum and set of constants.
This can cause issues when attempting to use co-ordinates from one system with a second system.
Due to the differences in grids, the resultant co-ordinates can be as much as 300m out from their true location.
It gets even more complicated in the UK where the Ordinance Survey has it's own mapping system which only loosly follows a GPS grid
The functions below allow the conversion between various grids and co-ordinate systems.
The maths for the functions was borrowed from the very useful spreadsheet provided by Steven Dutch:
> Steven Dutch --
http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm
and the Javascript functions provided by Chris Veness:
> Chris Veness --
http://www.movable-type.co.uk/scripts/l ... idref.html
(more information about GPS co-ordinate systems is provided on the above websites too.)
The functions require that the Datum Constants for the given grid be preloaded prior to use.
This allows for conversion between different Grids as well as the different co-ordinate systems
A Datum_Constants.ini file is available which conatins the necessary constants
a = equatorial radius
b = polar radius
e = eccentricity of the earth's elliptical cross-section
e1sq = e'2
k0 = scale along central meridian of zone
-------------------------------------------------------------------------------------
I use various pieces of GPS enabled equipment and have had trouble using the data on different systems so I have wrapped the Maths provided by others in a set of functions.
I have only developed functions which are useful to me at the moment but there may be more along in the future.
I provide them here in the hope that they may come in useful to someone.
-------------------------------------------------------------------------------------
GPS.ahk
Code:
;
; AutoHotkey Basic Version: 1.0.48.05
; Language: English
; Platform: Win9x/NT
; Author: wooly_sammoth <ahk@mj2p.co.uk>
;
;####################################################################################
;
;GPS.ahk
;Functions to allow the conversion of GPS co-ordinates to various different grids
;
;####################################################################################
;GPS units use co-ordinate systems to calculate their locations.
;There are various different co-ordinate grids used around the world as different grids fit different countries better than others.
;Each grid uses it's own datum and set of constants.
;This can cause issues when attempting to use co-ordinates from one system with a second system.
;Due to the differences in grids, the resultant co-ordinates can be as much as 300m out from their true location.
;It gets even more complicated in the UK where the Ordinance Survey has it's own mapping system which only loosly follows a GPS grid
;The functions below allow the conversion between various grids and co-ordinate systems.
;The maths for the functions was borrowed from the very useful spreadsheet provided by Steven Dutch:
;> Steven Dutch -- http://www.uwgb.edu/dutchs/usefuldata/utmformulas.htm
;and the Javascript functions provided by Chris Veness:
;> Chris Veness -- http://www.movable-type.co.uk/scripts/latlong-gridref.html
;(more information about GPS co-ordinate systems is provided on the above websites too.)
;
;The functions require that the Datum Constants for the given grid be preloaded prior to use.
;This allows for conversion between different Grids as well as the different co-ordinate systems
;
;A Datum_Constants.ini file is available which conatins the necessary constants
;a = equatorial radius
;b = polar radius
;e = eccentricity of the earth's elliptical cross-section
;e1sq = e'2
;k0 = scale along central meridian of zone
;
;####################################################################################
; Function Name: GPS_UTM2LatLon()
; Description: Converts UTM co-ordinates from the given Grid to Latitude and Longitude
; (cartesian co-ordinates)
; Requirements: Loaded Datum Constants from Datum_Constants.ini file
; Parameter(s): UTMEast - UTM Easting Value
; UTMNorth - UTM Northing Value
; Hemisphere - N = Northern Hemisphere
; S = Southern Hemisphere
; Longitude_Zone - Numerical value between 1 and 60 to indicate Zone (http://www.dmap.co.uk/utmworld.htm)
; Return Value(s): Latitude,Longitude
;
; Author(s): wooly_sammoth
;####################################################################################
GPS_UTM2LatLon(UTMEast, UTMNorth, Hemisphere, Longitude_Zone) {
Global
;For Footprint Latitude
ei := (1-(1-e*e)**(1/2))/(1+(1-e*e)**(1/2))
C1 := (3*ei/2-27*ei**3/32)
C2 := (21*ei**2/16-55*ei**4/32)
C3 := (151*ei**3/96)
C4 := (1097*ei**4/512)
If (Hemisphere = "S")
{
Corrected_Northing := (10000000-UTMNorth)
}
Else
{
Corrected_Northing := UTMNorth
}
East_Prime := (500000-UTMEast)
Arc_Length := (Corrected_Northing / k0)
Mu := (Arc_Length/(a*(1-e**2/4-3*e**4/64-5*e**6/256)))
Footprint_Latitude := (Mu+C1*Sin(2*Mu)+C2*Sin(4*Mu)+C3*Sin(6*Mu)+C4*Sin(8*Mu))
CC1 := (e1sq*Cos(Footprint_Latitude)**2)
T1 := (Tan(Footprint_Latitude)**2)
N1 := (a/(1-(e*Sin(Footprint_Latitude))**2)**(1/2))
R1 := (a*(1-e*e)/(1-(e*Sin(Footprint_Latitude))**2)**(3/2))
D := (East_Prime/(N1*k0))
Fact1 := (N1*Tan(Footprint_Latitude)/R1)
Fact2 := (D*D/2)
Fact3 := ((5+3*T1+10*CC1-4*CC1*CC1-9*e1sq)*D**4/24)
Fact4 := ((61+90*T1+298*CC1+45*T1*T1-252*e1sq-3*CC1*CC1)*D**6/720)
LoFact1 := D
LoFact2 := ((1+2*T1+CC1)*D**3/6)
LoFact3 := ((5-2*CC1+28*T1-3*CC1**2+8*e1sq+24*T1**2)*D**5/120)
Delta_Long := ((LoFact1-LoFact2+LoFact3)/Cos(Footprint_Latitude))
Zone_CM := (6*Longitude_Zone-183)
Raw_Latitude := (180*(Footprint_Latitude-Fact1*(Fact2+Fact3+Fact4))/(4*ATan(1)))
If (Hemisphere = "South")
{
Latitude := -Raw_Latitude
}
Else
{
Latitude := Raw_Latitude
}
Longitude := (Zone_CM-Delta_Long*180/(4*ATan(1)))
Return Latitude . "`," . Longitude
}
;####################################################################################
; Function Name: GPS_LatLon2OS()
; Description: Converts Latitude and Longitude values to OS Grid references
; Requirements: None
; Parameter(s): Latitude - Latitude Value
; Longitude - Longitude Value
; Return Value(s): OS_Easting,OS_Northing
;
; Author(s): wooly_sammoth
;####################################################################################
GPS_LatLon2OS(Latitude, Longitude) {
Global
Pi := (4*ATan(1))
lat := (Latitude *(Pi/180))
lon := (Longitude *(Pi/180))
a_Airy = 6377563.396
b_Airy = 6356256.910 F0 = 0.9996012717
lat0 := (49*(Pi/180))
lon0 := (-2*(Pi/180))
N0 = -100000
E0 = 400000 e2 := (1 - (b_Airy*b_Airy)/(a_Airy*a_Airy))
n := ((a_Airy-b_Airy)/(a_Airy+b_Airy))
n2 := (n*n)
n3 := (n*n*n)
cosLat := Cos(lat)
sinLat := Sin(lat)
nu := (a_Airy*F0/Sqrt(1-e2*sinLat*sinLat))
rho := (a_Airy*F0*(1-e2)/((1-e2*sinLat*sinLat)**1.5))
eta2 := (nu/rho-1)
Ma := ((1 + n + (5/4)*n2 + (5/4)*n3) * (lat-lat0))
Mb := ((3*n + 3*n*n + (21/8)*n3) * Sin(lat-lat0) * Cos(lat+lat0))
Mc := (((15/8)*n2 + (15/8)*n3) * Sin(2*(lat-lat0)) * Cos(2*(lat+lat0)))
Md := ((35/24)*n3 * Sin(3*(lat-lat0)) * Cos(3*(lat+lat0)))
M := (b_Airy * F0 * (Ma - Mb + Mc - Md))
cos3lat := (cosLat*cosLat*cosLat)
cos5lat := (cos3Lat*cosLat*cosLat)
tan2lat := (Tan(lat)*Tan(lat))
tan4lat := (tan2lat*tan2lat)
I := (M + N0)
II := ((nu/2)*sinLat*cosLat)
III := ((nu/24)*sinLat*cos3lat*(5-tan2lat+9*eta2))
IIIA := ((nu/720)*sinLat*cos5lat*(61-58*tan2lat+tan4lat))
IV := (nu*cosLat)
V := ((nu/6)*cos3lat*(nu/rho-tan2lat))
VI := ((nu/120) * cos5lat * (5 - 18*tan2lat + tan4lat + 14*eta2 - 58*tan2lat*eta2))
dLon := (lon-lon0)
dLon2 := (dLon*dLon)
dLon3 := (dLon2*dLon)
dLon4 := (dLon3*dLon)
dLon5 := (dLon4*dLon)
dLon6 := (dLon5*dLon)
Result_N := (I + II*dLon2 + III*dLon4 + IIIA*dLon6)
Result_E := (E0 + IV*dLon + V*dLon3 + VI*dLon5)
Return Result_E . "`," . Result_N
}
;####################################################################################
; Function Name: GPS_UTM2OS()
; Description: Converts UTM coordinates directly to OS Grid references
; (This is just the two functions from above crammed together to avoid having to use a stringsplit)
; Requirements: Loaded Datum Constants from Datum_Constants.ini file
; Parameter(s): UTMEast - UTM Easting Value
; UTMNorth - UTM Northing Value
; Hemisphere - N = Northern Hemisphere
; S = Southern Hemisphere
; Longitude_Zone - Numerical value between 1 and 60 to indicate Zone (http://www.dmap.co.uk/utmworld.htm)
; Return Value(s): OS_Easting,OS_Northing
;
; Author(s): wooly_sammoth
;####################################################################################
GPS_UTM2OS(UTMEast, UTMNorth, Hemisphere, Longitude_Zone) {
Global
;For Footprint Latitude
ei := (1-(1-e*e)**(1/2))/(1+(1-e*e)**(1/2))
C1 := (3*ei/2-27*ei**3/32)
C2 := (21*ei**2/16-55*ei**4/32)
C3 := (151*ei**3/96)
C4 := (1097*ei**4/512)
If (Hemisphere = "S")
{
Corrected_Northing := (10000000-UTMNorth)
}
Else
{
Corrected_Northing := UTMNorth
}
East_Prime := (500000-UTMEast)
Arc_Length := (Corrected_Northing / k0)
Mu := (Arc_Length/(a*(1-e**2/4-3*e**4/64-5*e**6/256)))
Footprint_Latitude := (Mu+C1*Sin(2*Mu)+C2*Sin(4*Mu)+C3*Sin(6*Mu)+C4*Sin(8*Mu))
CC1 := (e1sq*Cos(Footprint_Latitude)**2)
T1 := (Tan(Footprint_Latitude)**2)
N1 := (a/(1-(e*Sin(Footprint_Latitude))**2)**(1/2))
R1 := (a*(1-e*e)/(1-(e*Sin(Footprint_Latitude))**2)**(3/2))
D := (East_Prime/(N1*k0))
Fact1 := (N1*Tan(Footprint_Latitude)/R1)
Fact2 := (D*D/2)
Fact3 := ((5+3*T1+10*CC1-4*CC1*CC1-9*e1sq)*D**4/24)
Fact4 := ((61+90*T1+298*CC1+45*T1*T1-252*e1sq-3*CC1*CC1)*D**6/720)
LoFact1 := D
LoFact2 := ((1+2*T1+CC1)*D**3/6)
LoFact3 := ((5-2*CC1+28*T1-3*CC1**2+8*e1sq+24*T1**2)*D**5/120)
Delta_Long := ((LoFact1-LoFact2+LoFact3)/Cos(Footprint_Latitude))
Zone_CM := (6*Longitude_Zone-183)
Raw_Latitude := (180*(Footprint_Latitude-Fact1*(Fact2+Fact3+Fact4))/(4*ATan(1)))
If (North_or_South = "South")
{
Latitude := -Raw_Latitude
}
Else
{
Latitude := Raw_Latitude
}
Longitude := (Zone_CM-Delta_Long*180/(4*ATan(1)))
GPS_LatLon2OS(Latitude, Longitude)
}
;####################################################################################
; Function Name: GPS_LatLon2UTM()
; Description: Converts Latitude and Longitude cartesian co-ordinates to UTM co-ordinates for a given grid
; Requirements: Loaded Datum Constants from Datum_Constants.ini file
; Parameter(s): Latitude - Latitude Value
; Longitude - Longitude Value
; Return Value(s): UTM_Easting,UTM_Northing
;
; Author(s): wooly_sammoth
;####################################################################################
GPS_LatLon2UTM(Latitude, Longitude) {
Global
;Meridional Arc Constants
n := (a-b)/(a+b)
A0 := a*(1-n+(5*n*n/4)*(1-n) +(81*n**4/64)*(1-n))
B0 := (3*a*n/2)*(1 - n - (7*n*n/8)*(1-n) + 55*n**4/64)
C0 := (15*a*n*n/16)*(1 - n +(3*n*n/4)*(1-n))
D0 := (35*a*n**3/48)*(1 - n + 11*n*n/16)
E0 := (315*a*n**4/51)*(1-n)
LatDegrees := SubStr(Latitude, 1, (InStr(Latitude, ".")-1))
LonDegrees := SubStr(Longitude, 1, (InStr(Longitude, ".")-1))
If (LonDegrees/6) < 0
{
Longitude_Zone := 31 + Floor(LonDegrees/6)
}
Else
{
Longitude_Zone := Round(31+Substr((LonDegrees/6), 1, InStr((LonDegrees/6), ".")))
}
Long_Zone_CM := (6*Longitude_Zone-183)
Delta_LonRad := (LonDegrees-Long_Zone_CM)*(4*ATan(1))/180
LatRad := LatDegrees*(4*ATan(1))/180
LonRad := LonDegrees*(4*ATan(1))/180
rho := a*(1-e*e)/((1-(e*Sin(LatRad))**2)**(3/2))
nu := a/((1-(e*Sin(Latrad))**2)**(1/2))
Arc_S := A0*LatRad - B0*Sin(2*LatRad) + C0*Sin(4*LatRad) - D0*Sin(6*LatRad) + E0*Sin(8*LatRad)
Ki := Arc_S*k0
Kii := nu*Sin(LatRad)*Cos(LatRad)/2
Kiii := ((nu*Sin(LatRad)*Cos(LatRad)**3)/24)*(5-Tan(LatRad)**2+9*e1sq*Cos(LatRad)**2+4*e1sq**2*Cos(LatRad)**4)*k0
Kiv := nu*Cos(LatRad)*k0
Kv := (Cos(LatRad))**3*(nu/6)*(1-Tan(LatRad)**2+e1sq*Cos(LatRad)**2)*k0
A6 := ((Delta_LonRad)**6*nu*Sin(LatRad)*Cos(LatRad)**5/720)*(61-58*Tan(LatRad)**2+Tan(LatRad)**4+270*e1sq*Cos(LatRad)**2-330*e1sq*Sin(LatRad)**2)*k0
Raw_Northing := (Ki+Kii*Delta_LonRad*Delta_LonRad+Kiii*Delta_LonRad**4)
If (Raw_Northing < 0)
{
Northing := (10000000m + Raw_Northing)
}
Else
{
Northing := Raw_Northing
}
Easting := 500000+(Kiv*Delta_LonRad+Kv*Delta_LonRad**3)
Return Northing . "`," . Easting . "`," . Longitude_Zone
}
Datum_Constants.ini
Code:
[WGS84]
b=6356752.314
a=6378137
e=0.081819191
e1sq=0.006739497
k0=0.9996
[NAD83]
b=6356752.314
a=6378137
e=0.081819191
e1sq=0.006739497
k0=0.9996
[GRS80]
b=6356752.314
a=6378137
e=0.081819191
e1sq=0.006739497
k0=0.9996
[WGS72]
b=6356750.5
a=6378135
e=0.081818849
e1sq=0.00673944
k0=0.9996
[Australian 1965]
b=6356774.7
a=6378160
e=0.081820217
e1sq=0.006739667
k0=0.9996
[Krasovsky 1940]
b=6356863
a=6378245
e=0.08181337
e1sq=0.006738531
k0=0.9996
[North American 1927]
b=6356583.8
a=6378206.4
e=0.082271854
e1sq=0.006814785
k0=0.9996
[International 1924]
b=6356911.9
a=6378388
e=0.081991978
e1sq=0.006768185
k0=0.9996
[Hayford 1909]
b=6356911.9
a=6378388
e=0.081991978
e1sq=0.006768185
k0=0.9996
[Clarke 1880]
b=6356514.9
a=6378249.1
e=0.082483257
e1sq=0.006850092
k0=0.9996
[Clarke 1866]
b=6356583.8
a=6378206.4
e=0.082271854
e1sq=0.006814785
k0=0.9996
[Airy 1830]
b=6356256.9
a=6377563.4
e=0.081673399
e1sq=0.006715339
k0=0.9996
[Bessel 1841]
b=6356079
a=6377397.2
e=0.081696846
e1sq=0.006719221
k0=0.9996
[Everest 1830]
b=6356075.4
a=6377276.3
e=0.08147292
e1sq=0.006682192
k0=0.9996
KeyWords: GPS, UTM, OS, British National Grid, Cartesian, Convert