Election results in the London Borough of Sutton.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

OSGB36.rb 5.6 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. # https://raw.github.com/LambethCouncil/OSGB36_Converter/master/OSGB36.rb
  2. module OSGB36
  3. extend self
  4. # Takes OSGB36 Easting/Northing coords
  5. # and returns WGS84 Latitude and Longitude
  6. def en_to_ll(easting, northing)
  7. @OSGB36_ll = to_OSGB36(easting, northing)
  8. to_WGS84(@OSGB36_ll[:latitude], @OSGB36_ll[:longitude])
  9. end
  10. # Takes OSGB36 Easting/Northing coords and returns
  11. # OSGB36 Latitude and Longitude
  12. def to_OSGB36(easting, northing)
  13. @OSGB_F0 = 0.9996012717
  14. @N0 = -100000.0
  15. @E0 = 400000.0
  16. @phi0 = deg_to_rad(49.0)
  17. @lambda0 = deg_to_rad(-2.0)
  18. @a = 6377563.396
  19. @b = 6356256.909
  20. @eSquared = ((@a * @a) - (@b * @b)) / (@a * @a)
  21. @phi = 0.0
  22. @lambda = 0.0
  23. @E = easting
  24. @N = northing
  25. @n = (@a - @b) / (@a + @b)
  26. @M = 0.0
  27. @phiPrime = ((@N - @N0) / (@a * @OSGB_F0)) + @phi0
  28. begin
  29. @M =
  30. (@b * @OSGB_F0)\
  31. * (((1 + @n + ((5.0 / 4.0) * @n * @n) + ((5.0 / 4.0) * @n * @n * @n))\
  32. * (@phiPrime - @phi0))\
  33. - (((3 * @n) + (3 * @n * @n) + ((21.0 / 8.0) * @n * @n * @n))\
  34. * Math.sin(@phiPrime - @phi0)\
  35. * Math.cos(@phiPrime + @phi0))\
  36. + ((((15.0 / 8.0) * @n * @n) + ((15.0 / 8.0) * @n * @n * @n))\
  37. * Math.sin(2.0 * (@phiPrime - @phi0))\
  38. * Math.cos(2.0 * (@phiPrime + @phi0)))\
  39. - (((35.0 / 24.0) * @n * @n * @n)\
  40. * Math.sin(3.0 * (@phiPrime - @phi0))\
  41. * Math.cos(3.0 * (@phiPrime + @phi0))))
  42. @phiPrime += (@N - @N0 - @M) / (@a * @OSGB_F0)
  43. end while ((@N - @N0 - @M) >= 0.001)
  44. @v = @a * @OSGB_F0 * ((1.0 - @eSquared * sin_pow_2(@phiPrime)) ** -0.5)
  45. @rho =
  46. @a\
  47. * @OSGB_F0\
  48. * (1.0 - @eSquared)\
  49. * ((1.0 - @eSquared * sin_pow_2(@phiPrime)) ** -1.5)
  50. @etaSquared = (@v / @rho) - 1.0
  51. @VII = Math.tan(@phiPrime) / (2 * @rho * @v)
  52. @VIII =
  53. (Math.tan(@phiPrime) / (24.0 * @rho * (@v ** 3.0)))\
  54. * (5.0\
  55. + (3.0 * tan_pow_2(@phiPrime))\
  56. + @etaSquared\
  57. - (9.0 * tan_pow_2(@phiPrime) * @etaSquared))
  58. @IX =
  59. (Math.tan(@phiPrime) / (720.0 * @rho * (@v ** 5.0)))\
  60. * (61.0\
  61. + (90.0 * tan_pow_2(@phiPrime))\
  62. + (45.0 * tan_pow_2(@phiPrime) * tan_pow_2(@phiPrime)))
  63. @X = sec(@phiPrime) / @v
  64. @XI =
  65. (sec(@phiPrime) / (6.0 * @v * @v * @v))\
  66. * ((@v / @rho) + (2 * tan_pow_2(@phiPrime)))
  67. @XII =
  68. (sec(@phiPrime) / (120.0 * (@v ** 5.0)))\
  69. * (5.0\
  70. + (28.0 * tan_pow_2(@phiPrime))\
  71. + (24.0 * tan_pow_2(@phiPrime) * tan_pow_2(@phiPrime)))
  72. @XIIA =
  73. (sec(@phiPrime) / (5040.0 * (@v ** 7.0)))\
  74. * (61.0\
  75. + (662.0 * tan_pow_2(@phiPrime))\
  76. + (1320.0 * tan_pow_2(@phiPrime) * tan_pow_2(@phiPrime))\
  77. + (720.0\
  78. * tan_pow_2(@phiPrime)\
  79. * tan_pow_2(@phiPrime)\
  80. * tan_pow_2(@phiPrime)))
  81. @phi =
  82. @phiPrime\
  83. - (@VII * ((@E - @E0) ** 2.0))\
  84. + (@VIII * ((@E - @E0) ** 4.0))\
  85. - (@IX * ((@E - @E0) ** 6.0))
  86. @lambda =
  87. @lambda0\
  88. + (@X * (@E - @E0))\
  89. - (@XI * ((@E - @E0) ** 3.0))\
  90. + (@XII * ((@E - @E0) ** 5.0))\
  91. - (@XIIA * ((@E - @E0) ** 7.0))
  92. { :latitude => rad_to_deg(@phi), :longitude => rad_to_deg(@lambda) }
  93. end
  94. # Takes OSGB36 Latitude and Longitude coords
  95. # and returns WGS84 Latitude and Longitude
  96. def to_WGS84(latitude,longitude)
  97. @a = 6377563.396
  98. @b = 6356256.909
  99. @eSquared = ((@a * @a) - (@b * @b)) / (@a * @a)
  100. @phi = deg_to_rad(latitude)
  101. @lambda = deg_to_rad(longitude)
  102. @v = @a / (Math.sqrt(1 - @eSquared * sin_pow_2(@phi)))
  103. @H = 0
  104. @x = (@v + @H) * Math.cos(@phi) * Math.cos(@lambda)
  105. @y = (@v + @H) * Math.cos(@phi) * Math.sin(@lambda)
  106. @z = ((1 - @eSquared) * @v + @H) * Math.sin(@phi)
  107. @tx = 446.448
  108. @ty = -124.157
  109. @tz = 542.060
  110. @s = -0.0000204894
  111. @rx = deg_to_rad( 0.00004172222)
  112. @ry = deg_to_rad( 0.00006861111)
  113. @rz = deg_to_rad( 0.00023391666)
  114. @xB = @tx + (@x * (1 + @s)) + (-@rx * @y) + (@ry * @z)
  115. @yB = @ty + (@rz * @x) + (@y * (1 + @s)) + (-@rx * @z)
  116. @zB = @tz + (-@ry * @x) + (@rx * @y) + (@z * (1 + @s))
  117. @a = 6378137.000
  118. @b = 6356752.3141
  119. @eSquared = ((@a * @a) - (@b * @b)) / (@a * @a)
  120. @lambdaB = rad_to_deg(Math.atan(@yB / @xB))
  121. @p = Math.sqrt((@xB * @xB) + (@yB * @yB))
  122. @phiN = Math.atan(@zB / (@p * (1 - @eSquared)))
  123. (1..10).each do |i|
  124. @v = @a / (Math.sqrt(1 - @eSquared * sin_pow_2(@phiN)))
  125. @phiN1 = Math.atan((@zB + (@eSquared * @v * Math.sin(@phiN))) / @p)
  126. @phiN = @phiN1
  127. end
  128. @phiB = rad_to_deg(@phiN)
  129. { :latitude => @phiB, :longitude => @lambdaB }
  130. end
  131. private # Some Math
  132. def deg_to_rad(degrees)
  133. degrees / 180.0 * Math::PI
  134. end
  135. def rad_to_deg(r)
  136. (r/Math::PI)*180
  137. end
  138. def sin_pow_2(x)
  139. Math.sin(x) * Math.sin(x)
  140. end
  141. def cos_pow_2(x)
  142. Math.cos(x) * Math.cos(x)
  143. end
  144. def tan_pow_2(x)
  145. Math.tan(x) * Math.tan(x)
  146. end
  147. def sec(x)
  148. 1.0 / Math.cos(x)
  149. end
  150. end