Devuan fork of gpsd
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1008 lines
53 KiB

  1. /*
  2. * geoid.c -- ECEF to WGS84 conversions, including ellipsoid-to-MSL height
  3. * and magnetic variation.
  4. *
  5. * Geoid separation code by Oleg Gusev, from data by Peter Dana.
  6. * ECEF conversion by Rob Janssen.
  7. *
  8. * This file is Copyright (c) 2010-2019 by the GPSD project
  9. * SPDX-License-Identifier: BSD-2-clause
  10. */
  11. #include "gpsd_config.h" /* must be before all includes */
  12. #include <math.h>
  13. #include "gpsd.h"
  14. #include "os_compat.h"
  15. #ifdef __UNUSED
  16. static double fix_minuz(double d);
  17. static double atan2z(double y, double x);
  18. #endif /* __UNUSED */
  19. #define GEOID_ROW 37
  20. #define GEOID_COL 73
  21. /* This table is EGM2008. Values obtained from GeoidEval, part of
  22. * geographiclib., by using devtools/get_geoid_table.py
  23. *
  24. * geoid_delta[][] has the geoid separation, in cm, on a 5 degree by 5
  25. * degree grid for the entire planet.
  26. */
  27. /* *INDENT-OFF* */
  28. const short geoid_delta[GEOID_ROW][GEOID_COL] = {
  29. /* -90 */
  30. { -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  31. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  32. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  33. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  34. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  35. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  36. -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015, -3015,
  37. -3015, -3015, -3015},
  38. /* -85 */
  39. { -3568, -3608, -3739, -3904, -4039, -4079, -4033, -3946, -3845, -3734,
  40. -3603, -3458, -3310, -3163, -2994, -2827, -2695, -2667, -2737, -2823,
  41. -2840, -2757, -2634, -2567, -2547, -2540, -2452, -2247, -1969, -1704,
  42. -1540, -1507, -1552, -1592, -1573, -1513, -1465, -1478, -1542, -1577,
  43. -1483, -1256, -1029, -957, -1066, -1216, -1262, -1194, -1118, -1129,
  44. -1231, -1370, -1504, -1641, -1813, -2028, -2255, -2455, -2630, -2811,
  45. -3022, -3242, -3436, -3578, -3658, -3676, -3640, -3578, -3527, -3490,
  46. -3532, -3570, -3568},
  47. /* -80 */
  48. { -5232, -5276, -5275, -5301, -5286, -5276, -5218, -5001, -4775, -4580,
  49. -4319, -4064, -3854, -3691, -3523, -3205, -2910, -2608, -2337, -2355,
  50. -2417, -2445, -2471, -2350, -2230, -2136, -1869, -1689, -1732, -1748,
  51. -1540, -1236, -1048, -794, -569, -603, -501, -305, -166, 19,
  52. 146, 274, 444, 510, 534, 550, 458, 373, 473, 575,
  53. 607, 732, 562, 153, -271, -825, -1300, -1861, -2475, -2866,
  54. -3434, -4001, -4196, -4533, -4989, -5152, -5094, -4983, -4987, -5065,
  55. -5055, -5115, -5232},
  56. /* -75 */
  57. { -6155, -6339, -6266, -6344, -6282, -6100, -6009, -5492, -5088, -4547,
  58. -4187, -3901, -3586, -3234, -3051, -2886, -2577, -2289, -1981, -1655,
  59. -1435, -1096, -557, -617, -998, -961, -655, -464, -170, 79,
  60. -103, -64, 150, 223, 819, 1006, 1174, 1136, 1211, 1278,
  61. 1467, 1686, 1783, 1706, 1833, 1721, 1653, 1580, 1267, 953,
  62. 629, 807, 774, 607, 217, -386, -814, -1354, -2452, -3542,
  63. -3833, -3932, -4259, -4962, -4977, -5536, -5753, -5800, -6012, -5835,
  64. -5751, -5820, -6155},
  65. /* -70 */
  66. { -6218, -6432, -6333, -6150, -6021, -5948, -5705, -5480, -5213, -4789,
  67. -4365, -4003, -3757, -3514, -3250, -3000, -2672, -2541, -2138, -1220,
  68. -844, -277, 249, 906, 458, 69, 26, 98, 166, 130,
  69. 118, 253, 303, 437, 1010, 1341, 1423, 1558, 1682, 1825,
  70. 1766, 1917, 2027, 2047, 2164, 2909, 2882, 2997, 3010, 2687,
  71. 1749, 1703, 1799, 1438, 1099, 346, -813, -1432, -2149, -2320,
  72. -2704, -3085, -3907, -4172, -4287, -4846, -5466, -5592, -5576, -5525,
  73. -5800, -5954, -6218},
  74. /* -65 */
  75. { -5152, -5115, -5049, -4943, -4858, -4714, -4580, -4369, -4202, -4060,
  76. -3806, -3454, -3210, -3007, -2749, -2484, -2264, -1928, -1501, -1113,
  77. -614, 31, 642, 1502, 1833, 1844, 1268, 1442, 1441, 1302,
  78. 1164, 1041, 945, 874, 896, 1059, 1368, 1680, 1736, 1975,
  79. 1891, 1979, 2131, 2338, 2672, 2861, 3114, 3097, 2801, 2695,
  80. 2422, 2022, 1648, 1340, 713, 352, -127, -895, -1740, -2040,
  81. -2854, -3292, -3453, -3922, -4395, -4538, -4554, -4356, -4445, -4669,
  82. -4988, -5122, -5152},
  83. /* -60 */
  84. { -4598, -4449, -4278, -4056, -3732, -3417, -3205, -3094, -3008, -2876,
  85. -2669, -2478, -2350, -2272, -2218, -1969, -1660, -1381, -1123, -716,
  86. -350, 247, 924, 1712, 2016, 2066, 2032, 1556, 2123, 2322,
  87. 2384, 1034, 2121, 1923, 1720, 1571, 1517, 1668, 2008, 2366,
  88. 2546, 2736, 2914, 3169, 3395, 3467, 3315, 3286, 3279, 3073,
  89. 2930, 2727, 2502, 1783, 893, 311, -328, -778, -1364, -1973,
  90. -2467, -2833, -3143, -3283, -3311, -3120, -2956, -3027, -3485, -3972,
  91. -4454, -4679, -4598},
  92. /* -55 */
  93. { -3414, -3429, -3223, -3013, -2704, -2474, -2292, -2185, -1962, -1818,
  94. -1828, -1485, -1259, -1284, -1327, -1304, -1097, -1071, -628, -326,
  95. 174, 340, 1331, 1217, 1712, 1441, 1467, 1578, 1654, 2179,
  96. 764, 1486, 2074, 2245, 2462, 2655, 2720, 2581, 2423, 2731,
  97. 3145, 3383, 3436, 3909, 4448, 4422, 4032, 3938, 3665, 3461,
  98. 3465, 3317, 2487, 1908, 1311, 683, 52, -582, -1196, -1798,
  99. -2158, -2450, -2475, -2429, -2277, -2011, -2140, -2306, -2551, -2726,
  100. -3016, -3319, -3414},
  101. /* -50 */
  102. { -1615, -1938, -1875, -1827, -1839, -1793, -1605, -1650, -1737, -1773,
  103. -1580, -1237, -1010, -983, -1051, -1025, -838, -653, -316, 48,
  104. 502, 1382, 1186, 1114, 1264, 785, 231, 329, 353, 556,
  105. 1084, 1597, 2065, 2475, 2744, 2701, 2518, 2545, 2584, 2963,
  106. 3323, 3537, 3792, 4085, 4520, 4505, 4459, 4287, 3818, 4112,
  107. 3975, 3293, 2748, 2043, 1272, 569, -207, -898, -1498, -1990,
  108. -2242, -2358, -2212, -1968, -1843, -1695, -1705, -1688, -1400, -1177,
  109. -1013, -1168, -1615},
  110. /* -45 */
  111. { 338, -20, -606, -849, -777, -838, -1123, -1322, -1485, -1503,
  112. -1413, -1203, -1077, -1004, -960, -829, -662, -371, -88, 322,
  113. 710, 1323, 1831, 1202, 908, 47, -292, -367, -495, -174,
  114. 688, 1500, 2194, 2673, 2568, 2423, 2099, 2168, 2617, 2834,
  115. 3254, 3328, 3443, 4442, 4639, 4588, 4524, 4223, 3575, 3187,
  116. 3101, 2651, 2155, 1506, 774, -55, -961, -1719, -2355, -2719,
  117. -2731, -2670, -2430, -2026, -1715, -1477, -1144, -901, -646, -303,
  118. 871, 565, 338},
  119. /* -40 */
  120. { 2048, 1283, 637, 317, 109, -156, -679, -1023, -1186, -1277,
  121. -1275, -1202, -1282, -1150, -1022, -881, -690, -300, -84, 130,
  122. 694, 937, 2220, 1511, 1341, 558, -266, -623, -670, -209,
  123. 643, 1459, 2101, 2385, 2307, 2000, 1765, 1992, 2496, 2733,
  124. 2941, 3431, 3298, 3327, 3877, 4306, 4069, 3446, 2844, 2601,
  125. 2333, 1786, 1318, 599, -238, -1184, -2098, -2786, -3250, -3406,
  126. -3351, -3095, -2741, -2101, -1482, -148, -201, 221, 491, 1179,
  127. 1877, 1206, 2048},
  128. /* -35 */
  129. { 2833, 2556, 1700, 1059, 497, -21, -370, -752, -959, -1103,
  130. -1093, -1104, -1198, -1097, -960, -785, -596, -362, -211, 103,
  131. 739, 1300, 3029, 2021, 1712, 1269, -23, -616, -701, -255,
  132. 684, 1237, 1701, 1903, 1696, 1789, 1795, 2034, 2398, 2561,
  133. 3187, 2625, 2609, 2897, 2564, 3339, 3118, 3121, 2240, 2102,
  134. 1529, 991, 387, -559, -1464, -2380, -3138, -3999, -3899, -3446,
  135. -3473, -3300, -2823, -1043, 143, 970, 2058, 1555, 1940, 2621,
  136. 3154, 3839, 2833},
  137. /* -30 */
  138. { 4772, 3089, 2257, 1381, 566, 64, -136, -612, -868, -1186,
  139. -1309, -1131, -1033, -903, -780, -625, -443, -242, 100, 269,
  140. 815, 1489, 3633, 2424, 1810, 1138, 297, -720, -847, -2,
  141. 347, 579, 1025, 1408, 1504, 1686, 2165, 2353, 2599, 3182,
  142. 3332, 3254, 3094, 2042, 1369, 1945, 1468, 1487, 1505, 1048,
  143. 613, 26, -904, -1757, -2512, -3190, -3751, -3941, -3939, -2896,
  144. -2222, -1766, -1442, 70, 1262, 2229, 3189, 2910, 3371, 3608,
  145. 4379, 4520, 4772},
  146. /* -25 */
  147. { 4984, 2801, 2475, 1374, 798, 198, -269, -628, -1063, -1262,
  148. -1090, -970, -692, -516, -458, -313, -143, 19, 183, 403,
  149. 837, 1650, 3640, 2990, 2084, 628, 422, -597, -1130, -712,
  150. -474, -110, 446, 1043, 1349, 1571, 2008, 2572, 2405, 3175,
  151. 2766, 2407, 2100, 1130, 367, 840, 89, 114, 49, -25,
  152. -494, -1369, -2345, -3166, -3804, -4256, -4141, -3730, -3337, -1814,
  153. -901, -388, 298, 1365, 2593, 3490, 4639, 4427, 4795, 4771,
  154. 5325, 5202, 4984},
  155. /* -20 */
  156. { 4994, 5152, 2649, 1466, 935, 427, -115, -518, -838, -1135,
  157. -1134, -917, -525, -280, -218, -310, -396, -306, -137, 148,
  158. 811, 1643, 3496, 4189, 1958, 358, -784, -684, -740, -800,
  159. -579, -638, -49, 704, 1221, 1358, 1657, 1957, 2280, 2639,
  160. 2157, 1246, 728, -364, -1021, -586, -1098, -1055, -1032, -1244,
  161. -2065, -3158, -4028, -4660, -4802, -4817, -4599, -3523, -2561, -1260,
  162. 446, 1374, 2424, 3310, 4588, 5499, 5724, 5479, 5698, 5912,
  163. 6400, 6116, 4994},
  164. /* -15 */
  165. { 4930, 4158, 2626, 1375, 902, 630, 150, -275, -667, -1005,
  166. -954, -847, -645, -376, -315, -479, -639, -681, -550, -268,
  167. 709, 2996, 4880, 2382, 1695, -136, -964, -1211, -1038, -1045,
  168. -695, -595, 23, 733, 1107, 1318, 1348, 1376, 1630, 2240,
  169. 1248, 454, -737, -1252, -2001, -2513, -1416, -2169, -2269, -3089,
  170. -4063, -5194, -5715, -6105, -5700, -4873, -3919, -2834, -1393, -112,
  171. 1573, 3189, 3907, 4863, 5437, 6548, 6379, 6281, 6289, 5936,
  172. 6501, 5794, 4930},
  173. /* -10 */
  174. { 3525, 2747, 2135, 1489, 1078, 739, 544, -39, -268, -588,
  175. -917, -1025, -1087, -940, -771, -923, -1177, -1114, -919, -383,
  176. -108, 2135, 2818, 1929, 386, -1097, -1911, -1619, -1226, -1164,
  177. -952, -583, 399, 1070, 1280, 1345, 1117, 993, 1306, 1734,
  178. 538, -463, -1208, -1602, -2662, -3265, -3203, -3408, -3733, -5014,
  179. -6083, -7253, -7578, -7096, -6418, -4658, -2647, -586, -87, 1053,
  180. 3840, 3336, 5240, 6253, 6898, 7070, 7727, 7146, 6209, 5826,
  181. 5068, 4161, 3525},
  182. /* -5 */
  183. { 2454, 1869, 1656, 1759, 1404, 1263, 1012, 605, 108, -511,
  184. -980, -1364, -1620, -1633, -1421, -1342, -1412, -1349, -1006, -229,
  185. 1711, 1293, 1960, 605, -793, -2058, -2108, -2626, -1195, -606,
  186. -513, -108, 671, 1504, 1853, 1711, 1709, 940, 570, 296,
  187. -913, -1639, -1471, -1900, -3000, -4164, -4281, -4062, -5366, -6643,
  188. -7818, -8993, -9275, -8306, -6421, -4134, -1837, 1367, 2850, 4286,
  189. 5551, 5599, 5402, 6773, 7736, 7024, 8161, 6307, 5946, 4747,
  190. 3959, 3130, 2454},
  191. /* 0 */
  192. { 2128, 1774, 1532, 1470, 1613, 1589, 1291, 783, 79, -676,
  193. -1296, -1941, -2298, -2326, -2026, -1738, -1412, -1052, -406, 82,
  194. 1463, 1899, 1352, -170, -1336, -2446, -2593, -2328, -1863, -833,
  195. 245, 1005, 1355, 1896, 1913, 1888, 1723, 1642, 940, -127,
  196. -1668, -1919, -1078, -1633, -2762, -4357, -4885, -5143, -6260, -7507,
  197. -8947, -10042, -10259, -8865, -6329, -3424, -692, 1445, 3354, 5132,
  198. 5983, 4978, 7602, 7274, 7231, 6941, 6240, 5903, 4944, 4065,
  199. 3205, 2566, 2128},
  200. /* 5 */
  201. { 1632, 1459, 1243, 1450, 1643, 1432, 867, 283, -420, -1316,
  202. -1993, -2614, -3012, -3016, -2555, -1933, -1256, -688, -133, 634,
  203. 1369, 2095, -92, -858, -1946, -3392, -3666, -3110, -1839, -371,
  204. 674, 1221, 1657, 1994, 2689, 2577, 2020, 2126, 1997, 987,
  205. -739, -989, -1107, -1369, -1914, -3312, -4871, -5365, -6171, -7732,
  206. -9393, -10088, -10568, -9022, -6053, -4104, -1296, 373, 2310, 4378,
  207. 6279, 6294, 6999, 6852, 6573, 6302, 5473, 5208, 4502, 3445,
  208. 2790, 2215, 1632},
  209. /* 10 */
  210. { 1285, 1050, 1212, 1439, 1055, 638, 140, -351, -1115, -2060,
  211. -2904, -3593, -3930, -3694, -2924, -2006, -1145, -441, 164, 1059,
  212. 91, -440, -1043, -2791, -4146, -4489, -4259, -3218, -1691, -683,
  213. 306, 1160, 1735, 3081, 3275, 2807, 2373, 2309, 2151, 1245,
  214. 207, -132, -507, -564, -956, -1917, -3167, -5067, -5820, -7588,
  215. -9107, -9732, -9732, -8769, -6308, -4585, -2512, -891, 1108, 3278,
  216. 5183, 6391, 5985, 5969, 6049, 5616, 4527, 4156, 3531, 2776,
  217. 2456, 1904, 1285},
  218. /* 15 */
  219. { 862, 804, 860, 969, 544, 89, -417, -1008, -1641, -2608,
  220. -3607, -4234, -4482, -4100, -3232, -2092, -1105, -1092, 238, 330,
  221. -571, -1803, -2983, -3965, -5578, -4864, -3777, -2572, -1690, -536,
  222. 806, 2042, 2323, 3106, 3019, 2833, 2260, 2064, 2036, 1358,
  223. 1030, 908, 391, -54, -377, -885, -2172, -3359, -5309, -6686,
  224. -8058, -8338, -8695, -8322, -6404, -5003, -3420, -2060, -255, 1833,
  225. 4143, 4218, 4771, 5031, 5241, 5504, 4399, 3471, 2832, 2266,
  226. 1643, 1190, 862},
  227. /* 20 */
  228. { 442, 488, 986, 877, 757, 1175, -696, -1473, -2285, -3128,
  229. -3936, -4520, -4739, -4286, -3350, -2092, -747, -1894, -1083, -1508,
  230. -2037, -2528, -4813, -6316, -4698, -4222, -3279, -1814, -1001, 212,
  231. 1714, 2273, 2535, 3367, 3112, 2736, 3086, 2742, 2679, 2071,
  232. 1422, 1333, 922, 619, 183, -945, -3070, -3680, -4245, -5461,
  233. -6064, -6652, -6806, -6210, -5947, -5177, -3814, -2589, -1319, 551,
  234. 2150, 3262, 3799, 4177, 4898, 4658, 4149, 2833, 2148, 1410,
  235. 899, 551, 442},
  236. /* 25 */
  237. { -248, 12, 716, 415, 327, -187, -1103, -1729, -2469, -3296,
  238. -4040, -4545, -4642, -4232, -3466, -2064, -1667, -3232, -2660, -2685,
  239. -2789, -4262, -5208, -5084, -4935, -4077, -2622, -804, 131, 946,
  240. 1859, 2203, 3038, 3433, 3758, 3029, 2757, 3524, 3109, 2511,
  241. 2300, 1554, 1316, 1114, 954, -81, -2642, -3389, -3167, -4211,
  242. -4634, -5193, -6014, -6245, -5347, -5313, -3846, -3149, -2130, -354,
  243. 1573, 2760, 3310, 3713, 4594, 3862, 2827, 1939, 1019, 313,
  244. -142, -378, -248},
  245. /* 30 */
  246. { -720, -717, -528, -573, -867, -1224, -1588, -2135, -2796, -3432,
  247. -4036, -4329, -4246, -3464, -2996, -2389, -2323, -2844, -2744, -2884,
  248. -3238, -4585, -5164, -4463, -4064, -3238, -1751, 150, 1657, 2501,
  249. 3023, 3007, 3404, 3976, 4354, 4648, 3440, 2708, 2813, 2968,
  250. 2611, 2104, 1606, 1808, 1086, -392, -1793, -689, -1527, -2765,
  251. -3766, -4709, -3687, -2800, -3375, -3793, -3365, -4182, -2385, -1115,
  252. 785, 2302, 3020, 3564, 4178, 2993, 1940, 1081, 331, -364,
  253. -683, -690, -720},
  254. /* 35 */
  255. { -1004, -1222, -1315, -1304, -1463, -1680, -2160, -2675, -3233, -3746,
  256. -4021, -4053, -3373, -3012, -2447, -2184, -2780, -3219, -2825, -3079,
  257. -3181, -4284, -4548, -3867, -3123, -2302, -785, 943, 2687, 4048,
  258. 4460, 4290, 4118, 4585, 4282, 4437, 4898, 3818, 3696, 3414,
  259. 2299, 2057, 627, 1915, 1833, 451, 678, -876, -1602, -2167,
  260. -3344, -2549, -2860, -3514, -4043, -4207, -4005, -3918, -3121, -1521,
  261. 471, 2023, 2980, 3679, 3465, 2405, 1475, 553, -142, -880,
  262. -1178, -963, -1004},
  263. /* 40 */
  264. { -1223, -1218, -1076, -1116, -1298, -1541, -2085, -2648, -3120, -3473,
  265. -3679, -3342, -2334, -1912, -1787, -1756, -2482, -3182, -3322, -3429,
  266. -3395, -3374, -3372, -3341, -2654, -1509, 105, 1620, 3250, 4603,
  267. 5889, 5776, 5198, 4840, 4903, 5370, 5086, 4536, 4519, 4601,
  268. 3395, 4032, 3890, 3537, 3113, 2183, -1769, -1552, -2856, -3694,
  269. -4092, -3614, -5468, -6518, -6597, -5911, -5476, -4465, -2802, -1076,
  270. 232, 1769, 2305, 3018, 3768, 1721, 1694, 667, -154, -799,
  271. -1068, -1196, -1223},
  272. /* 45 */
  273. { -634, -460, -330, -267, -413, -818, -1310, -1763, -2352, -2738,
  274. -2632, -2685, -1929, -1340, -737, -1441, -2254, -2685, -3358, -3488,
  275. -3635, -3187, -2665, -2142, -1515, -124, 1727, 2798, 3965, 5065,
  276. 6150, 6513, 6089, 5773, 5044, 4471, 4677, 5052, 3938, 4537,
  277. 4425, 3652, 3063, 2178, 1267, 84, -1109, -1974, -2905, -3650,
  278. -4264, -4741, -4136, -6324, -5826, -5143, -4851, -4344, -3225, -1386,
  279. 5, 1153, 2198, 2833, 2835, 2563, 1337, 1194, 503, -329,
  280. -289, -754, -634},
  281. /* 50 */
  282. { -578, -40, 559, 880, 749, 464, 0, -516, -1140, -1655,
  283. -1818, -1589, -1555, -1337, -1769, -1919, -2372, -2981, -3485, -3976,
  284. -3941, -3565, -2614, -2223, -1253, 802, 2406, 3239, 4434, 5428,
  285. 6265, 6394, 6180, 5690, 5855, 5347, 4506, 4685, 4799, 4445,
  286. 3972, 3165, 2745, 1601, 1084, 41, -1170, -1701, -1916, -2914,
  287. -3305, -3790, -4435, -4128, -4163, -4535, -4190, -3891, -2951, -1869,
  288. -414, 851, 1494, 2097, 2268, 1939, 2031, 2460, 638, 578,
  289. 325, 98, -578},
  290. /* 55 */
  291. { -18, 482, 905, 1562, 1739, 983, 1097, 568, 34, -713,
  292. -695, -1072, -1576, -1879, -2479, -2884, -3275, -3971, -4456, -4654,
  293. -4461, -3688, -2697, -1623, -823, 1270, 2523, 3883, 4967, 5977,
  294. 6049, 6149, 6095, 5776, 5820, 5575, 4642, 4099, 4025, 3462,
  295. 2679, 2447, 1951, 1601, 1151, 663, 157, -603, -952, -1987,
  296. -2609, -3316, -3600, -3684, -3717, -3836, -4024, -3452, -2950, -1861,
  297. -903, 89, 975, 1499, 1560, 1601, 1922, 2031, 2326, -58,
  298. 506, -177, -18},
  299. /* 60 */
  300. { 93, 673, 969, 1168, 1498, 1486, 1439, 1165, 1128, 720,
  301. 5, -689, -1610, -2409, -3094, -3585, -4193, -4772, -4678, -4521,
  302. -4184, -2955, -2252, -834, 503, 1676, 2882, 4130, 4892, 5611,
  303. 6390, 6338, 6069, 5974, 5582, 5461, 4788, 4503, 4080, 2957,
  304. 1893, 1773, 1586, 1544, 1136, 1026, 622, 50, -389, -1484,
  305. -2123, -2625, -3028, -3143, -3366, -3288, -3396, -3069, -2770, -2605,
  306. -1663, -555, 25, 491, 1168, 1395, 1641, 1597, 1426, 1299,
  307. 921, -160, 93},
  308. /* 65 */
  309. { 419, 424, 443, 723, 884, 1030, 1077, 1191, 1065, 734,
  310. 265, -1052, -1591, -2136, -2773, -3435, -3988, -3978, -3698, -3509,
  311. -3370, -2490, -1347, -263, 1647, 2582, 3291, 4802, 4447, 5609,
  312. 5879, 6454, 6709, 6606, 5988, 5365, 5103, 4385, 3996, 3250,
  313. 2526, 1766, 1817, 1751, 1275, 857, 636, 29, -12, -918,
  314. -1364, -1871, -2023, -2102, -2258, -2441, -2371, -2192, -1908, -1799,
  315. -1720, -1662, -385, 86, 466, 880, 715, 834, 1010, 1105,
  316. 877, 616, 419},
  317. /* 70 */
  318. { 242, 93, 98, 62, -54, -25, -127, -156, -253, -412,
  319. -805, -1106, -1506, -1773, -2464, -2829, -2740, -2579, -2559, -2271,
  320. -1849, -853, 294, 1055, 2357, 2780, 2907, 3909, 4522, 5272,
  321. 5594, 5903, 5966, 5930, 5592, 5188, 4878, 4561, 4190, 3834,
  322. 2963, 2451, 1981, 1525, 1064, 694, 253, -70, -318, -781,
  323. -979, -1048, -1274, -1413, -1175, -1313, -1449, -1206, -850, -1087,
  324. -828, -933, -540, -301, -35, 53, 279, 267, 345, 371,
  325. 334, 289, 242},
  326. /* 75 */
  327. { 128, 228, 376, 46, -173, -355, -417, -548, -764, -925,
  328. -419, -950, -1185, -1102, -1293, -1355, -1075, -713, -365, 167,
  329. 516, 1381, 1882, 1826, 1956, 2492, 3192, 3541, 3750, 4123,
  330. 4462, 4592, 4472, 4705, 4613, 4559, 4340, 4392, 4144, 3973,
  331. 3119, 2582, 2057, 1684, 1199, 834, 477, 325, 295, -198,
  332. -459, -670, -706, -677, -766, -852, -939, -905, -637, -601,
  333. -531, -433, -292, -158, 88, 85, 118, 121, 147, 179,
  334. 173, 149, 128},
  335. /* 80 */
  336. { 342, 293, 244, 159, 38, 20, 15, -15, -109, -119,
  337. -240, -182, 16, 397, 550, 264, 350, 670, 865, 681,
  338. 1188, 1136, 703, 1153, 1930, 2412, 2776, 3118, 3351, 3634,
  339. 3653, 3272, 3177, 3161, 3354, 3671, 3615, 3572, 3522, 3274,
  340. 2914, 2682, 2426, 2185, 1845, 1584, 1297, 1005, 809, 507,
  341. 248, 314, 230, 96, 149, 240, 274, 297, 153, 109,
  342. 164, 91, 104, 43, 12, 153, 243, 170, 184, 59,
  343. 99, 158, 342},
  344. /* 85 */
  345. { 912, 961, 1013, 1013, 997, 1032, 1026, 1050, 1072, 1132,
  346. 1156, 1253, 1310, 1389, 1441, 1493, 1508, 1565, 1621, 1642,
  347. 1768, 1888, 2036, 2089, 2117, 2106, 2010, 2120, 2276, 2376,
  348. 2426, 2427, 2526, 2582, 2493, 2534, 2628, 2564, 2471, 2509,
  349. 2407, 2332, 2214, 2122, 1987, 1855, 1714, 1619, 1517, 1474,
  350. 1406, 1351, 1308, 1264, 1181, 1081, 1047, 1084, 1043, 964,
  351. 851, 755, 732, 706, 697, 785, 864, 762, 686, 729,
  352. 789, 856, 912},
  353. /* 90 */
  354. { 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  355. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  356. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  357. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  358. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  359. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  360. 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490, 1490,
  361. 1490, 1490, 1490}
  362. };
  363. /* This table is wmm2015. Values obtained from MagneticField, part of
  364. * geographiclib., by using devtools/get_mag_var_table.py
  365. *
  366. * magvar[][] has the magnetic variation (declination), in hundreths of
  367. * a degree, on a 5 degree by 5 * degree grid for the entire planet.
  368. *
  369. * This table is duplicated in gps/clienthelpers.py. Keep them in sync.
  370. */
  371. /* *INDENT-OFF* */
  372. const short magvar[GEOID_ROW][GEOID_COL] = {
  373. /* -90 */
  374. { 14920, 14420, 13920, 13420, 12920, 12420, 11920, 11420, 10920,
  375. 10420, 9920, 9420, 8920, 8420, 7920, 7420, 6920, 6420,
  376. 5920, 5420, 4920, 4420, 3920, 3420, 2920, 2420, 1920,
  377. 1420, 920, 420, -80, -580, -1080, -1580, -2080, -2580,
  378. -3080, -3580, -4080, -4580, -5080, -5580, -6080, -6580, -7080,
  379. -7580, -8080, -8580, -9080, -9580, -10080, -10580, -11080, -11580,
  380. -12080, -12580, -13080, -13580, -14080, -14580, -15080, -15580, -16080,
  381. -16580, -17080, -17580, 17920, 17420, 16920, 16420, 15920, 15420,
  382. 14920},
  383. /* -85 */
  384. { 14174, 13609, 13052, 12504, 11965, 11435, 10914, 10402, 9898,
  385. 9403, 8915, 8434, 7960, 7492, 7029, 6572, 6119, 5671,
  386. 5226, 4784, 4346, 3909, 3475, 3042, 2611, 2180, 1750,
  387. 1319, 889, 457, 25, -409, -845, -1283, -1723, -2166,
  388. -2612, -3061, -3514, -3971, -4431, -4895, -5364, -5837, -6315,
  389. -6798, -7285, -7778, -8277, -8781, -9291, -9808, -10331, -10860,
  390. -11397, -11940, -12491, -13048, -13613, -14184, -14761, -15344, -15931,
  391. -16523, -17117, -17714, 17690, 17094, 16500, 15910, 15325, 14746,
  392. 14174},
  393. /* -80 */
  394. { 12958, 12331, 11733, 11163, 10619, 10099, 9600, 9121, 8659,
  395. 8211, 7776, 7352, 6937, 6529, 6127, 5730, 5338, 4949,
  396. 4563, 4180, 3799, 3420, 3043, 2667, 2292, 1918, 1544,
  397. 1170, 795, 419, 40, -342, -727, -1117, -1512, -1912,
  398. -2318, -2729, -3147, -3571, -4002, -4438, -4880, -5328, -5782,
  399. -6241, -6707, -7180, -7659, -8146, -8641, -9146, -9662, -10190,
  400. -10732, -11290, -11866, -12461, -13077, -13716, -14379, -15064, -15772,
  401. -16500, -17244, -17999, 17241, 16485, 15738, 15007, 14298, 13614,
  402. 12958},
  403. /* -75 */
  404. { 11045, 10435, 9882, 9378, 8915, 8485, 8081, 7699, 7335,
  405. 6983, 6640, 6304, 5972, 5642, 5313, 4982, 4651, 4317,
  406. 3982, 3646, 3309, 2972, 2635, 2300, 1966, 1634, 1304,
  407. 975, 646, 316, -16, -352, -694, -1042, -1398, -1764,
  408. -2138, -2523, -2916, -3319, -3729, -4146, -4569, -4997, -5430,
  409. -5866, -6306, -6750, -7197, -7650, -8109, -8576, -9054, -9545,
  410. -10054, -10585, -11143, -11736, -12371, -13058, -13806, -14624, -15519,
  411. -16489, -17525, 17396, 16307, 15245, 14242, 13317, 12478, 11723,
  412. 11045},
  413. /* -70 */
  414. { 8567, 8144, 7771, 7437, 7132, 6851, 6587, 6336, 6095,
  415. 5858, 5623, 5386, 5144, 4896, 4639, 4372, 4094, 3807,
  416. 3510, 3206, 2895, 2582, 2266, 1952, 1641, 1334, 1033,
  417. 736, 444, 155, -136, -429, -729, -1038, -1359, -1693,
  418. -2042, -2406, -2782, -3170, -3568, -3973, -4383, -4795, -5208,
  419. -5620, -6030, -6437, -6843, -7246, -7650, -8054, -8463, -8880,
  420. -9308, -9756, -10230, -10744, -11314, -11965, -12737, -13686, -14889,
  421. -16424, 17708, 15701, 13867, 12382, 11234, 10344, 9636, 9056,
  422. 8567},
  423. /* -65 */
  424. { 6318, 6126, 5946, 5777, 5617, 5466, 5322, 5183, 5046,
  425. 4910, 4770, 4622, 4464, 4291, 4101, 3891, 3661, 3411,
  426. 3142, 2857, 2558, 2250, 1938, 1625, 1318, 1019, 730,
  427. 454, 189, -67, -318, -570, -827, -1096, -1381, -1685,
  428. -2009, -2354, -2717, -3095, -3485, -3881, -4279, -4676, -5068,
  429. -5453, -5828, -6193, -6546, -6887, -7218, -7538, -7849, -8152,
  430. -8450, -8744, -9037, -9335, -9645, -9979, -10368, -10886, -11809,
  431. -15193, 10922, 8778, 8037, 7595, 7264, 6988, 6744, 6523,
  432. 6318},
  433. /* -60 */
  434. { 4768, 4709, 4640, 4566, 4490, 4416, 4344, 4274, 4208,
  435. 4141, 4071, 3993, 3902, 3794, 3663, 3505, 3318, 3100,
  436. 2852, 2578, 2280, 1965, 1640, 1313, 991, 682, 392,
  437. 123, -125, -354, -569, -778, -991, -1215, -1458, -1726,
  438. -2023, -2347, -2695, -3064, -3445, -3833, -4220, -4600, -4969,
  439. -5323, -5658, -5972, -6264, -6532, -6776, -6993, -7181, -7338,
  440. -7458, -7532, -7546, -7474, -7273, -6857, -6058, -4557, -2058,
  441. 727, 2633, 3688, 4259, 4572, 4736, 4812, 4830, 4812,
  442. 4768},
  443. /* -55 */
  444. { 3771, 3768, 3750, 3720, 3685, 3647, 3611, 3577, 3546,
  445. 3519, 3492, 3462, 3421, 3364, 3283, 3171, 3023, 2835,
  446. 2607, 2339, 2036, 1705, 1356, 1001, 652, 319, 13,
  447. -261, -501, -709, -891, -1058, -1222, -1394, -1587, -1810,
  448. -2069, -2365, -2694, -3048, -3419, -3795, -4168, -4529, -4871,
  449. -5189, -5479, -5737, -5961, -6148, -6293, -6394, -6445, -6436,
  450. -6355, -6184, -5896, -5455, -4817, -3939, -2818, -1532, -251,
  451. 866, 1747, 2404, 2878, 3214, 3446, 3600, 3697, 3750,
  452. 3771},
  453. /* -50 */
  454. { 3099, 3120, 3123, 3115, 3098, 3077, 3056, 3036, 3021,
  455. 3011, 3006, 3001, 2992, 2971, 2929, 2856, 2743, 2584,
  456. 2373, 2111, 1800, 1449, 1071, 680, 294, -71, -401,
  457. -686, -925, -1118, -1273, -1401, -1516, -1633, -1767, -1932,
  458. -2138, -2392, -2689, -3021, -3374, -3734, -4089, -4425, -4736,
  459. -5014, -5253, -5450, -5601, -5700, -5743, -5724, -5634, -5465,
  460. -5202, -4832, -4344, -3732, -3008, -2203, -1368, -556, 188,
  461. 839, 1387, 1838, 2201, 2485, 2704, 2865, 2979, 3054,
  462. 3099},
  463. /* -45 */
  464. { 2611, 2642, 2656, 2658, 2651, 2639, 2625, 2610, 2598,
  465. 2592, 2591, 2595, 2601, 2600, 2583, 2539, 2456, 2321,
  466. 2128, 1871, 1554, 1183, 774, 346, -76, -472, -823,
  467. -1120, -1357, -1540, -1675, -1774, -1850, -1915, -1987, -2083,
  468. -2220, -2411, -2657, -2951, -3276, -3612, -3941, -4248, -4522,
  469. -4755, -4940, -5073, -5147, -5158, -5102, -4972, -4762, -4467,
  470. -4083, -3612, -3068, -2474, -1858, -1251, -675, -141, 343,
  471. 777, 1161, 1495, 1781, 2020, 2214, 2366, 2479, 2559,
  472. 2611},
  473. /* -40 */
  474. { 2236, 2269, 2287, 2295, 2295, 2289, 2279, 2266, 2253,
  475. 2243, 2238, 2239, 2245, 2250, 2246, 2220, 2157, 2043,
  476. 1864, 1613, 1290, 903, 468, 12, -438, -854, -1216,
  477. -1513, -1745, -1916, -2038, -2121, -2172, -2202, -2220, -2243,
  478. -2294, -2397, -2566, -2798, -3077, -3376, -3672, -3945, -4180,
  479. -4367, -4499, -4570, -4575, -4509, -4370, -4157, -3867, -3504,
  480. -3076, -2600, -2099, -1602, -1131, -697, -301, 62, 396,
  481. 706, 992, 1252, 1485, 1688, 1860, 1999, 2106, 2183,
  482. 2236},
  483. /* -35 */
  484. { 1934, 1966, 1985, 1996, 2001, 2000, 1994, 1982, 1967,
  485. 1952, 1939, 1932, 1930, 1932, 1930, 1911, 1860, 1758,
  486. 1589, 1343, 1016, 618, 167, -305, -767, -1187, -1544,
  487. -1830, -2047, -2204, -2315, -2387, -2426, -2432, -2406, -2360,
  488. -2315, -2308, -2368, -2508, -2716, -2964, -3222, -3462, -3666,
  489. -3818, -3909, -3934, -3888, -3771, -3584, -3331, -3015, -2645,
  490. -2236, -1809, -1390, -1003, -658, -355, -85, 165, 403,
  491. 634, 856, 1066, 1261, 1436, 1588, 1714, 1813, 1885,
  492. 1934},
  493. /* -30 */
  494. { 1687, 1715, 1732, 1744, 1752, 1755, 1753, 1744, 1728,
  495. 1709, 1689, 1672, 1660, 1653, 1647, 1629, 1581, 1485,
  496. 1321, 1075, 746, 343, -113, -588, -1045, -1453, -1792,
  497. -2056, -2251, -2390, -2484, -2542, -2565, -2544, -2475, -2360,
  498. -2220, -2093, -2026, -2049, -2164, -2349, -2568, -2786, -2976,
  499. -3116, -3193, -3201, -3138, -3007, -2815, -2567, -2271, -1936,
  500. -1577, -1218, -883, -590, -345, -140, 41, 212, 385,
  501. 563, 742, 918, 1085, 1238, 1374, 1488, 1578, 1643,
  502. 1687},
  503. /* -25 */
  504. { 1485, 1507, 1520, 1530, 1539, 1544, 1545, 1539, 1525,
  505. 1504, 1479, 1454, 1434, 1420, 1407, 1385, 1336, 1239,
  506. 1074, 827, 497, 93, -359, -823, -1262, -1647, -1960,
  507. -2198, -2366, -2478, -2546, -2575, -2564, -2502, -2380, -2200,
  508. -1978, -1753, -1575, -1486, -1504, -1617, -1794, -1998, -2189,
  509. -2341, -2432, -2454, -2406, -2295, -2131, -1920, -1670, -1388,
  510. -1089, -796, -531, -312, -141, -8, 108, 224, 353,
  511. 495, 646, 798, 945, 1082, 1204, 1308, 1389, 1447,
  512. 1485},
  513. /* -20 */
  514. { 1322, 1337, 1344, 1350, 1356, 1363, 1366, 1363, 1351,
  515. 1330, 1303, 1275, 1249, 1230, 1212, 1186, 1132, 1030,
  516. 859, 609, 278, -121, -561, -1006, -1420, -1775, -2058,
  517. -2264, -2401, -2478, -2506, -2489, -2425, -2309, -2134, -1903,
  518. -1633, -1359, -1122, -961, -902, -945, -1074, -1254, -1445,
  519. -1612, -1727, -1778, -1764, -1691, -1570, -1409, -1213, -986,
  520. -743, -504, -294, -131, -15, 66, 135, 213, 311,
  521. 430, 563, 699, 832, 957, 1070, 1165, 1240, 1291,
  522. 1322},
  523. /* -15 */
  524. { 1194, 1201, 1202, 1201, 1204, 1209, 1213, 1211, 1202,
  525. 1183, 1157, 1128, 1101, 1080, 1059, 1028, 968, 858,
  526. 680, 425, 94, -296, -718, -1138, -1522, -1846, -2096,
  527. -2268, -2367, -2401, -2378, -2304, -2182, -2013, -1798, -1545,
  528. -1270, -996, -752, -566, -462, -451, -529, -673, -849,
  529. -1019, -1151, -1228, -1246, -1212, -1135, -1023, -876, -700,
  530. -505, -311, -145, -23, 53, 97, 133, 184, 262,
  531. 366, 488, 615, 739, 856, 963, 1054, 1124, 1170,
  532. 1194},
  533. /* -10 */
  534. { 1097, 1098, 1090, 1083, 1081, 1083, 1087, 1087, 1080,
  535. 1063, 1039, 1011, 986, 965, 943, 906, 838, 718,
  536. 531, 271, -56, -434, -835, -1226, -1578, -1869, -2085,
  537. -2221, -2279, -2265, -2188, -2059, -1886, -1678, -1446, -1198,
  538. -946, -703, -482, -302, -181, -135, -170, -275, -425,
  539. -583, -719, -810, -851, -848, -808, -736, -633, -500,
  540. -346, -191, -59, 32, 78, 96, 109, 141, 205,
  541. 300, 415, 537, 658, 772, 877, 966, 1035, 1078,
  542. 1097},
  543. /* -5 */
  544. { 1026, 1022, 1009, 995, 988, 987, 990, 992, 987,
  545. 973, 951, 926, 903, 882, 856, 813, 734, 603,
  546. 407, 144, -179, -542, -919, -1281, -1601, -1858, -2038,
  547. -2136, -2152, -2094, -1971, -1797, -1589, -1363, -1131, -903,
  548. -685, -480, -293, -131, -10, 55, 50, -22, -143,
  549. -284, -412, -507, -561, -578, -565, -525, -457, -360,
  550. -242, -121, -18, 47, 71, 69, 66, 85, 140,
  551. 229, 339, 460, 580, 695, 803, 895, 966, 1010,
  552. 1026},
  553. /* 0 */
  554. { 975, 971, 953, 935, 924, 922, 926, 930, 928,
  555. 917, 898, 875, 852, 828, 796, 743, 651, 506,
  556. 300, 34, -282, -629, -981, -1314, -1601, -1823, -1967,
  557. -2028, -2006, -1910, -1753, -1553, -1327, -1096, -873, -669,
  558. -484, -315, -160, -20, 94, 166, 181, 134, 38,
  559. -84, -201, -293, -352, -380, -384, -367, -327, -261,
  560. -175, -84, -9, 33, 39, 23, 8, 17, 64,
  561. 147, 255, 375, 497, 617, 731, 831, 908, 957,
  562. 975},
  563. /* 5 */
  564. { 937, 936, 920, 901, 890, 888, 895, 902, 904,
  565. 897, 880, 858, 832, 803, 761, 693, 584, 423,
  566. 205, -65, -374, -704, -1031, -1333, -1587, -1773, -1881,
  567. -1906, -1853, -1730, -1554, -1341, -1112, -885, -675, -490,
  568. -331, -191, -62, 58, 162, 235, 260, 231, 154,
  569. 50, -56, -142, -201, -234, -249, -248, -228, -188,
  570. -130, -67, -18, 2, -9, -38, -64, -63, -24,
  571. 52, 157, 276, 402, 529, 652, 763, 852, 911,
  572. 937},
  573. /* 10 */
  574. { 901, 911, 902, 889, 881, 883, 895, 908, 916,
  575. 913, 899, 876, 845, 806, 749, 662, 532, 352,
  576. 120, -155, -459, -773, -1076, -1347, -1565, -1715, -1787,
  577. -1781, -1703, -1564, -1380, -1167, -942, -724, -526, -357,
  578. -216, -96, 13, 117, 210, 280, 312, 294, 232,
  579. 142, 47, -33, -89, -125, -145, -153, -149, -129,
  580. -97, -61, -38, -40, -67, -110, -146, -156, -127,
  581. -58, 40, 159, 289, 424, 559, 683, 787, 861,
  582. 901},
  583. /* 15 */
  584. { 859, 887, 893, 892, 893, 904, 924, 945, 959,
  585. 962, 950, 925, 888, 836, 760, 651, 497, 294,
  586. 45, -238, -540, -841, -1120, -1360, -1542, -1655, -1694,
  587. -1661, -1565, -1418, -1234, -1028, -812, -604, -416, -257,
  588. -128, -21, 75, 165, 249, 315, 349, 340, 290,
  589. 212, 127, 53, 0, -35, -58, -73, -80, -78,
  590. -68, -58, -61, -85, -131, -189, -238, -260, -243,
  591. -185, -94, 22, 155, 298, 445, 584, 706, 799,
  592. 859},
  593. /* 20 */
  594. { 803, 856, 885, 903, 921, 945, 976, 1006, 1029,
  595. 1037, 1027, 1000, 955, 888, 793, 658, 478, 250,
  596. -18, -314, -617, -908, -1167, -1377, -1524, -1602, -1610,
  597. -1554, -1446, -1296, -1117, -920, -715, -516, -336, -184,
  598. -60, 40, 127, 208, 284, 346, 381, 379, 339,
  599. 273, 198, 131, 81, 46, 22, 3, -14, -27,
  600. -38, -54, -83, -131, -198, -273, -338, -374, -371,
  601. -326, -244, -131, 3, 153, 310, 464, 605, 720,
  602. 803},
  603. /* 25 */
  604. { 731, 813, 871, 916, 957, 1000, 1045, 1086, 1117,
  605. 1131, 1123, 1094, 1040, 958, 842, 682, 475, 221,
  606. -70, -381, -690, -976, -1218, -1402, -1518, -1565, -1546,
  607. -1472, -1354, -1203, -1030, -841, -646, -455, -281, -130,
  608. -8, 90, 173, 249, 318, 377, 413, 418, 389,
  609. 336, 273, 214, 167, 134, 107, 83, 57, 29,
  610. -4, -45, -101, -176, -267, -361, -444, -497, -509,
  611. -477, -404, -296, -162, -7, 159, 326, 483, 621,
  612. 731},
  613. /* 30 */
  614. { 643, 756, 848, 926, 996, 1062, 1124, 1178, 1217,
  615. 1235, 1230, 1197, 1134, 1038, 902, 718, 484, 203,
  616. -113, -443, -762, -1046, -1276, -1439, -1530, -1551, -1511,
  617. -1422, -1297, -1145, -975, -792, -604, -418, -246, -96,
  618. 29, 129, 213, 287, 354, 411, 450, 464, 449,
  619. 411, 362, 313, 272, 238, 208, 176, 139, 94,
  620. 38, -31, -117, -220, -337, -454, -556, -626, -654,
  621. -634, -569, -466, -331, -174, -1, 176, 348, 506,
  622. 643},
  623. /* 35 */
  624. { 547, 691, 818, 930, 1031, 1123, 1205, 1273, 1321,
  625. 1345, 1340, 1304, 1234, 1124, 968, 760, 499, 189,
  626. -153, -505, -837, -1125, -1347, -1495, -1567, -1570, -1514,
  627. -1413, -1281, -1126, -956, -776, -590, -406, -233, -80,
  628. 50, 157, 246, 323, 392, 452, 498, 523, 525,
  629. 507, 476, 440, 405, 371, 335, 292, 239, 173,
  630. 90, -10, -129, -265, -411, -553, -675, -761, -801,
  631. -792, -734, -633, -499, -338, -161, 25, 210, 386,
  632. 547},
  633. /* 40 */
  634. { 454, 626, 784, 929, 1061, 1180, 1283, 1366, 1424,
  635. 1454, 1452, 1413, 1335, 1211, 1036, 804, 513, 173,
  636. -199, -576, -925, -1219, -1439, -1577, -1637, -1627, -1560,
  637. -1450, -1311, -1152, -978, -795, -607, -422, -245, -85,
  638. 54, 172, 271, 358, 435, 504, 562, 603, 627,
  639. 632, 622, 602, 575, 541, 497, 439, 365, 271,
  640. 156, 19, -139, -312, -489, -657, -799, -900, -950,
  641. -947, -892, -792, -656, -492, -310, -117, 79, 271,
  642. 454},
  643. /* 45 */
  644. { 374, 569, 754, 927, 1087, 1230, 1354, 1454, 1525,
  645. 1563, 1565, 1525, 1439, 1301, 1105, 845, 522, 145,
  646. -262, -668, -1037, -1341, -1562, -1696, -1748, -1729, -1654,
  647. -1538, -1392, -1225, -1045, -855, -661, -469, -284, -114,
  648. 39, 172, 289, 392, 486, 572, 648, 712, 761,
  649. 793, 808, 807, 790, 756, 702, 627, 526, 397,
  650. 241, 59, -144, -359, -573, -769, -930, -1043, -1099,
  651. -1098, -1042, -940, -799, -630, -442, -241, -34, 172,
  652. 374},
  653. /* 50 */
  654. { 313, 526, 732, 928, 1110, 1276, 1419, 1536, 1622,
  655. 1671, 1679, 1641, 1549, 1396, 1175, 882, 518, 96,
  656. -355, -797, -1192, -1508, -1733, -1864, -1910, -1885, -1804,
  657. -1680, -1526, -1350, -1159, -960, -755, -552, -354, -168,
  658. 4, 160, 301, 430, 549, 661, 764, 857, 935,
  659. 997, 1040, 1060, 1055, 1023, 960, 864, 731, 561,
  660. 355, 119, -139, -405, -660, -886, -1066, -1187, -1245,
  661. -1241, -1181, -1072, -925, -749, -552, -342, -125, 94,
  662. 313},
  663. /* 55 */
  664. { 270, 499, 721, 935, 1135, 1319, 1480, 1614, 1716,
  665. 1779, 1797, 1761, 1664, 1495, 1245, 909, 490, 9,
  666. -500, -988, -1413, -1744, -1971, -2099, -2138, -2105, -2015,
  667. -1881, -1716, -1528, -1324, -1110, -890, -670, -454, -246,
  668. -48, 137, 311, 475, 629, 776, 914, 1041, 1155,
  669. 1250, 1322, 1366, 1377, 1351, 1281, 1164, 997, 779,
  670. 514, 211, -114, -441, -744, -1003, -1201, -1329, -1387,
  671. -1377, -1308, -1191, -1034, -849, -642, -422, -194, 38,
  672. 270},
  673. /* 60 */
  674. { 240, 482, 719, 946, 1162, 1361, 1539, 1690, 1808,
  675. 1886, 1914, 1882, 1779, 1590, 1302, 908, 415, -149,
  676. -734, -1280, -1738, -2081, -2305, -2422, -2447, -2399, -2294,
  677. -2145, -1963, -1758, -1536, -1302, -1062, -819, -577, -340,
  678. -110, 113, 326, 532, 730, 919, 1099, 1267, 1420,
  679. 1551, 1657, 1730, 1764, 1749, 1680, 1548, 1349, 1080,
  680. 747, 364, -44, -446, -809, -1108, -1328, -1464, -1519,
  681. -1502, -1424, -1297, -1130, -934, -717, -487, -247, -4,
  682. 240},
  683. /* 65 */
  684. { 214, 468, 717, 957, 1186, 1399, 1592, 1759, 1891,
  685. 1982, 2018, 1988, 1872, 1652, 1308, 830, 230, -448,
  686. -1130, -1738, -2220, -2559, -2763, -2853, -2849, -2773, -2641,
  687. -2467, -2260, -2030, -1782, -1523, -1255, -983, -709, -437,
  688. -168, 96, 355, 608, 853, 1090, 1316, 1529, 1725,
  689. 1899, 2044, 2155, 2220, 2232, 2178, 2047, 1828, 1514,
  690. 1111, 635, 124, -376, -819, -1174, -1426, -1577, -1635,
  691. -1615, -1530, -1394, -1218, -1013, -787, -546, -296, -42,
  692. 214},
  693. /* 70 */
  694. { 178, 442, 702, 955, 1195, 1421, 1625, 1802, 1944,
  695. 2040, 2074, 2030, 1881, 1600, 1159, 546, -215, -1041,
  696. -1821, -2461, -2924, -3215, -3362, -3394, -3337, -3214, -3040,
  697. -2827, -2585, -2320, -2040, -1747, -1445, -1138, -828, -517,
  698. -207, 101, 406, 706, 999, 1283, 1558, 1819, 2062,
  699. 2284, 2479, 2637, 2752, 2811, 2799, 2700, 2496, 2170,
  700. 1716, 1147, 511, -125, -689, -1136, -1450, -1637, -1714,
  701. -1702, -1619, -1481, -1302, -1092, -859, -611, -352, -88,
  702. 178},
  703. /* 75 */
  704. { 114, 385, 652, 911, 1157, 1386, 1592, 1767, 1899,
  705. 1975, 1973, 1868, 1622, 1193, 548, -307, -1284, -2226,
  706. -2997, -3542, -3876, -4038, -4070, -4006, -3869, -3677, -3445,
  707. -3182, -2895, -2589, -2269, -1939, -1600, -1257, -909, -559,
  708. -210, 140, 486, 829, 1167, 1497, 1818, 2128, 2423,
  709. 2698, 2951, 3173, 3356, 3491, 3562, 3550, 3431, 3177,
  710. 2759, 2165, 1420, 605, -165, -797, -1254, -1540, -1684,
  711. -1714, -1659, -1539, -1370, -1166, -936, -687, -426, -157,
  712. 114},
  713. /* 80 */
  714. { -8, 249, 501, 742, 965, 1164, 1327, 1442, 1489,
  715. 1441, 1262, 902, 306, -553, -1618, -2716, -3648, -4317,
  716. -4731, -4941, -4998, -4945, -4811, -4617, -4378, -4104, -3804,
  717. -3483, -3146, -2796, -2436, -2068, -1693, -1315, -933, -549,
  718. -164, 220, 603, 984, 1361, 1733, 2099, 2457, 2805,
  719. 3140, 3459, 3758, 4031, 4273, 4472, 4616, 4686, 4657,
  720. 4492, 4146, 3573, 2755, 1755, 731, -142, -778, -1181,
  721. -1395, -1468, -1438, -1333, -1176, -980, -758, -517, -265,
  722. -8},
  723. /* 85 */
  724. { -546, -534, -552, -627, -794, -1097, -1585, -2300, -3236,
  725. -4294, -5297, -6100, -6655, -6988, -7144, -7167, -7093, -6945,
  726. -6742, -6496, -6217, -5912, -5585, -5241, -4883, -4513, -4134,
  727. -3746, -3352, -2952, -2547, -2138, -1726, -1312, -896, -478,
  728. -60, 359, 778, 1196, 1612, 2028, 2441, 2851, 3257,
  729. 3660, 4057, 4448, 4831, 5205, 5567, 5916, 6248, 6558,
  730. 6841, 7088, 7287, 7421, 7465, 7378, 7100, 6543, 5611,
  731. 4289, 2795, 1493, 572, 0, -325, -488, -553, -561,
  732. -546},
  733. /* 90 */
  734. { -17825, -17325, -16825, -16325, -15825, -15325, -14825, -14325, -13825,
  735. -13325, -12825, -12325, -11825, -11325, -10825, -10325, -9825, -9325,
  736. -8825, -8325, -7825, -7325, -6825, -6325, -5825, -5325, -4825,
  737. -4325, -3825, -3325, -2825, -2325, -1825, -1325, -825, -325,
  738. 175, 675, 1175, 1675, 2175, 2675, 3175, 3675, 4175,
  739. 4675, 5175, 5675, 6175, 6675, 7175, 7675, 8175, 8675,
  740. 9175, 9675, 10175, 10675, 11175, 11675, 12175, 12675, 13175,
  741. 13675, 14175, 14675, 15175, 15675, 16175, 16675, 17175, 17675,
  742. -17825}
  743. };
  744. /* *INDENT-ON* */
  745. /* compute bilinear approximation
  746. * since our data set rows and columns are integer degree, the corner
  747. * points can be integers.
  748. *
  749. * since the geoid_delta is shorts, the z11, z12, z21 an z22 can be ints.
  750. */
  751. static double bilinear(int x1, int y1, int x2, int y2, double x,
  752. double y, int z11, int z12, int z21,
  753. int z22)
  754. {
  755. int delta;
  756. double xx1 = x - x1;
  757. double x2x = x2 - x;
  758. double yy1 = y - y1;
  759. double y2y = y2 - y;
  760. /* handle some corner cases */
  761. if (y1 == y2) {
  762. if (x1 == x2)
  763. return z11;
  764. else
  765. return (z22 * (xx1) + z11 * (x2x)) / (x2 - x1);
  766. } else if (x1 == x2) {
  767. return (z22 * (yy1) + z11 * (y2y)) / (y2 - y1);
  768. }
  769. delta = (y2 - y1) * (x2 - x1);
  770. #ifdef __UNUSED
  771. fprintf(stderr, "x1 %d x2 %d y1 %d y2 %d delta %d\n",
  772. x1, x2, y1, y2, delta);
  773. #endif
  774. return (z22 * yy1 * xx1 + z12 * y2y * xx1 +
  775. z21 * yy1 * x2x + z11 * y2y * x2x) / delta;
  776. }
  777. /* return geoid separation (MSL-WGS84) in meters, given a lat/lon in degrees.
  778. * Online calculator here:
  779. * https://geographiclib.sourceforge.io/cgi-bin/GeoidEval
  780. *
  781. * Or use GeoidEval from the geographiclib.
  782. *
  783. * The value for any lat/lon is computed from the 5x5 using bilinear
  784. * interpolation. Should probably use cubic interpolation as GeoidEval
  785. * does by default?
  786. *
  787. * Calculated separation can differ from geoidEval by up to 12m!
  788. */
  789. double wgs84_separation(double lat, double lon)
  790. {
  791. int ilat, ilon;
  792. int ilat1, ilat2, ilon1, ilon2;
  793. const int span = 5;
  794. if (0 == isfinite(lat) ||
  795. 0 == isfinite(lon)) {
  796. return 0.0;
  797. }
  798. /* ilat is 0 to 18
  799. * lat -90 (90S) is ilat 0
  800. * lat 0 is ilat 9
  801. * lat 90 (90N) is ilat 18 */
  802. ilat = (int)floor((90. + lat) / span);
  803. /* ilon is 0 to 36
  804. * lon -180 is ilon 0
  805. * long 0 (Prime Median) is ilon 18
  806. * long 180 is ilon 36 */
  807. ilon = (int)floor((180. + lon) / span);
  808. /* sanity checks to prevent segfault on bad data */
  809. if ((GEOID_ROW <= ilat) || (0 > ilat) ||
  810. (GEOID_COL <= ilon) || (0 > ilon))
  811. return 0.0;
  812. ilat1 = ilat;
  813. ilon1 = ilon;
  814. ilat2 = (ilat < GEOID_ROW - 1) ? ilat + 1 : ilat;
  815. ilon2 = (ilon < GEOID_COL - 1) ? ilon + 1 : ilon;
  816. #ifdef __UNUSED
  817. fprintf(stderr, "ilat1 %3d lat %9.4f ilat2 %3d\n"
  818. "ilon1 %3d lon %9.4f ilon2 %3d\n",
  819. ilat1, lat, ilat2,
  820. ilon1, lon, ilon2);
  821. #endif
  822. /* the "/ 100" is to convert cm to meters */
  823. return bilinear(ilon1 * span - 180, ilat1 * span - 90,
  824. ilon2 * span - 180, ilat2 * span - 90,
  825. lon, lat,
  826. geoid_delta[ilat1][ilon1],
  827. geoid_delta[ilat1][ilon2],
  828. geoid_delta[ilat2][ilon1],
  829. geoid_delta[ilat2][ilon2]
  830. ) / 100;
  831. }
  832. /* return magnetic variation (deviation) degrees, given a lat/lon in degrees.
  833. * Online calculator here:
  834. * https://www.ngdc.noaa.gov/geomag/calculators/magcalc.shtml
  835. *
  836. * Or use MagneticField from the geographiclib.
  837. *
  838. * The value for any lat/lon is computed from the 5x5 using bilinear
  839. * interpolation.
  840. *
  841. * Substantially similar code to wgs84_separation() but may
  842. * diverge eventually, so separate.
  843. *
  844. */
  845. double mag_var(double lat, double lon)
  846. {
  847. int ilat, ilon;
  848. int ilat1, ilat2, ilon1, ilon2;
  849. const int span = 5;
  850. if (0 == isfinite(lat) ||
  851. 0 == isfinite(lon)) {
  852. return 0.0;
  853. }
  854. /* ilat is 0 to 18
  855. * lat -90 (90S) is ilat 0
  856. * lat 0 is ilat 9
  857. * lat 90 (90N) is ilat 18 */
  858. ilat = (int)floor((90. + lat) / span);
  859. /* ilon is 0 to 36
  860. * lon -180 is ilon 0
  861. * long 0 (Prime Median) is ilon 18
  862. * long 180 is ilon 36 */
  863. ilon = (int)floor((180. + lon) / span);
  864. /* sanity checks to prevent segfault on bad data */
  865. if ((GEOID_ROW <= ilat) || (0 > ilat) ||
  866. (GEOID_COL <= ilon) || (0 > ilon))
  867. return 0.0;
  868. ilat1 = ilat;
  869. ilon1 = ilon;
  870. ilat2 = (ilat < GEOID_ROW - 1) ? ilat + 1 : ilat;
  871. ilon2 = (ilon < GEOID_COL - 1) ? ilon + 1 : ilon;
  872. #ifdef __UNUSED
  873. fprintf(stderr, "ilat1 %3d lat %9.4f ilat2 %3d\n"
  874. "ilon1 %3d lon %9.4f ilon2 %3d\n",
  875. ilat1, lat, ilat2,
  876. ilon1, lon, ilon2);
  877. fprintf(stderr, "12 %3d 22 %3d\n"
  878. "11 %3d 12 %3d\n",
  879. magvar[ilat1][ilon1],
  880. magvar[ilat1][ilon2],
  881. magvar[ilat2][ilon1],
  882. magvar[ilat2][ilon2]);
  883. #endif
  884. /* the "/ 100" is to convert cm to meters */
  885. return bilinear(ilon1 * span - 180, ilat1 * span - 90,
  886. ilon2 * span - 180, ilat2 * span - 90,
  887. lon, lat,
  888. magvar[ilat1][ilon1],
  889. magvar[ilat1][ilon2],
  890. magvar[ilat2][ilon1],
  891. magvar[ilat2][ilon2]
  892. ) / 100;
  893. }
  894. /* fill in WGS84 position/velocity fields from ECEF coordinates
  895. * x, y, z are all in meters
  896. * vx, vy, vz are all in meters/second
  897. */
  898. gps_mask_t ecef_to_wgs84fix(struct gps_fix_t *fix,
  899. double x, double y, double z,
  900. double vx, double vy, double vz)
  901. {
  902. double lambda, phi, p, theta, n,vnorth, veast, vup;
  903. double cos_lambda, sin_lambda;
  904. double cos_phi, sin_phi;
  905. double cos_theta, sin_theta;
  906. gps_mask_t mask = 0;
  907. if (0 == isfinite(x) ||
  908. 0 == isfinite(y) ||
  909. 0 == isfinite(z)) {
  910. /* invalid inputs */
  911. return mask;
  912. }
  913. /* geodetic location */
  914. lambda = atan2(y, x);
  915. sincos(lambda, &sin_lambda, &cos_lambda);
  916. p = sqrt(pow(x, 2) + pow(y, 2));
  917. theta = atan2(z * WGS84A, p * WGS84B);
  918. sincos(theta, &sin_theta, &cos_theta);
  919. phi = atan2(z + WGS84E2 * WGS84B * pow(sin_theta, 3),
  920. p - WGS84E * WGS84A * pow(cos_theta, 3));
  921. sincos(phi, &sin_phi, &cos_phi);
  922. n = WGS84A / sqrt(1.0 - WGS84E * pow(sin_phi, 2));
  923. /* altitude is WGS84 */
  924. fix->altHAE = (p / cos_phi) - n;
  925. fix->latitude = phi * RAD_2_DEG;
  926. fix->longitude = lambda * RAD_2_DEG;
  927. mask |= LATLON_SET | ALTITUDE_SET;
  928. /* velocity computation */
  929. vnorth = -vx * sin_phi * cos_lambda - vy * sin_phi * sin_lambda +
  930. vz * cos_phi;
  931. veast = -vx * sin_lambda + vy * cos_lambda;
  932. vup = vx * cos_phi * cos_lambda + vy * cos_phi * sin_lambda + vz * sin_phi;
  933. /* save velNED */
  934. fix->NED.velN = vnorth;
  935. fix->NED.velE = veast;
  936. fix->NED.velD = -vup;
  937. mask |= VNED_SET;
  938. /* velNED is saved, let gpsd_error_model() do the
  939. * sanity checks and calculate climb/speed/track */
  940. return mask;
  941. }
  942. #ifdef __UNUSED
  943. /*
  944. * Some systems propagate the sign along with zero. This messes up
  945. * certain trig functions, like atan2():
  946. * atan2(+0, +0) = 0
  947. * atan2(+0, -0) = PI
  948. * Obviously that will break things. Luckily the "==" operator thinks
  949. * that -0 == +0; we will use this to return an unambiguous value.
  950. *
  951. * I hereby decree that zero is not allowed to have a negative sign!
  952. */
  953. static double fix_minuz(double d)
  954. {
  955. return ((d == 0.0) ? 0.0 : d);
  956. }
  957. /* atan2() protected by fix_minuz() */
  958. static double atan2z(double y, double x)
  959. {
  960. return atan2(fix_minuz(y), fix_minuz(x));
  961. }
  962. #endif /* __UNUSED */