AutoHotkey Community

It is currently May 27th, 2012, 6:36 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 3 posts ] 
Author Message
PostPosted: February 16th, 2011, 1:05 pm 
Offline

Joined: May 12th, 2009, 2:37 pm
Posts: 640
Location: Gloucester UK
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


Last edited by wooly_sammoth on April 20th, 2011, 12:45 pm, edited 1 time in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject: Thanks!
PostPosted: April 7th, 2011, 8:23 pm 
Offline

Joined: August 12th, 2007, 3:49 am
Posts: 12
Hi wooly_sammoth,

Thanks for posting this - it will save me a fair bit of work converting the javascript code I found on the net :-D


I found a couple problems stopping the code from working fully:

* typo "Longditude_Zone" on line 85 and 204

* this line:
If (North_or_South = "South")
should be
If (Hemisphere = "S")
to match the variable name used elsewhere.

* line 232 "n = (a-b)/(a+b)" should be "n := (a-b)/(a+b)"


GPS_UTM2LatLon() now works OK, but I still seem to get odd output from GPS_LatLon2UTM() so there must still be one more problem somewhere.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: April 20th, 2011, 12:48 pm 
Offline

Joined: May 12th, 2009, 2:37 pm
Posts: 640
Location: Gloucester UK
Hey tomte.

Thanks for the code repair. I've made the changes to the original post so the code there should be correct now.
With regards the GPS_LatLon2UTM() function, I was pretty sure that there was an issue somewhere and it's on my todo list but finding the time to go through it all has been tricky. Hopefully I will have a spare moment sometime soon to figure out what's going on with it.

Thanks again

_________________
The sooner you fall behind, the more time you have to catch up.


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: Apollo and 20 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group