Sub Class_Globals
Private Root As B4XView
Private xui As XUI
Private const MathPIdiv180 As Double = cPI / 180
Private Const WGS84_a As Double = 6378137
Private Const WGS84_b As Double = 6356752.3142
Type eGPSLocation(Latitude As Double, Longitude As Double)
Type eProjCoordinate(Easting As Double, Northing As Double)
End Sub
Public Sub Initialize
' B4XPages.GetManager.LogEvents = True
End Sub
'This event will be called once, before the page becomes visible.
Private Sub B4XPage_Created (Root1 As B4XView)
Root = Root1
Root.LoadLayout("MainPage")
End Sub
'You can see the list of page related events in the B4XPagesManager object. The event name is B4XPage.
Private Sub Button1_Click
' EPSG.IO API, thanks to Omar Parra A.
' https://epsg.io/trans?x=399871.321219788631424&y=5418344.341168709099293&z=0&s_srs=2950&t_srs=4326
' Result: {"x":"-72.20326051","y":"48.89612131","z":"0.00000000"}
' Calculation
Dim iMTMZone As Int = 8
Dim r As eGPSLocation = GetLatLonFromMTMNorthCoordinate(399871.321219788631424, 5418344.341168709099293, iMTMZone)
Log(NumberFormat(r.Latitude, 1, 8) & " " & NumberFormat(r.Longitude, 1, 8))
' 48.89612131 -72.20326051
End Sub
Public Sub GetMTMNorthCoordinateFromLatLon(Latitude As Double, Longitude As Double, iMTMZone As Int) As eProjCoordinate
If iMTMZone < 4 Or iMTMZone > 17 Then Return Null
Return GPS_GetTransverseMercator_FromLatLon(Latitude, Longitude, 304800, 0, GetCentralMeridianForMTMZone(iMTMZone), 0.9999, 0, WGS84_a, WGS84_b)
End Sub
Public Sub GetLatLonFromMTMNorthCoordinate(Easting As Double, Northing As Double, iMTMZone As Int) As eGPSLocation
If iMTMZone < 4 Or iMTMZone > 17 Then Return Null
Return GPS_GetLatLon_FromTransverseMercator(Easting, Northing, 304800, 0, GetCentralMeridianForMTMZone(iMTMZone), 0.9999, 0, WGS84_a, WGS84_b)
End Sub
Private Sub GetCentralMeridianForMTMZone(iZone As Int) As Double
If iZone >= 4 And iZone <= 11 Then
Return -61.5 - (iZone - 4) * 3
End If
If iZone >= 12 And iZone <= 17 Then
Return -81.0 - (iZone - 12) * 3
End If
Return 0
End Sub
Private Sub GPS_GetTransverseMercator_FromLatLon(Latitude As Double, _
Longitude As Double, _
FalseEasting As Double, _
FalseNorthing As Double, _
CentralMeridian As Double, _
CentralMeridianScaleFactor As Double, _
LatitudeOfOrigin As Double, _
Ellipsoid_A As Double, _
Ellipsoid_B As Double) As eProjCoordinate
Dim Northing, Easting, eccPrimeSquared, nu, T, C, A, M, M0 As Double
Dim eccSquared As Double = Ellipsoid_B / Ellipsoid_A
eccSquared = 1 - eccSquared * eccSquared
If Longitude < -180 Then Longitude = Longitude + 360
If Longitude > 180 Then Longitude = Longitude - 360
Dim LatRad As Double = Latitude * MathPIdiv180
Dim LongRad As Double = Longitude * MathPIdiv180
Dim LongOriginRad As Double = CentralMeridian * MathPIdiv180
Dim LatOriginRad As Double = LatitudeOfOrigin * MathPIdiv180
eccPrimeSquared = eccSquared / (1 - eccSquared)
nu = Ellipsoid_A / Sqrt(1 - eccSquared * Sin(LatRad) * Sin(LatRad))
T = Tan(LatRad) * Tan(LatRad)
C = eccPrimeSquared * Cos(LatRad) * Cos(LatRad)
A = Cos(LatRad) * (LongRad - LongOriginRad)
M = Ellipsoid_A * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(2 * LatRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(4 * LatRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Sin(6 * LatRad))
M0 = Ellipsoid_A * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatOriginRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(2 * LatOriginRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(4 * LatOriginRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Sin(6 * LatOriginRad))
Easting = (CentralMeridianScaleFactor * nu * (A + (1 - T + C) * A * A * A / 6 + (5 - 18 * T + T * T + 72 * C - 58 * eccPrimeSquared) * A * A * A * A * A / 120))
Northing = (CentralMeridianScaleFactor * (M - M0 + nu * Tan(LatRad) * (A * A / 2 + (5 - T + 9 * C + 4 * C * C) * A * A * A * A / 24 + (61 - 58 * T + T * T + 600 * C - 330 * eccPrimeSquared) * A * A * A * A * A * A / 720)))
Dim Coord As eProjCoordinate
Coord.Easting = Easting + FalseEasting
Coord.Northing = Northing + FalseNorthing
Return Coord
End Sub
Private Sub GPS_GetLatLon_FromTransverseMercator(Easting As Double, _
Northing As Double, _
FalseEasting As Double, _
FalseNorthing As Double, _
CentralMeridian As Double, _
CentralMeridianScaleFactor As Double, _
LatitudeOfOrigin As Double, _
Ellipsoid_A As Double, _
Ellipsoid_B As Double) As eGPSLocation
Dim Lat, Lon, N1, T1, C1, R1, D, M1, mu1, phi1Rad As Double
Dim LongOriginRad As Double = CentralMeridian * MathPIdiv180
Dim LatOriginRad As Double = LatitudeOfOrigin * MathPIdiv180
Dim eccSquared As Double = Ellipsoid_B / Ellipsoid_A
eccSquared = 1 - eccSquared * eccSquared
Dim e1 As Double = (1 - Sqrt(1 - eccSquared)) / (1 + Sqrt(1 - eccSquared))
Dim eccPrimeSquared As Double = (eccSquared) / (1 - eccSquared)
Dim M0 As Double = Ellipsoid_A * ((1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256) * LatOriginRad - (3 * eccSquared / 8 + 3 * eccSquared * eccSquared / 32 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(2 * LatOriginRad) + (15 * eccSquared * eccSquared / 256 + 45 * eccSquared * eccSquared * eccSquared / 1024) * Sin(4 * LatOriginRad) - (35 * eccSquared * eccSquared * eccSquared / 3072) * Sin(6 * LatOriginRad))
M1 = M0 + (Northing - FalseNorthing) / CentralMeridianScaleFactor
mu1 = M1 / (Ellipsoid_A * (1 - eccSquared / 4 - 3 * eccSquared * eccSquared / 64 - 5 * eccSquared * eccSquared * eccSquared / 256))
phi1Rad = mu1 + (3 * e1 / 2 - 27 * e1 * e1 * e1 / 32) * Sin(2 * mu1) + (21 * e1 * e1 / 16 - 55 * e1 * e1 * e1 * e1 / 32) * Sin(4 * mu1) + (151 * e1 * e1 * e1 / 96) * Sin(6 * mu1)
N1 = Ellipsoid_A / Sqrt(1 - eccSquared * Sin(phi1Rad) * Sin(phi1Rad))
T1 = Tan(phi1Rad) * Tan(phi1Rad)
C1 = eccPrimeSquared * Cos(phi1Rad) * Cos(phi1Rad)
R1 = Ellipsoid_A * (1 - eccSquared) / Power(1 - eccSquared * Sin(phi1Rad) * Sin(phi1Rad), 1.5)
D = (Easting - FalseEasting) / (N1 * CentralMeridianScaleFactor)
Lat = phi1Rad - (N1 * Tan(phi1Rad) / R1) * (D * D / 2 - (5 + 3 * T1 + 10 * C1 - 4 * C1 * C1 - 9 * eccPrimeSquared) * D * D * D * D / 24 + (61 + 90 * T1 + 298 * C1 + 45 * T1 * T1 - 252 * eccPrimeSquared - 3 * C1 * C1) * D * D * D * D * D * D / 720)
Lon = (D - (1 + 2 * T1 + C1) * D * D * D / 6 + (5 - 2 * C1 + 28 * T1 - 3 * C1 * C1 + 8 * eccPrimeSquared + 24 * T1 * T1) * D * D * D * D * D / 120) / Cos(phi1Rad)
Dim e As eGPSLocation
e.Latitude = Lat * (180.0 / cPI)
e.Longitude = (Lon + LongOriginRad) * (180.0 / cPI)
Return e
End Sub