Module:Ordnance Survey coordinates/sandbox: Difference between revisions

Content deleted Content added
fix bug
start to refactor Helmert
Line 52:
local rad2deg = math.deg
local dr = math.deg(1.0)
 
local wgs84radius = 6378137.0
-- Transverse Mercator parameters
local wgs84ecc = 0.00669438003551279089034150031998869922791
local scaleGB = 0.9996012717
local eastingGB = 400000.0
Line 59:
local lat0GB = 49.0
local lon0GB = -2.0
 
local Airyradius = 6377563.396
 
local Airyecc = 0.006670539761597529073698869358812557054558
--[[ DATUM SHIFT USING HELMERT TRANSFORMATION
*
* height above the ellipsoid is ignored
* latitude and longitude must be given in decimal degrees
*
* no transformation if abs(latitude)>89 or abs(longitude)>89
* (lifting this restriction requires some more lines of code)
*
* Written in 2009 by user Telford at de.wikipedia
* Based on math described in "A Guide to Coordinate Systems in Great Britain"
* by the UK Ordnance Survey
* URL: https://www.ordnancesurvey.co.uk/documents/resources/guide-coordinate-systems-great-britain.pdf
]]
 
-- Datum parameters
 
local OSGBglobe = {
semimajor = 6377563.396,
semiminor = 6356256.910,
ecc = 0.006670539761597529073698869358812557054558
}
 
local WGSglobe = {
semimajor = 6378137.0,
semiminor = 6356752.3141,
ecc = 0.00669438003551279089034150031998869922791
}
 
local WGS2OSGBparam = {
-- Table 4, Section 6.6, Ordnance Survey document
semimajor_src = WGSglobe.semimajor,
semiminor_src = WGSglobe.semiminor,
semimajor_dst = OSGBglobe.semimajor,
semiminor_dst = OSGBglobe.semiminor,
tx = -446.448,
ty = 125.157,
tz = -542.060,
s0 = 1.0000204894,
rx = deg2rad ( -.1502/3600. ),
ry = deg2rad ( -.2470/3600. ),
rz = deg2rad ( -.8241/3600. )
}
 
 
local function HelmertDatumShift ( latitude , longitude, param )
-- return if latitude or longitude out of range
 
if abs(latitude) > 89. or abs(longitude) > 89. then
return {lat=latitude, lon=longitude}
end
 
param = param or WGS2OSGBparam
 
-- parameters for ellipsoids
-- Annex A.1, Ordnance Survey document --
 
local a1 = param.semimajor_src
local b1 = param.semiminor_src
 
local a2 = param.semimajor_dst
local b2 = param.semiminor_dst
 
-- convert latitude and longitude to cartesian coordinates
-- math in Annex B.1, Ordnance Survey document
local phi = deg2rad ( latitude )
local lambda = deg2rad ( longitude )
local cosphi = cos ( phi )
local sinphi = sin ( phi )
local coslambda = cos ( lambda )
local sinlambda = sin ( lambda )
 
local aq = a1 * a1
local e1 = ( aq - b1 * b1 ) / aq
 
local ny = a1 / sqrt ( 1. - e1*sinphi*sinphi )
 
local x1 = ny * cosphi * coslambda
local y1 = ny * cosphi * sinlambda
local z1 = ny * ( 1. - e1 ) * sinphi
-- the helmert transformation proper
-- Equation 3, Section 6.2, Ordnance Survey document
 
local x2 = param.tx + ( param.s0 * x1 - param.rz * y1 + param.ry * z1 )
local y2 = param.ty + ( param.rz * x1 + param.s0 * y1 - param.rx * z1 )
local z2 = param.tz + ( -param.ry *x1 + param.rx * y1 + param.s0 * z1 )
-- convert cartesian coordinates to latitude and longitude
-- math in Annex B.2, of Ordnance Survey document
 
aq = a2 * a2
local e2 = ( aq - b2 * b2 ) / aq
 
lambda = atan ( y2 / x2 )
 
local p2 = sqrt ( x2*x2 + y2*y2 )
phi = atan ( z2 / p2*(1.-e2) )
 
local limit = 1. / b2
local n0 = 11
 
local phi_alt
repeat
phi_alt = phi
ny = a2 / sqrt ( 1. - e2 * sin(phi) * sin(phi) )
phi = atan ( (z2 + e2 * ny * sin(phi)) / p2 )
n0 = n0 - 1
until abs ( phi - phi_alt ) <= limit or n0 <= 0
 
return {lat=rad2deg(phi),lon=rad2deg(lambda)}
 
end
 
-- LAT LONG TO OS GRID LIBRARY RESUMES HERE
 
local function northeast(lett,num,shift)
Line 469 ⟶ 581:
]]
 
 
--[[
* datum shift using Helmert transformation
* parameters for transformation WGS84 --> OSGB36 hard coded
* possibility to implement other parameters should be evident
*
* height above the ellipsoid is ignored
* latitude and longitude must be given in decimal degrees
*
* no transformation if abs(latitude)>89 or abs(longitude)>89
* (lifting this restriction requires some more lines of code)
*
* Written in 2009 by user Telford at de.wikipedia
* Based on math described in "A Guide to Coordinate Systems in Great Britain"
* by the UK Ordnance Survey
* URL: https://www.ordnancesurvey.co.uk/documents/resources/guide-coordinate-systems-great-britain.pdf
]]
 
 
local function HelmertDatumShift ( latitude , longitude )
-- return if latitude or longitude out of range
 
if abs(latitude) > 89. or abs(longitude) > 89. then
return {lat=latitude, lon=longitude}
end
 
-- parameters for ellipsoids
-- Annex A.1, Ordnance Survey document --
 
local a1 = wgs84radius
local b1 = 6356752.3141
 
local a2 = Airyradius
local b2 = 6356256.910
 
-- parameters for transformation WGS84 --> OSGB36
-- Table 4, Section 6.6, Ordnance Survey document
 
local tx = -446.448
local ty = 125.157
local tz = -542.060
local s0 = 1.0000204894
local rx = deg2rad ( -.1502/3600. )
local ry = deg2rad ( -.2470/3600. )
local rz = deg2rad ( -.8241/3600. )
 
-- convert latitude and longitude to cartesian coordinates
-- math in Annex B.1, Ordnance Survey document
local phi = deg2rad ( latitude )
local lambda = deg2rad ( longitude )
local cosphi = cos ( phi )
local sinphi = sin ( phi )
local coslambda = cos ( lambda )
local sinlambda = sin ( lambda )
 
local aq = a1 * a1
local e1 = ( aq - b1 * b1 ) / aq
 
local ny = a1 / sqrt ( 1. - e1*sinphi*sinphi )
 
local x1 = ny * cosphi * coslambda
local y1 = ny * cosphi * sinlambda
local z1 = ny * ( 1. - e1 ) * sinphi
-- the helmert transformation proper
-- Equation 3, Section 6.2, Ordnance Survey document
 
local x2 = tx + ( s0 * x1 - rz * y1 + ry * z1 )
local y2 = ty + ( rz * x1 + s0 * y1 - rx * z1 )
local z2 = tz + ( -ry *x1 + rx * y1 + s0 * z1 )
-- convert cartesian coordinates to latitude and longitude
-- math in Annex B.2, of Ordnance Survey document
 
aq = a2 * a2
local e2 = ( aq - b2 * b2 ) / aq
 
lambda = atan ( y2 / x2 )
 
local p2 = sqrt ( x2*x2 + y2*y2 )
phi = atan ( z2 / p2*(1.-e2) )
 
local limit = 1. / b2
local n0 = 11
 
local phi_alt
repeat
phi_alt = phi
ny = a2 / sqrt ( 1. - e2 * sin(phi) * sin(phi) )
phi = atan ( (z2 + e2 * ny * sin(phi)) / p2 )
n0 = n0 - 1
until abs ( phi - phi_alt ) <= limit or n0 <= 0
 
return {lat=rad2deg(phi),lon=rad2deg(lambda)}
 
end
 
local function find_M ( lat_rad )