libcfe  0.12.1
some useful C-functions
geo_calculations.c
Go to the documentation of this file.
1 #include "config.h"
2 #include "geo_calculations.h"
3 
4 #include <features.h>
5 #include <stdio.h>
6 
7 #include "gpstypes.h"
8 
9 #ifndef MIN
10 # define MIN(a,b) (((a) < (b)) ? (a) : (b))
11 #endif
12 
13 #ifndef MAX
14 # define MAX(a,b) (((a) > (b)) ? (a) : (b))
15 #endif
16 
17 #define MAX_NUMBER_ITERATIONS (100)
18 
19 /* if macro USE_MPFR is set, use the mpfr version of the calculation
20  * it is not much more accurate, but a can handle small numbers a bit better at the cost of some preformance.
21  * Otherwise use the faster calculation which uses long doubles, in almost all cases this should be enough.
22  * If you define USE_MPFR, dont forget to link against libmpfr (-lmpfr) instead of libm.
23  */
24 
25 #if defined USE_MPFR && defined HAVE_LIBMPFR
26 
27 #include <mpfr.h>
28 
29 #define FORMULA_MPFR
30 /*
31 #undef EARTH_RADIUS_IN_METERS
32 #define EARTH_RADIUS_IN_METERS "6372797.560856"
33 */
34 #ifndef DEFAULT_PREC
35 #define DEFAULT_PREC 64
36 #endif
37 
38 #define _MPFR_DEFAULT_PREC MIN(MAX((DEFAULT_PREC), (MPFR_PREC_MIN)), ((MPFR_PREC_MAX) / 4))
39 
40 int deg_to_rad_mpfr(mpfr_ptr res, mpfr_srcptr x, mpfr_rnd_t r);
41 int VincentyDistance_mpfr(mpfr_ptr res, mpfr_srcptr lat1, mpfr_srcptr lng1, mpfr_srcptr lat2, mpfr_srcptr lng2, mpfr_prec_t p, mpfr_rnd_t r);
42 
43 /* convert degrees to radians, res = x * PI / 180 */
44 int deg_to_rad_mpfr(mpfr_ptr res, mpfr_srcptr x, mpfr_rnd_t r)
45 {
46  mpfr_set_nan(res);
47  mpfr_t pi;
48  mpfr_init2(pi, mpfr_get_default_prec() * 2);
49 
50  mpfr_const_pi(pi, r);
51  mpfr_mul(res, x, pi, r);
52  mpfr_div_ui(res, res, 180, r);
53 
54  mpfr_free_cache();
55  mpfr_clears(pi, (mpfr_ptr)NULL);
56 
57  return 0;
58 }
59 
60 int VincentyDistance_mpfr(mpfr_ptr res, mpfr_srcptr lat1, mpfr_srcptr lng1, mpfr_srcptr lat2, mpfr_srcptr lng2, mpfr_prec_t p, mpfr_rnd_t r)
61 {
62  mpfr_t a, b, f, fInv, L, U1, U2, sinU1, sinU2, cosU1, cosU2, lambda, lambdaP, sinLambda, cosLambda, sigma, sinSigma, cosSigma, sinAlpha, cosSqAlpha, cos2SigmaM, C, dLambda, lambdaC, uSq, k1, A, B, deltaSigma;
63  mpfr_inits2(p, a, b, f, fInv, L, U1, U2, sinU1, sinU2, cosU1, cosU2, lambda, lambdaP, sinLambda, cosLambda, sigma, sinSigma, cosSigma, sinAlpha, cosSqAlpha, cos2SigmaM, C, dLambda, lambdaC, uSq, k1, A, B, deltaSigma, (mpfr_ptr)NULL);
64  mpfr_t part1, tmp1, tmp2, tmp3, tmp4;
65  mpfr_inits2(p, part1, tmp1, tmp2, tmp3, tmp4, (mpfr_ptr)NULL);
66 
67  /* set result to NaN (not a number, until we reach the final calculation */
68  mpfr_set_nan(res);
69 
70  /* some constants */
71  /* precision target, setting this smaller than 1 * 10 ^ -12 does not have much effect */
72  mpfr_set_ld(lambdaC, (long double)1e-24, MPFR_RNDA); /* round away from zero (0). what ever precision is choosen, this value is alwas hihger then zero (0) */
73  /* radius at equator */
74  mpfr_set_ld(a, (long double)6378137.0, r);
75  /* flattening of the ellipsoid (fInv is the inverse of this) */
76  mpfr_set_ld(fInv, (long double)298.257223563, r);
77  mpfr_ui_div(f, 1, fInv, r);
78 
79  /* b = (1 - f) * a */
80  mpfr_ui_sub(tmp1, 1, f, r);
81  mpfr_mul(b, tmp1, a, r);
82 
83  /* L = lng2 - lng1 */
84  mpfr_sub(L, lng2, lng1, r);
85 
86  /*
87  U1 = atan((1 - f) * tan(lat1))
88  U2 = atan((1 - f) * tan(lat2))
89  */
90  mpfr_ui_sub(part1, 1, f, r);
91  mpfr_tan(tmp1, lat1, r);
92  mpfr_mul(U1, part1, tmp1, r);
93  mpfr_atan(U1, U1, r);
94  mpfr_tan(tmp1, lat2, r);
95  mpfr_mul(U2, part1, tmp1, r);
96  mpfr_atan(U2, U2, r);
97  //mpfr_printf("sin(U1) = %Rf\ncos(U1) = %Rf\n", sinU1, cosU1);
98  //mpfr_printf("sin(U2) = %Rf\ncos(U2) = %Rf\n", sinU2, cosU2);
99 
100  mpfr_sin(sinU1, U1, r);
101  mpfr_sin(sinU2, U2, r);
102  mpfr_cos(cosU1, U1, r);
103  mpfr_cos(cosU2, U2, r);
104  //mpfr_printf("sin(U1) = %Rf\ncos(U1) = %Rf\n", sinU1, cosU1);
105  //mpfr_printf("sin(U2) = %Rf\ncos(U2) = %Rf\n", sinU2, cosU2);
106 
107  //lambda = L;
108  mpfr_set(lambda, L, r);
109  //lambdaP = 0;
110  mpfr_set_ui(lambdaP, 0, r);
111 
112  /* maximum number of iterations, after this amount we return without a result */
113  int iterLimit = MAX_NUMBER_ITERATIONS;
114 
115  do
116  {
117  //printf("2\n");
118  //sinLambda = sin(lambda);
119  //cosLambda = cos(lambda);
120  mpfr_sin(sinLambda, lambda, r);
121  mpfr_cos(cosLambda, lambda, r);
122  //mpfr_printf("sin(lambda) = %Rf\ncos(lambda) = %Rf\n", sinLambda, cosLambda);
123 
124  // sinSigma = sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
125  mpfr_mul(tmp1, cosU2, sinLambda, r);
126  //mpfr_printf("cosU2 * sinLambda = %Rf\n", tmp1);
127  mpfr_sqr(tmp1, tmp1, r);
128  //mpfr_printf("sqr(cosU2 * sinLambda) = %Rf\n", tmp1);
129  mpfr_mul(tmp2, cosU1, sinU2, r);
130  //mpfr_printf("cosU1 * sinU2 = %Rf\n", tmp2);
131  mpfr_mul(tmp3, sinU1, cosU2, r);
132  mpfr_mul(tmp3, tmp3, cosLambda, r);
133  //mpfr_printf("sinU1 * cosU2 * cosLambda = %Rf\n", tmp3);
134  mpfr_sub(tmp2, tmp2, tmp3, r);
135  //mpfr_printf("cosU1 * sinU2 - sinU1 * cosU2 * cosLambda = %Rf\n", tmp2);
136  mpfr_sqr(tmp2, tmp2, r);
137  //mpfr_printf("sqr(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) = %Rf\n", tmp2);
138  mpfr_add(tmp3, tmp1, tmp2, r);
139  //mpfr_printf("sqr(cosU2 * sinLambda) + sqr(cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) = %Rf\n", tmp3);
140  mpfr_sqrt(sinSigma, tmp3, r);
141 
142  if(mpfr_nan_p(sinSigma) != 0 || mpfr_zero_p(sinSigma) != 0 || mpfr_cmp_ui(sinSigma, 0) == 0) return -1; // co-incident points
143 
144  // cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda
145  mpfr_mul(tmp1, sinU1, sinU2, r);
146  mpfr_mul(tmp2, cosU1, cosU2, r);
147  mpfr_mul(tmp2, tmp2, cosLambda, r);
148  mpfr_add(cosSigma, tmp1, tmp2, r);
149 
150  // sigma = atan2(sinSigma, cosSigma)
151  mpfr_atan2(sigma, sinSigma, cosSigma, r);
152 
153  // sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma
154  mpfr_mul(sinAlpha, cosU1, cosU2, r);
155  mpfr_mul(sinAlpha, sinAlpha, sinLambda, r);
156  mpfr_mul(sinAlpha, sinAlpha, sinSigma, r);
157 
158  // cosSqAlpha = 1 - sinAlpha * sinAlpha
159  mpfr_mul(tmp1, sinAlpha, sinAlpha, r);
160  mpfr_ui_sub(cosSqAlpha, 1, tmp1, r);
161 
162  // cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha
163  mpfr_mul(tmp1, sinU1, sinU2, r);
164  mpfr_div(tmp1, tmp1, cosSqAlpha, r);
165  mpfr_mul_ui(tmp1, tmp1, 2, r);
166  mpfr_sub(cos2SigmaM, cosSigma, tmp1, r);
167 
168  if(mpfr_nan_p(cos2SigmaM) != 0) mpfr_set_ui(cos2SigmaM, 0, r); // equatorial line: cosSqAlpha=0
169 
170  // C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha))
171  mpfr_mul_ui(tmp1, cosSqAlpha, 3, r);
172  mpfr_ui_sub(tmp2, 4, tmp1, r);
173  mpfr_mul(tmp1, f, tmp2, r);
174  mpfr_add_ui(tmp2, tmp1, 4, r);
175  mpfr_mul(tmp1, cosSqAlpha, tmp2, r);
176  mpfr_div_ui(tmp2, f, 16, r);
177  mpfr_mul(C, tmp2, tmp1, r);
178 
179  mpfr_set(lambdaP, lambda, r);
180 
181  // lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)))
182  mpfr_sqr(tmp3, cos2SigmaM, r);
183  mpfr_mul_ui(tmp3, tmp3, 2, r);
184  mpfr_sub_ui(tmp2, tmp3, 1, r);
185  mpfr_mul(tmp1, cosSigma, tmp2, r);
186  mpfr_mul(tmp1, C, tmp1, r);
187  mpfr_add(tmp3, cos2SigmaM, tmp1, r);
188  mpfr_mul(tmp2, sinSigma, tmp3, r);
189  mpfr_mul(tmp2, C, tmp2, r);
190  mpfr_add(tmp1, sigma, tmp2, r);
191  mpfr_mul(tmp3, sinAlpha, tmp1, r);
192  mpfr_mul(tmp3, f, tmp3, r);
193  mpfr_ui_sub(tmp2, 1, C, r);
194  mpfr_mul(tmp1, tmp2, tmp3, r);
195  mpfr_add(lambda, L, tmp1, r);
196 
197  mpfr_sub(dLambda, lambda, lambdaP, r);
198  mpfr_abs(dLambda, dLambda, r);
199  }
200  while((mpfr_less_p(dLambda, lambdaC) == 0) && (--iterLimit > 0));
201 
202  // uSq = cosSqAlpha * (a * a - b * b) / (b * b)
203  mpfr_sqr(tmp1, a, r);
204  mpfr_sqr(tmp2, b, r);
205  mpfr_sub(tmp3, tmp1, tmp2, r);
206  mpfr_div(tmp1, tmp3, tmp2, r);
207  mpfr_mul(uSq, cosSqAlpha, tmp1, r);
208 
209  // k1 = (sqrt(1 + uSq) - 1) / (sqrt(1 + uSq) + 1)
210  mpfr_add_ui(tmp2, uSq, 1, r);
211  mpfr_sqrt(tmp1, tmp2, r);
212  mpfr_sub_ui(tmp2, tmp1, 1, r);
213  mpfr_add_ui(tmp3, tmp1, 1, r);
214  mpfr_div(k1, tmp2, tmp3, r);
215 
216  // A = (1 + 0.25 * k1 * k1) / (1 - k1)
217  mpfr_sqr(tmp1, k1, r);
218  mpfr_div_ui(tmp3, tmp1, 4, r);
219  mpfr_add_ui(tmp2, tmp3, 1, r);
220  mpfr_ui_sub(tmp3, 1, k1, r);
221  mpfr_div(A, tmp2, tmp3, r);
222 
223  // B = k1 * (1 - 3/8 * k1 * k1)
224  mpfr_mul_ui(tmp3, tmp1, 3, r);
225  mpfr_div_ui(tmp3, tmp3, 8, r);
226  mpfr_ui_sub(tmp2, 1, tmp3, r);
227  mpfr_mul(B, k1, tmp2, r);
228 
229  // deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)))
230  mpfr_sqr(tmp2, sinSigma, r);
231  mpfr_mul_ui(tmp2, tmp2, 4, r);
232  mpfr_sub_ui(tmp2, tmp2, 3, r);
233  mpfr_sqr(tmp4, cos2SigmaM, r);
234  mpfr_mul_ui(tmp3, tmp4, 4, r);
235  mpfr_sub_ui(tmp3, tmp3, 3, r);
236  mpfr_mul(tmp1, tmp2, tmp3, r);
237 
238  mpfr_mul(tmp3, cos2SigmaM, tmp1, r);
239  mpfr_mul(tmp3, tmp3, B, r);
240  mpfr_div_ui(tmp3, tmp3, 6, r);
241 
242  mpfr_mul_ui(tmp2, tmp4, 2, r);
243  mpfr_sub_ui(tmp2, tmp2, 1, r);
244 
245  mpfr_mul(tmp1, cosSigma, tmp2, r);
246  mpfr_sub(tmp1, tmp1, tmp3, r);
247 
248  mpfr_mul(tmp2, B, tmp1, r);
249  mpfr_div_ui(tmp2, tmp2, 4, r);
250  mpfr_add(tmp2, cos2SigmaM, tmp2, r);
251 
252  mpfr_mul(tmp1, sinSigma, tmp2, r);
253  mpfr_mul(deltaSigma, B, tmp1, r);
254 
255  // res = b * A * (sigma - deltaSigma)
256  mpfr_sub(tmp1, sigma, deltaSigma, r);
257  mpfr_mul(tmp2, A, tmp1, r);
258  mpfr_mul(res, b, tmp2, r);
259 
260  /* calculate heading
261  //heading_start = atan2((cosU2 * sinLambda) / (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda))
262  mpfr_mul(part1, cosU2, sinLambda, r);
263  mpfr_mul(tmp1, cosU1, sinU2, r);
264  mpfr_mul(tmp2, sinU1, cosU2, r);
265  mpfr_mul(tmp2, tmp2, cosLambda, r);
266  mpfr_sub(tmp1, tmp1, tmp2, r);
267  mpfr_atan2(heading_start, part1, tmp1, r);
268 
269  //heading_end = atan2((cosU1 * sinLambda) / (-sinU1 * cosU2 + cosU1 * sinU2 * cosLambda))
270  mpfr_mul(part1, cosU1, sinLambda, r);
271  mpfr_mul_si(tmp1, sinU1, -1, r);
272  mpfr_mul(tmp1, tmp1, cosU2, r);
273  mpfr_mul(tmp2, cosU1, sinU2, r);
274  mpfr_mul(tmp2, tmp2, cosLambda, r);
275  mpfr_sub(tmp1, tmp1, tmp2, r);
276  mpfr_atan2(heading_end, part1, tmp1, r);
277 */
278  //mpfr_clears(a, b, f, L, U1, U2, sinU1, sinU2, cosU1, cosU2, lambda, lambdaP, sinLambda, cosLambda, sigma, sinSigma, cosSigma, sinAlpha, cosSqAlpha, cos2SigmaM, C, dLambda, lambdaC, (mpfr_ptr)NULL);
279  //mpfr_clears(tmp1, tmp2, tmp3, tmp4, (mpfr_ptr)NULL);
280  mpfr_clears(a, b, f, fInv, L, U1, U2, sinU1, sinU2, cosU1, cosU2, lambda, lambdaP, sinLambda, cosLambda, sigma, sinSigma, cosSigma, sinAlpha, cosSqAlpha, cos2SigmaM, C, dLambda, lambdaC, uSq, k1, A, B, deltaSigma, (mpfr_ptr)NULL);
281  mpfr_clears(part1, tmp1, tmp2, tmp3, tmp4, (mpfr_ptr)NULL);
282 
283  return 0;
284 }
285 
286 long double calculate_distance(lat_t lat1_deg, lng_t lng1_deg, alt_t ele1_in, lat_t lat2_deg, lng_t lng2_deg, alt_t ele2_in)
287 {
288  mpfr_rnd_t rnd = MPFR_RNDN; /* round to nearest */
289  mpfr_prec_t prec = MAX(_MPFR_DEFAULT_PREC, 32); /* minimal a precision from 32 bits */
290 
291  mpfr_t ans, lat1, lng1, ele1, lat2, lng2, ele2, lat_start, lat_end, lng_start, lng_end;
292  mpfr_inits2(prec, ans, lat1, lng1, ele1, lat2, lng2, ele2, lat_start, lat_end, lng_start, lng_end, (mpfr_ptr)NULL);
293 
294  mpfr_set_default_prec(prec);
295 
296  /* save the parameters as mpfr variables */
297  mpfr_set_d(lat_start, lat1_deg, rnd);
298  mpfr_set_d(lng_start, lng1_deg, rnd);
299  mpfr_set_d(ele1, ele1_in, rnd);
300  mpfr_set_d(lat_end, lat2_deg, rnd);
301  mpfr_set_d(lng_end, lng2_deg, rnd);
302  mpfr_set_d(ele2, ele2_in, rnd);
303 
304  deg_to_rad_mpfr(lat1, lat_start, rnd);
305  deg_to_rad_mpfr(lat2, lat_end, rnd);
306  deg_to_rad_mpfr(lng1, lng_start, rnd);
307  deg_to_rad_mpfr(lng2, lng_end, rnd);
308  //mpfr_printf("point 1\nlat: %.10Rf\nlng: %.10Rf\npoint 2\nlat: %.10Rf\nlng: %.10Rf\n", lat1, lng1, lat2, lng2);
309 
310  /* if NaN (not a number is returned, double the precision and calculate again. */
311  for(prec = _MPFR_DEFAULT_PREC; (mpfr_nan_p(ans) != 0) && (prec < (MPFR_PREC_MAX / 4)); prec *= 2)
312  {
313  //printf("1\n");
314  mpfr_set_nan(ans); /* set ans2 back to NaN for sanity */
315  if(VincentyDistance_mpfr(ans, lat1, lng1, lat2, lng2, prec, rnd) == -1)
316  return 0;
317  //mpfr_printf("ans: %Rf\n", ans);
318  }
319 
320  /* use pythagoras to calculate the length on a slope */
321  mpfr_t ans_real, dAlt, tmp1, tmp2, tmp3;
322  mpfr_inits2(prec, ans_real, dAlt, tmp1, tmp2, tmp3, (mpfr_ptr)NULL);
323  mpfr_sub(dAlt, ele1, ele2, rnd);
324  mpfr_sqr(tmp1, dAlt, rnd);
325  mpfr_sqr(tmp2, ans, rnd);
326  mpfr_add(tmp3, tmp1, tmp2, rnd);
327  mpfr_sqrt(ans_real, tmp3, rnd);
328 /*
329  mpfr_printf("c^2 = a^2 + b^2\n");
330  mpfr_printf("c^2 = %Rf^2 + %Rf^2\n", ans, dAlt);
331  mpfr_printf("c^2 = %Rf + %Rf\n", tmp2, tmp1);
332  mpfr_printf("c^2 = %Rf\n", tmp3);
333  mpfr_printf("c = %Rf\n", ans_real);
334 */
335  mpfr_clears(dAlt, tmp1, tmp2, tmp3, (mpfr_ptr)NULL);
336 
337  mpfr_clears(lat1, lng1, ele1, lat2, lng2, ele2, (mpfr_ptr)NULL);
338  /* save the answer in a normal variable */
339  long double res = mpfr_get_ld(ans_real, rnd);
340 
341  mpfr_clears(ans, ans_real, (mpfr_ptr)NULL);
342  mpfr_free_cache();
343 
344  /* return the answer */
345  return res;
346 }
347 
348 float calculate_incline(long double dst, alt_t d_ele)
349 {
350  mpfr_rnd_t rnd = MPFR_RNDN; /* round to nearest */
351  mpfr_prec_t prec = MAX(_MPFR_DEFAULT_PREC, 32); /* minimal a precision from 32 bits */
352 
353  mpfr_t ans, e, d, tmp1;
354  mpfr_inits2(prec, ans, e, d, tmp1, (mpfr_ptr)NULL);
355 
356  mpfr_set_default_prec(prec);
357 
358  mpfr_set_ld(d, dst, rnd);
359  mpfr_set_d(e, d_ele, rnd);
360 
361  // tan(asin(ele / dst))
362  mpfr_div(tmp1, e, d, rnd);
363  mpfr_asin(tmp1, tmp1, rnd);
364  mpfr_tan(ans, tmp1, rnd);
365  float res = mpfr_get_d(ans, rnd);
366 
367  mpfr_clears(ans, e, d, tmp1, (mpfr_ptr)NULL);
368  mpfr_free_cache();
369 
370  return res;
371 }
372 
373 #else /* USE_MPFR */
374 
375 #define FORMULA_DOUBLE
376 
377 #include <stdlib.h>
378 #include <math.h>
379 
380 #define f ((long double)(1/(long double)298.257223563))
381 #define a ((long double)6378137.0)
382 #define PI ((long double)(M_PI))
383 
384 long double calculate_distance(lat_t lat1_deg, lng_t lng1_deg, alt_t ele1, lat_t lat2_deg, lng_t lng2_deg, alt_t ele2)
385 {
386  long double lat1, lat2, lng1, lng2;
387  lat1 = (long double)lat1_deg / 180 * PI;
388  lng1 = (long double)lng1_deg / 180 * PI;
389  lat2 = (long double)lat2_deg / 180 * PI;
390  lng2 = (long double)lng2_deg / 180 * PI;
391  long double b, lambda, L, U1, U2, cosU1, cosU2, sinU1, sinU2, sinLambda, cosLambda, sinSigma, cosSigma, sigma, sinAlpha, cosSqAlpha, cos2SigmaM, C, uSq, k1, A, B, deltaSigma, res;
392  b = a * (1 - f);
393  lambda = L = lng2 - lng1;
394  U1 = atan((1 - f) * tan(lat1));
395  U2 = atan((1 - f) * tan(lat2));
396  cosU1 = cos(U1);
397  cosU2 = cos(U2);
398  sinU1 = sin(U1);
399  sinU2 = sin(U2);
400  long double lambda_prev;
401  int iterLimit = MAX_NUMBER_ITERATIONS;
402  do
403  {
404  lambda_prev = lambda;
405  sinLambda = sin(lambda);
406  cosLambda = cos(lambda);
407  sinSigma = sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda) + (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
408  //sinSigma = sqrt(tmp1 + tmp2);
409  //if(mpfr_nan_p(sinSigma) != 0 || mpfr_zero_p(sinSigma) != 0 || mpfr_cmp_ui(sinSigma, 0) == 0) return 0; // co-incident points
410  cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;
411  sigma = atan2(sinSigma, cosSigma);
412  sinAlpha = cosU1 * cosU2 * sinLambda / sinSigma;
413  cosSqAlpha = 1 - sinAlpha * sinAlpha;
414  cos2SigmaM = cosSigma - 2 * sinU1 * sinU2 / cosSqAlpha;
415  //if(if(mpfr_nan_p(cos2SigmaM) != 0) mpfr_set_ui(cos2SigmaM, 0, r); // equatorial line: cosSqAlpha=0
416  C = f / 16 * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha));
417  lambda = L + (1 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));
418  }
419  while(abs(lambda - lambda_prev) > (long double)1e-24 && (--iterLimit > 0));
420 
421  uSq = cosSqAlpha * (a * a - b * b) / (b * b);
422  k1 = (sqrt(1 + uSq) - 1) / (sqrt(1 + uSq) + 1);
423  A = (1 + 0.25 * k1 * k1) / (1 - k1);
424  B = k1 * (1 - 3/8 * k1 * k1);
425  deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) - B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));
426  res = b * A * (sigma - deltaSigma);
427 
428  /* calculate heading
429  heading_start = atan2((cosU2 * sinLambda) / (cosU1 * sinU2 - sinU1 * cosU2 * cosLambda));
430  heading_end = atan2((cosU1 * sinLambda) / (-sinU1 * cosU2 + cosU1 * sinU2 * cosLambda));
431  */
432 
433  double res_real = (double)sqrt(pow((long double)ele1 - (long double)ele2, 2) + pow(res, 2));
434  return res_real;
435 }
436 
437 float calculate_incline(long double dst, alt_t d_ele)
438 {
439  return (float)tan(asin((long double)d_ele / dst));
440 }
441 
442 #undef f
443 #undef a
444 #undef b
445 
446 #endif /* USE_MPFR */
double alt_t
Definition: gpstypes.h:10
float calculate_incline(long double dst, alt_t d_ele)
#define a
#define PI
double lat_t
Definition: gpstypes.h:8
long double calculate_distance(lat_t lat1_deg, lng_t lng1_deg, alt_t ele1, lat_t lat2_deg, lng_t lng2_deg, alt_t ele2)
#define MAX(a, b)
#define MAX_NUMBER_ITERATIONS
double lng_t
Definition: gpstypes.h:9
#define f