geodesic.c
Go to the documentation of this file.
1 
10 /*
11  * This is a C implementation of the geodesic algorithms described in
12  *
13  * C. F. F. Karney,
14  * Algorithms for geodesics,
15  * J. Geodesy <b>87</b>, 43--55 (2013);
16  * https://doi.org/10.1007/s00190-012-0578-z
17  * Addenda: https://geographiclib.sourceforge.io/geod-addenda.html
18  *
19  * See the comments in geodesic.h for documentation.
20  *
21  * Copyright (c) Charles Karney (2012-2017) <charles@karney.com> and licensed
22  * under the MIT/X11 License. For more information, see
23  * https://geographiclib.sourceforge.io/
24  */
25 
26 #include "geodesic.h"
27 #include <math.h>
28 
29 #if !defined(HAVE_C99_MATH)
30 #define HAVE_C99_MATH 0
31 #endif
32 
33 #define GEOGRAPHICLIB_GEODESIC_ORDER 6
34 #define nA1 GEOGRAPHICLIB_GEODESIC_ORDER
35 #define nC1 GEOGRAPHICLIB_GEODESIC_ORDER
36 #define nC1p GEOGRAPHICLIB_GEODESIC_ORDER
37 #define nA2 GEOGRAPHICLIB_GEODESIC_ORDER
38 #define nC2 GEOGRAPHICLIB_GEODESIC_ORDER
39 #define nA3 GEOGRAPHICLIB_GEODESIC_ORDER
40 #define nA3x nA3
41 #define nC3 GEOGRAPHICLIB_GEODESIC_ORDER
42 #define nC3x ((nC3 * (nC3 - 1)) / 2)
43 #define nC4 GEOGRAPHICLIB_GEODESIC_ORDER
44 #define nC4x ((nC4 * (nC4 + 1)) / 2)
45 #define nC (GEOGRAPHICLIB_GEODESIC_ORDER + 1)
46 
47 typedef double real;
48 typedef int boolx;
49 
50 static unsigned init = 0;
51 static const int FALSE = 0;
52 static const int TRUE = 1;
53 static unsigned digits, maxit1, maxit2;
54 static real epsilon, realmin, pi, degree, NaN,
55  tiny, tol0, tol1, tol2, tolb, xthresh;
56 
57 static void Init() {
58  if (!init) {
59 #if defined(__DBL_MANT_DIG__)
60  digits = __DBL_MANT_DIG__;
61 #else
62  digits = 53;
63 #endif
64 #if defined(__DBL_EPSILON__)
65  epsilon = __DBL_EPSILON__;
66 #else
67  epsilon = pow(0.5, digits - 1);
68 #endif
69 #if defined(__DBL_MIN__)
70  realmin = __DBL_MIN__;
71 #else
72  realmin = pow(0.5, 1022);
73 #endif
74 #if defined(M_PI)
75  pi = M_PI;
76 #else
77  pi = atan2(0.0, -1.0);
78 #endif
79  maxit1 = 20;
80  maxit2 = maxit1 + digits + 10;
81  tiny = sqrt(realmin);
82  tol0 = epsilon;
83  /* Increase multiplier in defn of tol1 from 100 to 200 to fix inverse case
84  * 52.784459512564 0 -52.784459512563990912 179.634407464943777557
85  * which otherwise failed for Visual Studio 10 (Release and Debug) */
86  tol1 = 200 * tol0;
87  tol2 = sqrt(tol0);
88  /* Check on bisection interval */
89  tolb = tol0 * tol2;
90  xthresh = 1000 * tol2;
91  degree = pi/180;
92  {
93  real minus1 = -1;
94  NaN = sqrt(minus1);
95  }
96  init = 1;
97  }
98 }
99 
100 enum captype {
101  CAP_NONE = 0U,
102  CAP_C1 = 1U<<0,
103  CAP_C1p = 1U<<1,
104  CAP_C2 = 1U<<2,
105  CAP_C3 = 1U<<3,
106  CAP_C4 = 1U<<4,
107  CAP_ALL = 0x1FU,
108  OUT_ALL = 0x7F80U
109 };
110 
111 static real sq(real x) { return x * x; }
112 #if HAVE_C99_MATH
113 #define atanhx atanh
114 #define copysignx copysign
115 #define hypotx hypot
116 #define cbrtx cbrt
117 #else
118 static real log1px(real x) {
119  volatile real
120  y = 1 + x,
121  z = y - 1;
122  /* Here's the explanation for this magic: y = 1 + z, exactly, and z
123  * approx x, thus log(y)/z (which is nearly constant near z = 0) returns
124  * a good approximation to the true log(1 + x)/x. The multiplication x *
125  * (log(y)/z) introduces little additional error. */
126  return z == 0 ? x : x * log(y) / z;
127 }
128 
129 static real atanhx(real x) {
130  real y = fabs(x); /* Enforce odd parity */
131  y = log1px(2 * y/(1 - y))/2;
132  return x < 0 ? -y : y;
133 }
134 
135 static real copysignx(real x, real y) {
136  return fabs(x) * (y < 0 || (y == 0 && 1/y < 0) ? -1 : 1);
137 }
138 
139 static real hypotx(real x, real y)
140 { return sqrt(x * x + y * y); }
141 
142 static real cbrtx(real x) {
143  real y = pow(fabs(x), 1/(real)(3)); /* Return the real cube root */
144  return x < 0 ? -y : y;
145 }
146 #endif
147 
148 static real sumx(real u, real v, real* t) {
149  volatile real s = u + v;
150  volatile real up = s - v;
151  volatile real vpp = s - up;
152  up -= u;
153  vpp -= v;
154  if (t) *t = -(up + vpp);
155  /* error-free sum:
156  * u + v = s + t
157  * = round(u + v) + t */
158  return s;
159 }
160 
161 static real polyval(int N, const real p[], real x) {
162  real y = N < 0 ? 0 : *p++;
163  while (--N >= 0) y = y * x + *p++;
164  return y;
165 }
166 
167 /* mimic C++ std::min and std::max */
168 static real minx(real a, real b)
169 { return (b < a) ? b : a; }
170 
171 static real maxx(real a, real b)
172 { return (a < b) ? b : a; }
173 
174 static void swapx(real* x, real* y)
175 { real t = *x; *x = *y; *y = t; }
176 
177 static void norm2(real* sinx, real* cosx) {
178  real r = hypotx(*sinx, *cosx);
179  *sinx /= r;
180  *cosx /= r;
181 }
182 
183 static real AngNormalize(real x) {
184 #if HAVE_C99_MATH
185  x = remainder(x, (real)(360));
186  return x != -180 ? x : 180;
187 #else
188  x = fmod(x, (real)(360));
189  return x <= -180 ? x + 360 : (x <= 180 ? x : x - 360);
190 #endif
191 }
192 
193 static real LatFix(real x)
194 { return fabs(x) > 90 ? NaN : x; }
195 
196 static real AngDiff(real x, real y, real* e) {
197  real t, d = AngNormalize(sumx(AngNormalize(-x), AngNormalize(y), &t));
198  /* Here y - x = d + t (mod 360), exactly, where d is in (-180,180] and
199  * abs(t) <= eps (eps = 2^-45 for doubles). The only case where the
200  * addition of t takes the result outside the range (-180,180] is d = 180
201  * and t > 0. The case, d = -180 + eps, t = -eps, can't happen, since
202  * sum would have returned the exact result in such a case (i.e., given t
203  * = 0). */
204  return sumx(d == 180 && t > 0 ? -180 : d, t, e);
205 }
206 
207 static real AngRound(real x) {
208  const real z = 1/(real)(16);
209  volatile real y;
210  if (x == 0) return 0;
211  y = fabs(x);
212  /* The compiler mustn't "simplify" z - (z - y) to y */
213  y = y < z ? z - (z - y) : y;
214  return x < 0 ? -y : y;
215 }
216 
217 static void sincosdx(real x, real* sinx, real* cosx) {
218  /* In order to minimize round-off errors, this function exactly reduces
219  * the argument to the range [-45, 45] before converting it to radians. */
220  real r, s, c; int q;
221 #if HAVE_C99_MATH && !defined(__GNUC__)
222  /* Disable for gcc because of bug in glibc version < 2.22, see
223  * https://sourceware.org/bugzilla/show_bug.cgi?id=17569 */
224  r = remquo(x, (real)(90), &q);
225 #else
226  r = fmod(x, (real)(360));
227  q = (int)(floor(r / 90 + (real)(0.5)));
228  r -= 90 * q;
229 #endif
230  /* now abs(r) <= 45 */
231  r *= degree;
232  /* Possibly could call the gnu extension sincos */
233  s = sin(r); c = cos(r);
234  switch ((unsigned)q & 3U) {
235  case 0U: *sinx = s; *cosx = c; break;
236  case 1U: *sinx = c; *cosx = -s; break;
237  case 2U: *sinx = -s; *cosx = -c; break;
238  default: *sinx = -c; *cosx = s; break; /* case 3U */
239  }
240  if (x != 0) { *sinx += (real)(0); *cosx += (real)(0); }
241 }
242 
243 static real atan2dx(real y, real x) {
244  /* In order to minimize round-off errors, this function rearranges the
245  * arguments so that result of atan2 is in the range [-pi/4, pi/4] before
246  * converting it to degrees and mapping the result to the correct
247  * quadrant. */
248  int q = 0; real ang;
249  if (fabs(y) > fabs(x)) { swapx(&x, &y); q = 2; }
250  if (x < 0) { x = -x; ++q; }
251  /* here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4] */
252  ang = atan2(y, x) / degree;
253  switch (q) {
254  /* Note that atan2d(-0.0, 1.0) will return -0. However, we expect that
255  * atan2d will not be called with y = -0. If need be, include
256  *
257  * case 0: ang = 0 + ang; break;
258  */
259  case 1: ang = (y >= 0 ? 180 : -180) - ang; break;
260  case 2: ang = 90 - ang; break;
261  case 3: ang = -90 + ang; break;
262  }
263  return ang;
264 }
265 
266 static void A3coeff(struct geod_geodesic* g);
267 static void C3coeff(struct geod_geodesic* g);
268 static void C4coeff(struct geod_geodesic* g);
269 static real SinCosSeries(boolx sinp,
270  real sinx, real cosx,
271  const real c[], int n);
272 static void Lengths(const struct geod_geodesic* g,
273  real eps, real sig12,
274  real ssig1, real csig1, real dn1,
275  real ssig2, real csig2, real dn2,
276  real cbet1, real cbet2,
277  real* ps12b, real* pm12b, real* pm0,
278  real* pM12, real* pM21,
279  /* Scratch area of the right size */
280  real Ca[]);
281 static real Astroid(real x, real y);
282 static real InverseStart(const struct geod_geodesic* g,
283  real sbet1, real cbet1, real dn1,
284  real sbet2, real cbet2, real dn2,
285  real lam12, real slam12, real clam12,
286  real* psalp1, real* pcalp1,
287  /* Only updated if return val >= 0 */
288  real* psalp2, real* pcalp2,
289  /* Only updated for short lines */
290  real* pdnm,
291  /* Scratch area of the right size */
292  real Ca[]);
293 static real Lambda12(const struct geod_geodesic* g,
294  real sbet1, real cbet1, real dn1,
295  real sbet2, real cbet2, real dn2,
296  real salp1, real calp1,
297  real slam120, real clam120,
298  real* psalp2, real* pcalp2,
299  real* psig12,
300  real* pssig1, real* pcsig1,
301  real* pssig2, real* pcsig2,
302  real* peps,
303  real* pgomg12,
304  boolx diffp, real* pdlam12,
305  /* Scratch area of the right size */
306  real Ca[]);
307 static real A3f(const struct geod_geodesic* g, real eps);
308 static void C3f(const struct geod_geodesic* g, real eps, real c[]);
309 static void C4f(const struct geod_geodesic* g, real eps, real c[]);
310 static real A1m1f(real eps);
311 static void C1f(real eps, real c[]);
312 static void C1pf(real eps, real c[]);
313 static real A2m1f(real eps);
314 static void C2f(real eps, real c[]);
315 static int transit(real lon1, real lon2);
316 static int transitdirect(real lon1, real lon2);
317 static void accini(real s[]);
318 static void acccopy(const real s[], real t[]);
319 static void accadd(real s[], real y);
320 static real accsum(const real s[], real y);
321 static void accneg(real s[]);
322 
323 void geod_init(struct geod_geodesic* g, real a, real f) {
324  if (!init) Init();
325  g->a = a;
326  g->f = f;
327  g->f1 = 1 - g->f;
328  g->e2 = g->f * (2 - g->f);
329  g->ep2 = g->e2 / sq(g->f1); /* e2 / (1 - e2) */
330  g->n = g->f / ( 2 - g->f);
331  g->b = g->a * g->f1;
332  g->c2 = (sq(g->a) + sq(g->b) *
333  (g->e2 == 0 ? 1 :
334  (g->e2 > 0 ? atanhx(sqrt(g->e2)) : atan(sqrt(-g->e2))) /
335  sqrt(fabs(g->e2))))/2; /* authalic radius squared */
336  /* The sig12 threshold for "really short". Using the auxiliary sphere
337  * solution with dnm computed at (bet1 + bet2) / 2, the relative error in the
338  * azimuth consistency check is sig12^2 * abs(f) * min(1, 1-f/2) / 2. (Error
339  * measured for 1/100 < b/a < 100 and abs(f) >= 1/1000. For a given f and
340  * sig12, the max error occurs for lines near the pole. If the old rule for
341  * computing dnm = (dn1 + dn2)/2 is used, then the error increases by a
342  * factor of 2.) Setting this equal to epsilon gives sig12 = etol2. Here
343  * 0.1 is a safety factor (error decreased by 100) and max(0.001, abs(f))
344  * stops etol2 getting too large in the nearly spherical case. */
345  g->etol2 = 0.1 * tol2 /
346  sqrt( maxx((real)(0.001), fabs(g->f)) * minx((real)(1), 1 - g->f/2) / 2 );
347 
348  A3coeff(g);
349  C3coeff(g);
350  C4coeff(g);
351 }
352 
353 static void geod_lineinit_int(struct geod_geodesicline* l,
354  const struct geod_geodesic* g,
355  real lat1, real lon1,
356  real azi1, real salp1, real calp1,
357  unsigned caps) {
358  real cbet1, sbet1, eps;
359  l->a = g->a;
360  l->f = g->f;
361  l->b = g->b;
362  l->c2 = g->c2;
363  l->f1 = g->f1;
364  /* If caps is 0 assume the standard direct calculation */
365  l->caps = (caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE) |
366  /* always allow latitude and azimuth and unrolling of longitude */
368 
369  l->lat1 = LatFix(lat1);
370  l->lon1 = lon1;
371  l->azi1 = azi1;
372  l->salp1 = salp1;
373  l->calp1 = calp1;
374 
375  sincosdx(AngRound(l->lat1), &sbet1, &cbet1); sbet1 *= l->f1;
376  /* Ensure cbet1 = +epsilon at poles */
377  norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
378  l->dn1 = sqrt(1 + g->ep2 * sq(sbet1));
379 
380  /* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), */
381  l->salp0 = l->salp1 * cbet1; /* alp0 in [0, pi/2 - |bet1|] */
382  /* Alt: calp0 = hypot(sbet1, calp1 * cbet1). The following
383  * is slightly better (consider the case salp1 = 0). */
384  l->calp0 = hypotx(l->calp1, l->salp1 * sbet1);
385  /* Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
386  * sig = 0 is nearest northward crossing of equator.
387  * With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
388  * With bet1 = pi/2, alp1 = -pi, sig1 = pi/2
389  * With bet1 = -pi/2, alp1 = 0 , sig1 = -pi/2
390  * Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
391  * With alp0 in (0, pi/2], quadrants for sig and omg coincide.
392  * No atan2(0,0) ambiguity at poles since cbet1 = +epsilon.
393  * With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi. */
394  l->ssig1 = sbet1; l->somg1 = l->salp0 * sbet1;
395  l->csig1 = l->comg1 = sbet1 != 0 || l->calp1 != 0 ? cbet1 * l->calp1 : 1;
396  norm2(&l->ssig1, &l->csig1); /* sig1 in (-pi, pi] */
397  /* norm2(somg1, comg1); -- don't need to normalize! */
398 
399  l->k2 = sq(l->calp0) * g->ep2;
400  eps = l->k2 / (2 * (1 + sqrt(1 + l->k2)) + l->k2);
401 
402  if (l->caps & CAP_C1) {
403  real s, c;
404  l->A1m1 = A1m1f(eps);
405  C1f(eps, l->C1a);
406  l->B11 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C1a, nC1);
407  s = sin(l->B11); c = cos(l->B11);
408  /* tau1 = sig1 + B11 */
409  l->stau1 = l->ssig1 * c + l->csig1 * s;
410  l->ctau1 = l->csig1 * c - l->ssig1 * s;
411  /* Not necessary because C1pa reverts C1a
412  * B11 = -SinCosSeries(TRUE, stau1, ctau1, C1pa, nC1p); */
413  }
414 
415  if (l->caps & CAP_C1p)
416  C1pf(eps, l->C1pa);
417 
418  if (l->caps & CAP_C2) {
419  l->A2m1 = A2m1f(eps);
420  C2f(eps, l->C2a);
421  l->B21 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C2a, nC2);
422  }
423 
424  if (l->caps & CAP_C3) {
425  C3f(g, eps, l->C3a);
426  l->A3c = -l->f * l->salp0 * A3f(g, eps);
427  l->B31 = SinCosSeries(TRUE, l->ssig1, l->csig1, l->C3a, nC3-1);
428  }
429 
430  if (l->caps & CAP_C4) {
431  C4f(g, eps, l->C4a);
432  /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0) */
433  l->A4 = sq(l->a) * l->calp0 * l->salp0 * g->e2;
434  l->B41 = SinCosSeries(FALSE, l->ssig1, l->csig1, l->C4a, nC4);
435  }
436 
437  l->a13 = l->s13 = NaN;
438 }
439 
440 void geod_lineinit(struct geod_geodesicline* l,
441  const struct geod_geodesic* g,
442  real lat1, real lon1, real azi1, unsigned caps) {
443  real salp1, calp1;
444  azi1 = AngNormalize(azi1);
445  /* Guard against underflow in salp0 */
446  sincosdx(AngRound(azi1), &salp1, &calp1);
447  geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps);
448 }
449 
451  const struct geod_geodesic* g,
452  real lat1, real lon1, real azi1,
453  unsigned flags, real a12_s12,
454  unsigned caps) {
455  geod_lineinit(l, g, lat1, lon1, azi1, caps);
456  geod_gensetdistance(l, flags, a12_s12);
457 }
458 
459 void geod_directline(struct geod_geodesicline* l,
460  const struct geod_geodesic* g,
461  real lat1, real lon1, real azi1,
462  real s12, unsigned caps) {
463  geod_gendirectline(l, g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, caps);
464 }
465 
466 real geod_genposition(const struct geod_geodesicline* l,
467  unsigned flags, real s12_a12,
468  real* plat2, real* plon2, real* pazi2,
469  real* ps12, real* pm12,
470  real* pM12, real* pM21,
471  real* pS12) {
472  real lat2 = 0, lon2 = 0, azi2 = 0, s12 = 0,
473  m12 = 0, M12 = 0, M21 = 0, S12 = 0;
474  /* Avoid warning about uninitialized B12. */
475  real sig12, ssig12, csig12, B12 = 0, AB1 = 0;
476  real omg12, lam12, lon12;
477  real ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2, dn2;
478  unsigned outmask =
479  (plat2 ? GEOD_LATITUDE : 0U) |
480  (plon2 ? GEOD_LONGITUDE : 0U) |
481  (pazi2 ? GEOD_AZIMUTH : 0U) |
482  (ps12 ? GEOD_DISTANCE : 0U) |
483  (pm12 ? GEOD_REDUCEDLENGTH : 0U) |
484  (pM12 || pM21 ? GEOD_GEODESICSCALE : 0U) |
485  (pS12 ? GEOD_AREA : 0U);
486 
487  outmask &= l->caps & OUT_ALL;
488  if (!( TRUE /*Init()*/ &&
489  (flags & GEOD_ARCMODE || (l->caps & (GEOD_DISTANCE_IN & OUT_ALL))) ))
490  /* Uninitialized or impossible distance calculation requested */
491  return NaN;
492 
493  if (flags & GEOD_ARCMODE) {
494  /* Interpret s12_a12 as spherical arc length */
495  sig12 = s12_a12 * degree;
496  sincosdx(s12_a12, &ssig12, &csig12);
497  } else {
498  /* Interpret s12_a12 as distance */
499  real
500  tau12 = s12_a12 / (l->b * (1 + l->A1m1)),
501  s = sin(tau12),
502  c = cos(tau12);
503  /* tau2 = tau1 + tau12 */
504  B12 = - SinCosSeries(TRUE,
505  l->stau1 * c + l->ctau1 * s,
506  l->ctau1 * c - l->stau1 * s,
507  l->C1pa, nC1p);
508  sig12 = tau12 - (B12 - l->B11);
509  ssig12 = sin(sig12); csig12 = cos(sig12);
510  if (fabs(l->f) > 0.01) {
511  /* Reverted distance series is inaccurate for |f| > 1/100, so correct
512  * sig12 with 1 Newton iteration. The following table shows the
513  * approximate maximum error for a = WGS_a() and various f relative to
514  * GeodesicExact.
515  * erri = the error in the inverse solution (nm)
516  * errd = the error in the direct solution (series only) (nm)
517  * errda = the error in the direct solution (series + 1 Newton) (nm)
518  *
519  * f erri errd errda
520  * -1/5 12e6 1.2e9 69e6
521  * -1/10 123e3 12e6 765e3
522  * -1/20 1110 108e3 7155
523  * -1/50 18.63 200.9 27.12
524  * -1/100 18.63 23.78 23.37
525  * -1/150 18.63 21.05 20.26
526  * 1/150 22.35 24.73 25.83
527  * 1/100 22.35 25.03 25.31
528  * 1/50 29.80 231.9 30.44
529  * 1/20 5376 146e3 10e3
530  * 1/10 829e3 22e6 1.5e6
531  * 1/5 157e6 3.8e9 280e6 */
532  real serr;
533  ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12;
534  csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
535  B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1);
536  serr = (1 + l->A1m1) * (sig12 + (B12 - l->B11)) - s12_a12 / l->b;
537  sig12 = sig12 - serr / sqrt(1 + l->k2 * sq(ssig2));
538  ssig12 = sin(sig12); csig12 = cos(sig12);
539  /* Update B12 below */
540  }
541  }
542 
543  /* sig2 = sig1 + sig12 */
544  ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12;
545  csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
546  dn2 = sqrt(1 + l->k2 * sq(ssig2));
548  if (flags & GEOD_ARCMODE || fabs(l->f) > 0.01)
549  B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1);
550  AB1 = (1 + l->A1m1) * (B12 - l->B11);
551  }
552  /* sin(bet2) = cos(alp0) * sin(sig2) */
553  sbet2 = l->calp0 * ssig2;
554  /* Alt: cbet2 = hypot(csig2, salp0 * ssig2); */
555  cbet2 = hypotx(l->salp0, l->calp0 * csig2);
556  if (cbet2 == 0)
557  /* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case */
558  cbet2 = csig2 = tiny;
559  /* tan(alp0) = cos(sig2)*tan(alp2) */
560  salp2 = l->salp0; calp2 = l->calp0 * csig2; /* No need to normalize */
561 
562  if (outmask & GEOD_DISTANCE)
563  s12 = flags & GEOD_ARCMODE ?
564  l->b * ((1 + l->A1m1) * sig12 + AB1) :
565  s12_a12;
566 
567  if (outmask & GEOD_LONGITUDE) {
568  real E = copysignx(1, l->salp0); /* east or west going? */
569  /* tan(omg2) = sin(alp0) * tan(sig2) */
570  somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */
571  /* omg12 = omg2 - omg1 */
572  omg12 = flags & GEOD_LONG_UNROLL
573  ? E * (sig12
574  - (atan2( ssig2, csig2) - atan2( l->ssig1, l->csig1))
575  + (atan2(E * somg2, comg2) - atan2(E * l->somg1, l->comg1)))
576  : atan2(somg2 * l->comg1 - comg2 * l->somg1,
577  comg2 * l->comg1 + somg2 * l->somg1);
578  lam12 = omg12 + l->A3c *
579  ( sig12 + (SinCosSeries(TRUE, ssig2, csig2, l->C3a, nC3-1)
580  - l->B31));
581  lon12 = lam12 / degree;
582  lon2 = flags & GEOD_LONG_UNROLL ? l->lon1 + lon12 :
583  AngNormalize(AngNormalize(l->lon1) + AngNormalize(lon12));
584  }
585 
586  if (outmask & GEOD_LATITUDE)
587  lat2 = atan2dx(sbet2, l->f1 * cbet2);
588 
589  if (outmask & GEOD_AZIMUTH)
590  azi2 = atan2dx(salp2, calp2);
591 
592  if (outmask & (GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) {
593  real
594  B22 = SinCosSeries(TRUE, ssig2, csig2, l->C2a, nC2),
595  AB2 = (1 + l->A2m1) * (B22 - l->B21),
596  J12 = (l->A1m1 - l->A2m1) * sig12 + (AB1 - AB2);
597  if (outmask & GEOD_REDUCEDLENGTH)
598  /* Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
599  * accurate cancellation in the case of coincident points. */
600  m12 = l->b * ((dn2 * (l->csig1 * ssig2) - l->dn1 * (l->ssig1 * csig2))
601  - l->csig1 * csig2 * J12);
602  if (outmask & GEOD_GEODESICSCALE) {
603  real t = l->k2 * (ssig2 - l->ssig1) * (ssig2 + l->ssig1) /
604  (l->dn1 + dn2);
605  M12 = csig12 + (t * ssig2 - csig2 * J12) * l->ssig1 / l->dn1;
606  M21 = csig12 - (t * l->ssig1 - l->csig1 * J12) * ssig2 / dn2;
607  }
608  }
609 
610  if (outmask & GEOD_AREA) {
611  real
612  B42 = SinCosSeries(FALSE, ssig2, csig2, l->C4a, nC4);
613  real salp12, calp12;
614  if (l->calp0 == 0 || l->salp0 == 0) {
615  /* alp12 = alp2 - alp1, used in atan2 so no need to normalize */
616  salp12 = salp2 * l->calp1 - calp2 * l->salp1;
617  calp12 = calp2 * l->calp1 + salp2 * l->salp1;
618  } else {
619  /* tan(alp) = tan(alp0) * sec(sig)
620  * tan(alp2-alp1) = (tan(alp2) -tan(alp1)) / (tan(alp2)*tan(alp1)+1)
621  * = calp0 * salp0 * (csig1-csig2) / (salp0^2 + calp0^2 * csig1*csig2)
622  * If csig12 > 0, write
623  * csig1 - csig2 = ssig12 * (csig1 * ssig12 / (1 + csig12) + ssig1)
624  * else
625  * csig1 - csig2 = csig1 * (1 - csig12) + ssig12 * ssig1
626  * No need to normalize */
627  salp12 = l->calp0 * l->salp0 *
628  (csig12 <= 0 ? l->csig1 * (1 - csig12) + ssig12 * l->ssig1 :
629  ssig12 * (l->csig1 * ssig12 / (1 + csig12) + l->ssig1));
630  calp12 = sq(l->salp0) + sq(l->calp0) * l->csig1 * csig2;
631  }
632  S12 = l->c2 * atan2(salp12, calp12) + l->A4 * (B42 - l->B41);
633  }
634 
635  if (outmask & GEOD_LATITUDE)
636  *plat2 = lat2;
637  if (outmask & GEOD_LONGITUDE)
638  *plon2 = lon2;
639  if (outmask & GEOD_AZIMUTH)
640  *pazi2 = azi2;
641  if (outmask & GEOD_DISTANCE)
642  *ps12 = s12;
643  if (outmask & GEOD_REDUCEDLENGTH)
644  *pm12 = m12;
645  if (outmask & GEOD_GEODESICSCALE) {
646  if (pM12) *pM12 = M12;
647  if (pM21) *pM21 = M21;
648  }
649  if (outmask & GEOD_AREA)
650  *pS12 = S12;
651 
652  return flags & GEOD_ARCMODE ? s12_a12 : sig12 / degree;
653 }
654 
655 void geod_setdistance(struct geod_geodesicline* l, real s13) {
656  l->s13 = s13;
657  l->a13 = geod_genposition(l, GEOD_NOFLAGS, l->s13, 0, 0, 0, 0, 0, 0, 0, 0);
658 }
659 
660 static void geod_setarc(struct geod_geodesicline* l, real a13) {
661  l->a13 = a13; l->s13 = NaN;
662  geod_genposition(l, GEOD_ARCMODE, l->a13, 0, 0, 0, &l->s13, 0, 0, 0, 0);
663 }
664 
666  unsigned flags, real s13_a13) {
667  flags & GEOD_ARCMODE ?
668  geod_setarc(l, s13_a13) :
669  geod_setdistance(l, s13_a13);
670 }
671 
672 void geod_position(const struct geod_geodesicline* l, real s12,
673  real* plat2, real* plon2, real* pazi2) {
674  geod_genposition(l, FALSE, s12, plat2, plon2, pazi2, 0, 0, 0, 0, 0);
675 }
676 
677 real geod_gendirect(const struct geod_geodesic* g,
678  real lat1, real lon1, real azi1,
679  unsigned flags, real s12_a12,
680  real* plat2, real* plon2, real* pazi2,
681  real* ps12, real* pm12, real* pM12, real* pM21,
682  real* pS12) {
683  struct geod_geodesicline l;
684  unsigned outmask =
685  (plat2 ? GEOD_LATITUDE : 0U) |
686  (plon2 ? GEOD_LONGITUDE : 0U) |
687  (pazi2 ? GEOD_AZIMUTH : 0U) |
688  (ps12 ? GEOD_DISTANCE : 0U) |
689  (pm12 ? GEOD_REDUCEDLENGTH : 0U) |
690  (pM12 || pM21 ? GEOD_GEODESICSCALE : 0U) |
691  (pS12 ? GEOD_AREA : 0U);
692 
693  geod_lineinit(&l, g, lat1, lon1, azi1,
694  /* Automatically supply GEOD_DISTANCE_IN if necessary */
695  outmask |
696  (flags & GEOD_ARCMODE ? GEOD_NONE : GEOD_DISTANCE_IN));
697  return geod_genposition(&l, flags, s12_a12,
698  plat2, plon2, pazi2, ps12, pm12, pM12, pM21, pS12);
699 }
700 
701 void geod_direct(const struct geod_geodesic* g,
702  real lat1, real lon1, real azi1,
703  real s12,
704  real* plat2, real* plon2, real* pazi2) {
705  geod_gendirect(g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, plat2, plon2, pazi2,
706  0, 0, 0, 0, 0);
707 }
708 
709 static real geod_geninverse_int(const struct geod_geodesic* g,
710  real lat1, real lon1, real lat2, real lon2,
711  real* ps12,
712  real* psalp1, real* pcalp1,
713  real* psalp2, real* pcalp2,
714  real* pm12, real* pM12, real* pM21,
715  real* pS12) {
716  real s12 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0;
717  real lon12, lon12s;
718  int latsign, lonsign, swapp;
719  real sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
720  real dn1, dn2, lam12, slam12, clam12;
721  real a12 = 0, sig12, calp1 = 0, salp1 = 0, calp2 = 0, salp2 = 0;
722  real Ca[nC];
723  boolx meridian;
724  /* somg12 > 1 marks that it needs to be calculated */
725  real omg12 = 0, somg12 = 2, comg12 = 0;
726 
727  unsigned outmask =
728  (ps12 ? GEOD_DISTANCE : 0U) |
729  (pm12 ? GEOD_REDUCEDLENGTH : 0U) |
730  (pM12 || pM21 ? GEOD_GEODESICSCALE : 0U) |
731  (pS12 ? GEOD_AREA : 0U);
732 
733  outmask &= OUT_ALL;
734  /* Compute longitude difference (AngDiff does this carefully). Result is
735  * in [-180, 180] but -180 is only for west-going geodesics. 180 is for
736  * east-going and meridional geodesics. */
737  lon12 = AngDiff(lon1, lon2, &lon12s);
738  /* Make longitude difference positive. */
739  lonsign = lon12 >= 0 ? 1 : -1;
740  /* If very close to being on the same half-meridian, then make it so. */
741  lon12 = lonsign * AngRound(lon12);
742  lon12s = AngRound((180 - lon12) - lonsign * lon12s);
743  lam12 = lon12 * degree;
744  if (lon12 > 90) {
745  sincosdx(lon12s, &slam12, &clam12);
746  clam12 = -clam12;
747  } else
748  sincosdx(lon12, &slam12, &clam12);
749 
750  /* If really close to the equator, treat as on equator. */
751  lat1 = AngRound(LatFix(lat1));
752  lat2 = AngRound(LatFix(lat2));
753  /* Swap points so that point with higher (abs) latitude is point 1
754  * If one latitude is a nan, then it becomes lat1. */
755  swapp = fabs(lat1) < fabs(lat2) ? -1 : 1;
756  if (swapp < 0) {
757  lonsign *= -1;
758  swapx(&lat1, &lat2);
759  }
760  /* Make lat1 <= 0 */
761  latsign = lat1 < 0 ? 1 : -1;
762  lat1 *= latsign;
763  lat2 *= latsign;
764  /* Now we have
765  *
766  * 0 <= lon12 <= 180
767  * -90 <= lat1 <= 0
768  * lat1 <= lat2 <= -lat1
769  *
770  * longsign, swapp, latsign register the transformation to bring the
771  * coordinates to this canonical form. In all cases, 1 means no change was
772  * made. We make these transformations so that there are few cases to
773  * check, e.g., on verifying quadrants in atan2. In addition, this
774  * enforces some symmetries in the results returned. */
775 
776  sincosdx(lat1, &sbet1, &cbet1); sbet1 *= g->f1;
777  /* Ensure cbet1 = +epsilon at poles */
778  norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
779 
780  sincosdx(lat2, &sbet2, &cbet2); sbet2 *= g->f1;
781  /* Ensure cbet2 = +epsilon at poles */
782  norm2(&sbet2, &cbet2); cbet2 = maxx(tiny, cbet2);
783 
784  /* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
785  * |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
786  * a better measure. This logic is used in assigning calp2 in Lambda12.
787  * Sometimes these quantities vanish and in that case we force bet2 = +/-
788  * bet1 exactly. An example where is is necessary is the inverse problem
789  * 48.522876735459 0 -48.52287673545898293 179.599720456223079643
790  * which failed with Visual Studio 10 (Release and Debug) */
791 
792  if (cbet1 < -sbet1) {
793  if (cbet2 == cbet1)
794  sbet2 = sbet2 < 0 ? sbet1 : -sbet1;
795  } else {
796  if (fabs(sbet2) == -sbet1)
797  cbet2 = cbet1;
798  }
799 
800  dn1 = sqrt(1 + g->ep2 * sq(sbet1));
801  dn2 = sqrt(1 + g->ep2 * sq(sbet2));
802 
803  meridian = lat1 == -90 || slam12 == 0;
804 
805  if (meridian) {
806 
807  /* Endpoints are on a single full meridian, so the geodesic might lie on
808  * a meridian. */
809 
810  real ssig1, csig1, ssig2, csig2;
811  calp1 = clam12; salp1 = slam12; /* Head to the target longitude */
812  calp2 = 1; salp2 = 0; /* At the target we're heading north */
813 
814  /* tan(bet) = tan(sig) * cos(alp) */
815  ssig1 = sbet1; csig1 = calp1 * cbet1;
816  ssig2 = sbet2; csig2 = calp2 * cbet2;
817 
818  /* sig12 = sig2 - sig1 */
819  sig12 = atan2(maxx((real)(0), csig1 * ssig2 - ssig1 * csig2),
820  csig1 * csig2 + ssig1 * ssig2);
821  Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
822  cbet1, cbet2, &s12x, &m12x, 0,
823  outmask & GEOD_GEODESICSCALE ? &M12 : 0,
824  outmask & GEOD_GEODESICSCALE ? &M21 : 0,
825  Ca);
826  /* Add the check for sig12 since zero length geodesics might yield m12 <
827  * 0. Test case was
828  *
829  * echo 20.001 0 20.001 0 | GeodSolve -i
830  *
831  * In fact, we will have sig12 > pi/2 for meridional geodesic which is
832  * not a shortest path. */
833  if (sig12 < 1 || m12x >= 0) {
834  /* Need at least 2, to handle 90 0 90 180 */
835  if (sig12 < 3 * tiny)
836  sig12 = m12x = s12x = 0;
837  m12x *= g->b;
838  s12x *= g->b;
839  a12 = sig12 / degree;
840  } else
841  /* m12 < 0, i.e., prolate and too close to anti-podal */
842  meridian = FALSE;
843  }
844 
845  if (!meridian &&
846  sbet1 == 0 && /* and sbet2 == 0 */
847  /* Mimic the way Lambda12 works with calp1 = 0 */
848  (g->f <= 0 || lon12s >= g->f * 180)) {
849 
850  /* Geodesic runs along equator */
851  calp1 = calp2 = 0; salp1 = salp2 = 1;
852  s12x = g->a * lam12;
853  sig12 = omg12 = lam12 / g->f1;
854  m12x = g->b * sin(sig12);
855  if (outmask & GEOD_GEODESICSCALE)
856  M12 = M21 = cos(sig12);
857  a12 = lon12 / g->f1;
858 
859  } else if (!meridian) {
860 
861  /* Now point1 and point2 belong within a hemisphere bounded by a
862  * meridian and geodesic is neither meridional or equatorial. */
863 
864  /* Figure a starting point for Newton's method */
865  real dnm = 0;
866  sig12 = InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2,
867  lam12, slam12, clam12,
868  &salp1, &calp1, &salp2, &calp2, &dnm,
869  Ca);
870 
871  if (sig12 >= 0) {
872  /* Short lines (InverseStart sets salp2, calp2, dnm) */
873  s12x = sig12 * g->b * dnm;
874  m12x = sq(dnm) * g->b * sin(sig12 / dnm);
875  if (outmask & GEOD_GEODESICSCALE)
876  M12 = M21 = cos(sig12 / dnm);
877  a12 = sig12 / degree;
878  omg12 = lam12 / (g->f1 * dnm);
879  } else {
880 
881  /* Newton's method. This is a straightforward solution of f(alp1) =
882  * lambda12(alp1) - lam12 = 0 with one wrinkle. f(alp) has exactly one
883  * root in the interval (0, pi) and its derivative is positive at the
884  * root. Thus f(alp) is positive for alp > alp1 and negative for alp <
885  * alp1. During the course of the iteration, a range (alp1a, alp1b) is
886  * maintained which brackets the root and with each evaluation of
887  * f(alp) the range is shrunk, if possible. Newton's method is
888  * restarted whenever the derivative of f is negative (because the new
889  * value of alp1 is then further from the solution) or if the new
890  * estimate of alp1 lies outside (0,pi); in this case, the new starting
891  * guess is taken to be (alp1a + alp1b) / 2. */
892  real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0;
893  unsigned numit = 0;
894  /* Bracketing range */
895  real salp1a = tiny, calp1a = 1, salp1b = tiny, calp1b = -1;
896  boolx tripn, tripb;
897  for (tripn = FALSE, tripb = FALSE; numit < maxit2; ++numit) {
898  /* the WGS84 test set: mean = 1.47, sd = 1.25, max = 16
899  * WGS84 and random input: mean = 2.85, sd = 0.60 */
900  real dv = 0,
901  v = Lambda12(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
902  slam12, clam12,
903  &salp2, &calp2, &sig12, &ssig1, &csig1, &ssig2, &csig2,
904  &eps, &domg12, numit < maxit1, &dv, Ca);
905  /* 2 * tol0 is approximately 1 ulp for a number in [0, pi]. */
906  /* Reversed test to allow escape with NaNs */
907  if (tripb || !(fabs(v) >= (tripn ? 8 : 1) * tol0)) break;
908  /* Update bracketing values */
909  if (v > 0 && (numit > maxit1 || calp1/salp1 > calp1b/salp1b))
910  { salp1b = salp1; calp1b = calp1; }
911  else if (v < 0 && (numit > maxit1 || calp1/salp1 < calp1a/salp1a))
912  { salp1a = salp1; calp1a = calp1; }
913  if (numit < maxit1 && dv > 0) {
914  real
915  dalp1 = -v/dv;
916  real
917  sdalp1 = sin(dalp1), cdalp1 = cos(dalp1),
918  nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
919  if (nsalp1 > 0 && fabs(dalp1) < pi) {
920  calp1 = calp1 * cdalp1 - salp1 * sdalp1;
921  salp1 = nsalp1;
922  norm2(&salp1, &calp1);
923  /* In some regimes we don't get quadratic convergence because
924  * slope -> 0. So use convergence conditions based on epsilon
925  * instead of sqrt(epsilon). */
926  tripn = fabs(v) <= 16 * tol0;
927  continue;
928  }
929  }
930  /* Either dv was not positive or updated value was outside legal
931  * range. Use the midpoint of the bracket as the next estimate.
932  * This mechanism is not needed for the WGS84 ellipsoid, but it does
933  * catch problems with more eccentric ellipsoids. Its efficacy is
934  * such for the WGS84 test set with the starting guess set to alp1 =
935  * 90deg:
936  * the WGS84 test set: mean = 5.21, sd = 3.93, max = 24
937  * WGS84 and random input: mean = 4.74, sd = 0.99 */
938  salp1 = (salp1a + salp1b)/2;
939  calp1 = (calp1a + calp1b)/2;
940  norm2(&salp1, &calp1);
941  tripn = FALSE;
942  tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb ||
943  fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb);
944  }
945  Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
946  cbet1, cbet2, &s12x, &m12x, 0,
947  outmask & GEOD_GEODESICSCALE ? &M12 : 0,
948  outmask & GEOD_GEODESICSCALE ? &M21 : 0, Ca);
949  m12x *= g->b;
950  s12x *= g->b;
951  a12 = sig12 / degree;
952  if (outmask & GEOD_AREA) {
953  /* omg12 = lam12 - domg12 */
954  real sdomg12 = sin(domg12), cdomg12 = cos(domg12);
955  somg12 = slam12 * cdomg12 - clam12 * sdomg12;
956  comg12 = clam12 * cdomg12 + slam12 * sdomg12;
957  }
958  }
959  }
960 
961  if (outmask & GEOD_DISTANCE)
962  s12 = 0 + s12x; /* Convert -0 to 0 */
963 
964  if (outmask & GEOD_REDUCEDLENGTH)
965  m12 = 0 + m12x; /* Convert -0 to 0 */
966 
967  if (outmask & GEOD_AREA) {
968  real
969  /* From Lambda12: sin(alp1) * cos(bet1) = sin(alp0) */
970  salp0 = salp1 * cbet1,
971  calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */
972  real alp12;
973  if (calp0 != 0 && salp0 != 0) {
974  real
975  /* From Lambda12: tan(bet) = tan(sig) * cos(alp) */
976  ssig1 = sbet1, csig1 = calp1 * cbet1,
977  ssig2 = sbet2, csig2 = calp2 * cbet2,
978  k2 = sq(calp0) * g->ep2,
979  eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
980  /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0). */
981  A4 = sq(g->a) * calp0 * salp0 * g->e2;
982  real B41, B42;
983  norm2(&ssig1, &csig1);
984  norm2(&ssig2, &csig2);
985  C4f(g, eps, Ca);
986  B41 = SinCosSeries(FALSE, ssig1, csig1, Ca, nC4);
987  B42 = SinCosSeries(FALSE, ssig2, csig2, Ca, nC4);
988  S12 = A4 * (B42 - B41);
989  } else
990  /* Avoid problems with indeterminate sig1, sig2 on equator */
991  S12 = 0;
992 
993  if (!meridian && somg12 > 1) {
994  somg12 = sin(omg12); comg12 = cos(omg12);
995  }
996 
997  if (!meridian &&
998  /* omg12 < 3/4 * pi */
999  comg12 > -(real)(0.7071) && /* Long difference not too big */
1000  sbet2 - sbet1 < (real)(1.75)) { /* Lat difference not too big */
1001  /* Use tan(Gamma/2) = tan(omg12/2)
1002  * * (tan(bet1/2)+tan(bet2/2))/(1+tan(bet1/2)*tan(bet2/2))
1003  * with tan(x/2) = sin(x)/(1+cos(x)) */
1004  real
1005  domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
1006  alp12 = 2 * atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
1007  domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) );
1008  } else {
1009  /* alp12 = alp2 - alp1, used in atan2 so no need to normalize */
1010  real
1011  salp12 = salp2 * calp1 - calp2 * salp1,
1012  calp12 = calp2 * calp1 + salp2 * salp1;
1013  /* The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
1014  * salp12 = -0 and alp12 = -180. However this depends on the sign
1015  * being attached to 0 correctly. The following ensures the correct
1016  * behavior. */
1017  if (salp12 == 0 && calp12 < 0) {
1018  salp12 = tiny * calp1;
1019  calp12 = -1;
1020  }
1021  alp12 = atan2(salp12, calp12);
1022  }
1023  S12 += g->c2 * alp12;
1024  S12 *= swapp * lonsign * latsign;
1025  /* Convert -0 to 0 */
1026  S12 += 0;
1027  }
1028 
1029  /* Convert calp, salp to azimuth accounting for lonsign, swapp, latsign. */
1030  if (swapp < 0) {
1031  swapx(&salp1, &salp2);
1032  swapx(&calp1, &calp2);
1033  if (outmask & GEOD_GEODESICSCALE)
1034  swapx(&M12, &M21);
1035  }
1036 
1037  salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
1038  salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
1039 
1040  if (psalp1) *psalp1 = salp1;
1041  if (pcalp1) *pcalp1 = calp1;
1042  if (psalp2) *psalp2 = salp2;
1043  if (pcalp2) *pcalp2 = calp2;
1044 
1045  if (outmask & GEOD_DISTANCE)
1046  *ps12 = s12;
1047  if (outmask & GEOD_REDUCEDLENGTH)
1048  *pm12 = m12;
1049  if (outmask & GEOD_GEODESICSCALE) {
1050  if (pM12) *pM12 = M12;
1051  if (pM21) *pM21 = M21;
1052  }
1053  if (outmask & GEOD_AREA)
1054  *pS12 = S12;
1055 
1056  /* Returned value in [0, 180] */
1057  return a12;
1058 }
1059 
1060 real geod_geninverse(const struct geod_geodesic* g,
1061  real lat1, real lon1, real lat2, real lon2,
1062  real* ps12, real* pazi1, real* pazi2,
1063  real* pm12, real* pM12, real* pM21, real* pS12) {
1064  real salp1, calp1, salp2, calp2,
1065  a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, ps12,
1066  &salp1, &calp1, &salp2, &calp2,
1067  pm12, pM12, pM21, pS12);
1068  if (pazi1) *pazi1 = atan2dx(salp1, calp1);
1069  if (pazi2) *pazi2 = atan2dx(salp2, calp2);
1070  return a12;
1071 }
1072 
1073 void geod_inverseline(struct geod_geodesicline* l,
1074  const struct geod_geodesic* g,
1075  real lat1, real lon1, real lat2, real lon2,
1076  unsigned caps) {
1077  real salp1, calp1,
1078  a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, 0,
1079  &salp1, &calp1, 0, 0,
1080  0, 0, 0, 0),
1081  azi1 = atan2dx(salp1, calp1);
1082  caps = caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE;
1083  /* Ensure that a12 can be converted to a distance */
1084  if (caps & (OUT_ALL & GEOD_DISTANCE_IN)) caps |= GEOD_DISTANCE;
1085  geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps);
1086  geod_setarc(l, a12);
1087 }
1088 
1089 void geod_inverse(const struct geod_geodesic* g,
1090  real lat1, real lon1, real lat2, real lon2,
1091  real* ps12, real* pazi1, real* pazi2) {
1092  geod_geninverse(g, lat1, lon1, lat2, lon2, ps12, pazi1, pazi2, 0, 0, 0, 0);
1093 }
1094 
1095 real SinCosSeries(boolx sinp, real sinx, real cosx, const real c[], int n) {
1096  /* Evaluate
1097  * y = sinp ? sum(c[i] * sin( 2*i * x), i, 1, n) :
1098  * sum(c[i] * cos((2*i+1) * x), i, 0, n-1)
1099  * using Clenshaw summation. N.B. c[0] is unused for sin series
1100  * Approx operation count = (n + 5) mult and (2 * n + 2) add */
1101  real ar, y0, y1;
1102  c += (n + sinp); /* Point to one beyond last element */
1103  ar = 2 * (cosx - sinx) * (cosx + sinx); /* 2 * cos(2 * x) */
1104  y0 = n & 1 ? *--c : 0; y1 = 0; /* accumulators for sum */
1105  /* Now n is even */
1106  n /= 2;
1107  while (n--) {
1108  /* Unroll loop x 2, so accumulators return to their original role */
1109  y1 = ar * y0 - y1 + *--c;
1110  y0 = ar * y1 - y0 + *--c;
1111  }
1112  return sinp
1113  ? 2 * sinx * cosx * y0 /* sin(2 * x) * y0 */
1114  : cosx * (y0 - y1); /* cos(x) * (y0 - y1) */
1115 }
1116 
1117 void Lengths(const struct geod_geodesic* g,
1118  real eps, real sig12,
1119  real ssig1, real csig1, real dn1,
1120  real ssig2, real csig2, real dn2,
1121  real cbet1, real cbet2,
1122  real* ps12b, real* pm12b, real* pm0,
1123  real* pM12, real* pM21,
1124  /* Scratch area of the right size */
1125  real Ca[]) {
1126  real m0 = 0, J12 = 0, A1 = 0, A2 = 0;
1127  real Cb[nC];
1128 
1129  /* Return m12b = (reduced length)/b; also calculate s12b = distance/b,
1130  * and m0 = coefficient of secular term in expression for reduced length. */
1131  boolx redlp = pm12b || pm0 || pM12 || pM21;
1132  if (ps12b || redlp) {
1133  A1 = A1m1f(eps);
1134  C1f(eps, Ca);
1135  if (redlp) {
1136  A2 = A2m1f(eps);
1137  C2f(eps, Cb);
1138  m0 = A1 - A2;
1139  A2 = 1 + A2;
1140  }
1141  A1 = 1 + A1;
1142  }
1143  if (ps12b) {
1144  real B1 = SinCosSeries(TRUE, ssig2, csig2, Ca, nC1) -
1145  SinCosSeries(TRUE, ssig1, csig1, Ca, nC1);
1146  /* Missing a factor of b */
1147  *ps12b = A1 * (sig12 + B1);
1148  if (redlp) {
1149  real B2 = SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
1150  SinCosSeries(TRUE, ssig1, csig1, Cb, nC2);
1151  J12 = m0 * sig12 + (A1 * B1 - A2 * B2);
1152  }
1153  } else if (redlp) {
1154  /* Assume here that nC1 >= nC2 */
1155  int l;
1156  for (l = 1; l <= nC2; ++l)
1157  Cb[l] = A1 * Ca[l] - A2 * Cb[l];
1158  J12 = m0 * sig12 + (SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
1159  SinCosSeries(TRUE, ssig1, csig1, Cb, nC2));
1160  }
1161  if (pm0) *pm0 = m0;
1162  if (pm12b)
1163  /* Missing a factor of b.
1164  * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
1165  * accurate cancellation in the case of coincident points. */
1166  *pm12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
1167  csig1 * csig2 * J12;
1168  if (pM12 || pM21) {
1169  real csig12 = csig1 * csig2 + ssig1 * ssig2;
1170  real t = g->ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
1171  if (pM12)
1172  *pM12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
1173  if (pM21)
1174  *pM21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
1175  }
1176 }
1177 
1178 real Astroid(real x, real y) {
1179  /* Solve k^4+2*k^3-(x^2+y^2-1)*k^2-2*y^2*k-y^2 = 0 for positive root k.
1180  * This solution is adapted from Geocentric::Reverse. */
1181  real k;
1182  real
1183  p = sq(x),
1184  q = sq(y),
1185  r = (p + q - 1) / 6;
1186  if ( !(q == 0 && r <= 0) ) {
1187  real
1188  /* Avoid possible division by zero when r = 0 by multiplying equations
1189  * for s and t by r^3 and r, resp. */
1190  S = p * q / 4, /* S = r^3 * s */
1191  r2 = sq(r),
1192  r3 = r * r2,
1193  /* The discriminant of the quadratic equation for T3. This is zero on
1194  * the evolute curve p^(1/3)+q^(1/3) = 1 */
1195  disc = S * (S + 2 * r3);
1196  real u = r;
1197  real v, uv, w;
1198  if (disc >= 0) {
1199  real T3 = S + r3, T;
1200  /* Pick the sign on the sqrt to maximize abs(T3). This minimizes loss
1201  * of precision due to cancellation. The result is unchanged because
1202  * of the way the T is used in definition of u. */
1203  T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc); /* T3 = (r * t)^3 */
1204  /* N.B. cbrtx always returns the real root. cbrtx(-8) = -2. */
1205  T = cbrtx(T3); /* T = r * t */
1206  /* T can be zero; but then r2 / T -> 0. */
1207  u += T + (T != 0 ? r2 / T : 0);
1208  } else {
1209  /* T is complex, but the way u is defined the result is real. */
1210  real ang = atan2(sqrt(-disc), -(S + r3));
1211  /* There are three possible cube roots. We choose the root which
1212  * avoids cancellation. Note that disc < 0 implies that r < 0. */
1213  u += 2 * r * cos(ang / 3);
1214  }
1215  v = sqrt(sq(u) + q); /* guaranteed positive */
1216  /* Avoid loss of accuracy when u < 0. */
1217  uv = u < 0 ? q / (v - u) : u + v; /* u+v, guaranteed positive */
1218  w = (uv - q) / (2 * v); /* positive? */
1219  /* Rearrange expression for k to avoid loss of accuracy due to
1220  * subtraction. Division by 0 not possible because uv > 0, w >= 0. */
1221  k = uv / (sqrt(uv + sq(w)) + w); /* guaranteed positive */
1222  } else { /* q == 0 && r <= 0 */
1223  /* y = 0 with |x| <= 1. Handle this case directly.
1224  * for y small, positive root is k = abs(y)/sqrt(1-x^2) */
1225  k = 0;
1226  }
1227  return k;
1228 }
1229 
1230 real InverseStart(const struct geod_geodesic* g,
1231  real sbet1, real cbet1, real dn1,
1232  real sbet2, real cbet2, real dn2,
1233  real lam12, real slam12, real clam12,
1234  real* psalp1, real* pcalp1,
1235  /* Only updated if return val >= 0 */
1236  real* psalp2, real* pcalp2,
1237  /* Only updated for short lines */
1238  real* pdnm,
1239  /* Scratch area of the right size */
1240  real Ca[]) {
1241  real salp1 = 0, calp1 = 0, salp2 = 0, calp2 = 0, dnm = 0;
1242 
1243  /* Return a starting point for Newton's method in salp1 and calp1 (function
1244  * value is -1). If Newton's method doesn't need to be used, return also
1245  * salp2 and calp2 and function value is sig12. */
1246  real
1247  sig12 = -1, /* Return value */
1248  /* bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0] */
1249  sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
1250  cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
1251  real sbet12a;
1252  boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) &&
1253  cbet2 * lam12 < (real)(0.5);
1254  real somg12, comg12, ssig12, csig12;
1255 #if defined(__GNUC__) && __GNUC__ == 4 && \
1256  (__GNUC_MINOR__ < 6 || defined(__MINGW32__))
1257  /* Volatile declaration needed to fix inverse cases
1258  * 88.202499451857 0 -88.202499451857 179.981022032992859592
1259  * 89.262080389218 0 -89.262080389218 179.992207982775375662
1260  * 89.333123580033 0 -89.333123580032997687 179.99295812360148422
1261  * which otherwise fail with g++ 4.4.4 x86 -O3 (Linux)
1262  * and g++ 4.4.0 (mingw) and g++ 4.6.1 (tdm mingw). */
1263  {
1264  volatile real xx1 = sbet2 * cbet1;
1265  volatile real xx2 = cbet2 * sbet1;
1266  sbet12a = xx1 + xx2;
1267  }
1268 #else
1269  sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
1270 #endif
1271  if (shortline) {
1272  real sbetm2 = sq(sbet1 + sbet2), omg12;
1273  /* sin((bet1+bet2)/2)^2
1274  * = (sbet1 + sbet2)^2 / ((sbet1 + sbet2)^2 + (cbet1 + cbet2)^2) */
1275  sbetm2 /= sbetm2 + sq(cbet1 + cbet2);
1276  dnm = sqrt(1 + g->ep2 * sbetm2);
1277  omg12 = lam12 / (g->f1 * dnm);
1278  somg12 = sin(omg12); comg12 = cos(omg12);
1279  } else {
1280  somg12 = slam12; comg12 = clam12;
1281  }
1282 
1283  salp1 = cbet2 * somg12;
1284  calp1 = comg12 >= 0 ?
1285  sbet12 + cbet2 * sbet1 * sq(somg12) / (1 + comg12) :
1286  sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
1287 
1288  ssig12 = hypotx(salp1, calp1);
1289  csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
1290 
1291  if (shortline && ssig12 < g->etol2) {
1292  /* really short lines */
1293  salp2 = cbet1 * somg12;
1294  calp2 = sbet12 - cbet1 * sbet2 *
1295  (comg12 >= 0 ? sq(somg12) / (1 + comg12) : 1 - comg12);
1296  norm2(&salp2, &calp2);
1297  /* Set return value */
1298  sig12 = atan2(ssig12, csig12);
1299  } else if (fabs(g->n) > (real)(0.1) || /* No astroid calc if too eccentric */
1300  csig12 >= 0 ||
1301  ssig12 >= 6 * fabs(g->n) * pi * sq(cbet1)) {
1302  /* Nothing to do, zeroth order spherical approximation is OK */
1303  } else {
1304  /* Scale lam12 and bet2 to x, y coordinate system where antipodal point
1305  * is at origin and singular point is at y = 0, x = -1. */
1306  real y, lamscale, betscale;
1307  /* Volatile declaration needed to fix inverse case
1308  * 56.320923501171 0 -56.320923501171 179.664747671772880215
1309  * which otherwise fails with g++ 4.4.4 x86 -O3 */
1310  volatile real x;
1311  real lam12x = atan2(-slam12, -clam12); /* lam12 - pi */
1312  if (g->f >= 0) { /* In fact f == 0 does not get here */
1313  /* x = dlong, y = dlat */
1314  {
1315  real
1316  k2 = sq(sbet1) * g->ep2,
1317  eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
1318  lamscale = g->f * cbet1 * A3f(g, eps) * pi;
1319  }
1320  betscale = lamscale * cbet1;
1321 
1322  x = lam12x / lamscale;
1323  y = sbet12a / betscale;
1324  } else { /* f < 0 */
1325  /* x = dlat, y = dlong */
1326  real
1327  cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
1328  bet12a = atan2(sbet12a, cbet12a);
1329  real m12b, m0;
1330  /* In the case of lon12 = 180, this repeats a calculation made in
1331  * Inverse. */
1332  Lengths(g, g->n, pi + bet12a,
1333  sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
1334  cbet1, cbet2, 0, &m12b, &m0, 0, 0, Ca);
1335  x = -1 + m12b / (cbet1 * cbet2 * m0 * pi);
1336  betscale = x < -(real)(0.01) ? sbet12a / x :
1337  -g->f * sq(cbet1) * pi;
1338  lamscale = betscale / cbet1;
1339  y = lam12x / lamscale;
1340  }
1341 
1342  if (y > -tol1 && x > -1 - xthresh) {
1343  /* strip near cut */
1344  if (g->f >= 0) {
1345  salp1 = minx((real)(1), -(real)(x)); calp1 = - sqrt(1 - sq(salp1));
1346  } else {
1347  calp1 = maxx((real)(x > -tol1 ? 0 : -1), (real)(x));
1348  salp1 = sqrt(1 - sq(calp1));
1349  }
1350  } else {
1351  /* Estimate alp1, by solving the astroid problem.
1352  *
1353  * Could estimate alpha1 = theta + pi/2, directly, i.e.,
1354  * calp1 = y/k; salp1 = -x/(1+k); for f >= 0
1355  * calp1 = x/(1+k); salp1 = -y/k; for f < 0 (need to check)
1356  *
1357  * However, it's better to estimate omg12 from astroid and use
1358  * spherical formula to compute alp1. This reduces the mean number of
1359  * Newton iterations for astroid cases from 2.24 (min 0, max 6) to 2.12
1360  * (min 0 max 5). The changes in the number of iterations are as
1361  * follows:
1362  *
1363  * change percent
1364  * 1 5
1365  * 0 78
1366  * -1 16
1367  * -2 0.6
1368  * -3 0.04
1369  * -4 0.002
1370  *
1371  * The histogram of iterations is (m = number of iterations estimating
1372  * alp1 directly, n = number of iterations estimating via omg12, total
1373  * number of trials = 148605):
1374  *
1375  * iter m n
1376  * 0 148 186
1377  * 1 13046 13845
1378  * 2 93315 102225
1379  * 3 36189 32341
1380  * 4 5396 7
1381  * 5 455 1
1382  * 6 56 0
1383  *
1384  * Because omg12 is near pi, estimate work with omg12a = pi - omg12 */
1385  real k = Astroid(x, y);
1386  real
1387  omg12a = lamscale * ( g->f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
1388  somg12 = sin(omg12a); comg12 = -cos(omg12a);
1389  /* Update spherical estimate of alp1 using omg12 instead of lam12 */
1390  salp1 = cbet2 * somg12;
1391  calp1 = sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
1392  }
1393  }
1394  /* Sanity check on starting guess. Backwards check allows NaN through. */
1395  if (!(salp1 <= 0))
1396  norm2(&salp1, &calp1);
1397  else {
1398  salp1 = 1; calp1 = 0;
1399  }
1400 
1401  *psalp1 = salp1;
1402  *pcalp1 = calp1;
1403  if (shortline)
1404  *pdnm = dnm;
1405  if (sig12 >= 0) {
1406  *psalp2 = salp2;
1407  *pcalp2 = calp2;
1408  }
1409  return sig12;
1410 }
1411 
1412 real Lambda12(const struct geod_geodesic* g,
1413  real sbet1, real cbet1, real dn1,
1414  real sbet2, real cbet2, real dn2,
1415  real salp1, real calp1,
1416  real slam120, real clam120,
1417  real* psalp2, real* pcalp2,
1418  real* psig12,
1419  real* pssig1, real* pcsig1,
1420  real* pssig2, real* pcsig2,
1421  real* peps,
1422  real* pdomg12,
1423  boolx diffp, real* pdlam12,
1424  /* Scratch area of the right size */
1425  real Ca[]) {
1426  real salp2 = 0, calp2 = 0, sig12 = 0,
1427  ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0,
1428  domg12 = 0, dlam12 = 0;
1429  real salp0, calp0;
1430  real somg1, comg1, somg2, comg2, somg12, comg12, lam12;
1431  real B312, eta, k2;
1432 
1433  if (sbet1 == 0 && calp1 == 0)
1434  /* Break degeneracy of equatorial line. This case has already been
1435  * handled. */
1436  calp1 = -tiny;
1437 
1438  /* sin(alp1) * cos(bet1) = sin(alp0) */
1439  salp0 = salp1 * cbet1;
1440  calp0 = hypotx(calp1, salp1 * sbet1); /* calp0 > 0 */
1441 
1442  /* tan(bet1) = tan(sig1) * cos(alp1)
1443  * tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1) */
1444  ssig1 = sbet1; somg1 = salp0 * sbet1;
1445  csig1 = comg1 = calp1 * cbet1;
1446  norm2(&ssig1, &csig1);
1447  /* norm2(&somg1, &comg1); -- don't need to normalize! */
1448 
1449  /* Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful
1450  * about this case, since this can yield singularities in the Newton
1451  * iteration.
1452  * sin(alp2) * cos(bet2) = sin(alp0) */
1453  salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
1454  /* calp2 = sqrt(1 - sq(salp2))
1455  * = sqrt(sq(calp0) - sq(sbet2)) / cbet2
1456  * and subst for calp0 and rearrange to give (choose positive sqrt
1457  * to give alp2 in [0, pi/2]). */
1458  calp2 = cbet2 != cbet1 || fabs(sbet2) != -sbet1 ?
1459  sqrt(sq(calp1 * cbet1) +
1460  (cbet1 < -sbet1 ?
1461  (cbet2 - cbet1) * (cbet1 + cbet2) :
1462  (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 :
1463  fabs(calp1);
1464  /* tan(bet2) = tan(sig2) * cos(alp2)
1465  * tan(omg2) = sin(alp0) * tan(sig2). */
1466  ssig2 = sbet2; somg2 = salp0 * sbet2;
1467  csig2 = comg2 = calp2 * cbet2;
1468  norm2(&ssig2, &csig2);
1469  /* norm2(&somg2, &comg2); -- don't need to normalize! */
1470 
1471  /* sig12 = sig2 - sig1, limit to [0, pi] */
1472  sig12 = atan2(maxx((real)(0), csig1 * ssig2 - ssig1 * csig2),
1473  csig1 * csig2 + ssig1 * ssig2);
1474 
1475  /* omg12 = omg2 - omg1, limit to [0, pi] */
1476  somg12 = maxx((real)(0), comg1 * somg2 - somg1 * comg2);
1477  comg12 = comg1 * comg2 + somg1 * somg2;
1478  /* eta = omg12 - lam120 */
1479  eta = atan2(somg12 * clam120 - comg12 * slam120,
1480  comg12 * clam120 + somg12 * slam120);
1481  k2 = sq(calp0) * g->ep2;
1482  eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
1483  C3f(g, eps, Ca);
1484  B312 = (SinCosSeries(TRUE, ssig2, csig2, Ca, nC3-1) -
1485  SinCosSeries(TRUE, ssig1, csig1, Ca, nC3-1));
1486  domg12 = -g->f * A3f(g, eps) * salp0 * (sig12 + B312);
1487  lam12 = eta + domg12;
1488 
1489  if (diffp) {
1490  if (calp2 == 0)
1491  dlam12 = - 2 * g->f1 * dn1 / sbet1;
1492  else {
1493  Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1494  cbet1, cbet2, 0, &dlam12, 0, 0, 0, Ca);
1495  dlam12 *= g->f1 / (calp2 * cbet2);
1496  }
1497  }
1498 
1499  *psalp2 = salp2;
1500  *pcalp2 = calp2;
1501  *psig12 = sig12;
1502  *pssig1 = ssig1;
1503  *pcsig1 = csig1;
1504  *pssig2 = ssig2;
1505  *pcsig2 = csig2;
1506  *peps = eps;
1507  *pdomg12 = domg12;
1508  if (diffp)
1509  *pdlam12 = dlam12;
1510 
1511  return lam12;
1512 }
1513 
1514 real A3f(const struct geod_geodesic* g, real eps) {
1515  /* Evaluate A3 */
1516  return polyval(nA3 - 1, g->A3x, eps);
1517 }
1518 
1519 void C3f(const struct geod_geodesic* g, real eps, real c[]) {
1520  /* Evaluate C3 coeffs
1521  * Elements c[1] through c[nC3 - 1] are set */
1522  real mult = 1;
1523  int o = 0, l;
1524  for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */
1525  int m = nC3 - l - 1; /* order of polynomial in eps */
1526  mult *= eps;
1527  c[l] = mult * polyval(m, g->C3x + o, eps);
1528  o += m + 1;
1529  }
1530 }
1531 
1532 void C4f(const struct geod_geodesic* g, real eps, real c[]) {
1533  /* Evaluate C4 coeffs
1534  * Elements c[0] through c[nC4 - 1] are set */
1535  real mult = 1;
1536  int o = 0, l;
1537  for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */
1538  int m = nC4 - l - 1; /* order of polynomial in eps */
1539  c[l] = mult * polyval(m, g->C4x + o, eps);
1540  o += m + 1;
1541  mult *= eps;
1542  }
1543 }
1544 
1545 /* The scale factor A1-1 = mean value of (d/dsigma)I1 - 1 */
1546 real A1m1f(real eps) {
1547  static const real coeff[] = {
1548  /* (1-eps)*A1-1, polynomial in eps2 of order 3 */
1549  1, 4, 64, 0, 256,
1550  };
1551  int m = nA1/2;
1552  real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1553  return (t + eps) / (1 - eps);
1554 }
1555 
1556 /* The coefficients C1[l] in the Fourier expansion of B1 */
1557 void C1f(real eps, real c[]) {
1558  static const real coeff[] = {
1559  /* C1[1]/eps^1, polynomial in eps2 of order 2 */
1560  -1, 6, -16, 32,
1561  /* C1[2]/eps^2, polynomial in eps2 of order 2 */
1562  -9, 64, -128, 2048,
1563  /* C1[3]/eps^3, polynomial in eps2 of order 1 */
1564  9, -16, 768,
1565  /* C1[4]/eps^4, polynomial in eps2 of order 1 */
1566  3, -5, 512,
1567  /* C1[5]/eps^5, polynomial in eps2 of order 0 */
1568  -7, 1280,
1569  /* C1[6]/eps^6, polynomial in eps2 of order 0 */
1570  -7, 2048,
1571  };
1572  real
1573  eps2 = sq(eps),
1574  d = eps;
1575  int o = 0, l;
1576  for (l = 1; l <= nC1; ++l) { /* l is index of C1p[l] */
1577  int m = (nC1 - l) / 2; /* order of polynomial in eps^2 */
1578  c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1579  o += m + 2;
1580  d *= eps;
1581  }
1582 }
1583 
1584 /* The coefficients C1p[l] in the Fourier expansion of B1p */
1585 void C1pf(real eps, real c[]) {
1586  static const real coeff[] = {
1587  /* C1p[1]/eps^1, polynomial in eps2 of order 2 */
1588  205, -432, 768, 1536,
1589  /* C1p[2]/eps^2, polynomial in eps2 of order 2 */
1590  4005, -4736, 3840, 12288,
1591  /* C1p[3]/eps^3, polynomial in eps2 of order 1 */
1592  -225, 116, 384,
1593  /* C1p[4]/eps^4, polynomial in eps2 of order 1 */
1594  -7173, 2695, 7680,
1595  /* C1p[5]/eps^5, polynomial in eps2 of order 0 */
1596  3467, 7680,
1597  /* C1p[6]/eps^6, polynomial in eps2 of order 0 */
1598  38081, 61440,
1599  };
1600  real
1601  eps2 = sq(eps),
1602  d = eps;
1603  int o = 0, l;
1604  for (l = 1; l <= nC1p; ++l) { /* l is index of C1p[l] */
1605  int m = (nC1p - l) / 2; /* order of polynomial in eps^2 */
1606  c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1607  o += m + 2;
1608  d *= eps;
1609  }
1610 }
1611 
1612 /* The scale factor A2-1 = mean value of (d/dsigma)I2 - 1 */
1613 real A2m1f(real eps) {
1614  static const real coeff[] = {
1615  /* (eps+1)*A2-1, polynomial in eps2 of order 3 */
1616  -11, -28, -192, 0, 256,
1617  };
1618  int m = nA2/2;
1619  real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1620  return (t - eps) / (1 + eps);
1621 }
1622 
1623 /* The coefficients C2[l] in the Fourier expansion of B2 */
1624 void C2f(real eps, real c[]) {
1625  static const real coeff[] = {
1626  /* C2[1]/eps^1, polynomial in eps2 of order 2 */
1627  1, 2, 16, 32,
1628  /* C2[2]/eps^2, polynomial in eps2 of order 2 */
1629  35, 64, 384, 2048,
1630  /* C2[3]/eps^3, polynomial in eps2 of order 1 */
1631  15, 80, 768,
1632  /* C2[4]/eps^4, polynomial in eps2 of order 1 */
1633  7, 35, 512,
1634  /* C2[5]/eps^5, polynomial in eps2 of order 0 */
1635  63, 1280,
1636  /* C2[6]/eps^6, polynomial in eps2 of order 0 */
1637  77, 2048,
1638  };
1639  real
1640  eps2 = sq(eps),
1641  d = eps;
1642  int o = 0, l;
1643  for (l = 1; l <= nC2; ++l) { /* l is index of C2[l] */
1644  int m = (nC2 - l) / 2; /* order of polynomial in eps^2 */
1645  c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1646  o += m + 2;
1647  d *= eps;
1648  }
1649 }
1650 
1651 /* The scale factor A3 = mean value of (d/dsigma)I3 */
1652 void A3coeff(struct geod_geodesic* g) {
1653  static const real coeff[] = {
1654  /* A3, coeff of eps^5, polynomial in n of order 0 */
1655  -3, 128,
1656  /* A3, coeff of eps^4, polynomial in n of order 1 */
1657  -2, -3, 64,
1658  /* A3, coeff of eps^3, polynomial in n of order 2 */
1659  -1, -3, -1, 16,
1660  /* A3, coeff of eps^2, polynomial in n of order 2 */
1661  3, -1, -2, 8,
1662  /* A3, coeff of eps^1, polynomial in n of order 1 */
1663  1, -1, 2,
1664  /* A3, coeff of eps^0, polynomial in n of order 0 */
1665  1, 1,
1666  };
1667  int o = 0, k = 0, j;
1668  for (j = nA3 - 1; j >= 0; --j) { /* coeff of eps^j */
1669  int m = nA3 - j - 1 < j ? nA3 - j - 1 : j; /* order of polynomial in n */
1670  g->A3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1671  o += m + 2;
1672  }
1673 }
1674 
1675 /* The coefficients C3[l] in the Fourier expansion of B3 */
1676 void C3coeff(struct geod_geodesic* g) {
1677  static const real coeff[] = {
1678  /* C3[1], coeff of eps^5, polynomial in n of order 0 */
1679  3, 128,
1680  /* C3[1], coeff of eps^4, polynomial in n of order 1 */
1681  2, 5, 128,
1682  /* C3[1], coeff of eps^3, polynomial in n of order 2 */
1683  -1, 3, 3, 64,
1684  /* C3[1], coeff of eps^2, polynomial in n of order 2 */
1685  -1, 0, 1, 8,
1686  /* C3[1], coeff of eps^1, polynomial in n of order 1 */
1687  -1, 1, 4,
1688  /* C3[2], coeff of eps^5, polynomial in n of order 0 */
1689  5, 256,
1690  /* C3[2], coeff of eps^4, polynomial in n of order 1 */
1691  1, 3, 128,
1692  /* C3[2], coeff of eps^3, polynomial in n of order 2 */
1693  -3, -2, 3, 64,
1694  /* C3[2], coeff of eps^2, polynomial in n of order 2 */
1695  1, -3, 2, 32,
1696  /* C3[3], coeff of eps^5, polynomial in n of order 0 */
1697  7, 512,
1698  /* C3[3], coeff of eps^4, polynomial in n of order 1 */
1699  -10, 9, 384,
1700  /* C3[3], coeff of eps^3, polynomial in n of order 2 */
1701  5, -9, 5, 192,
1702  /* C3[4], coeff of eps^5, polynomial in n of order 0 */
1703  7, 512,
1704  /* C3[4], coeff of eps^4, polynomial in n of order 1 */
1705  -14, 7, 512,
1706  /* C3[5], coeff of eps^5, polynomial in n of order 0 */
1707  21, 2560,
1708  };
1709  int o = 0, k = 0, l, j;
1710  for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */
1711  for (j = nC3 - 1; j >= l; --j) { /* coeff of eps^j */
1712  int m = nC3 - j - 1 < j ? nC3 - j - 1 : j; /* order of polynomial in n */
1713  g->C3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1714  o += m + 2;
1715  }
1716  }
1717 }
1718 
1719 /* The coefficients C4[l] in the Fourier expansion of I4 */
1720 void C4coeff(struct geod_geodesic* g) {
1721  static const real coeff[] = {
1722  /* C4[0], coeff of eps^5, polynomial in n of order 0 */
1723  97, 15015,
1724  /* C4[0], coeff of eps^4, polynomial in n of order 1 */
1725  1088, 156, 45045,
1726  /* C4[0], coeff of eps^3, polynomial in n of order 2 */
1727  -224, -4784, 1573, 45045,
1728  /* C4[0], coeff of eps^2, polynomial in n of order 3 */
1729  -10656, 14144, -4576, -858, 45045,
1730  /* C4[0], coeff of eps^1, polynomial in n of order 4 */
1731  64, 624, -4576, 6864, -3003, 15015,
1732  /* C4[0], coeff of eps^0, polynomial in n of order 5 */
1733  100, 208, 572, 3432, -12012, 30030, 45045,
1734  /* C4[1], coeff of eps^5, polynomial in n of order 0 */
1735  1, 9009,
1736  /* C4[1], coeff of eps^4, polynomial in n of order 1 */
1737  -2944, 468, 135135,
1738  /* C4[1], coeff of eps^3, polynomial in n of order 2 */
1739  5792, 1040, -1287, 135135,
1740  /* C4[1], coeff of eps^2, polynomial in n of order 3 */
1741  5952, -11648, 9152, -2574, 135135,
1742  /* C4[1], coeff of eps^1, polynomial in n of order 4 */
1743  -64, -624, 4576, -6864, 3003, 135135,
1744  /* C4[2], coeff of eps^5, polynomial in n of order 0 */
1745  8, 10725,
1746  /* C4[2], coeff of eps^4, polynomial in n of order 1 */
1747  1856, -936, 225225,
1748  /* C4[2], coeff of eps^3, polynomial in n of order 2 */
1749  -8448, 4992, -1144, 225225,
1750  /* C4[2], coeff of eps^2, polynomial in n of order 3 */
1751  -1440, 4160, -4576, 1716, 225225,
1752  /* C4[3], coeff of eps^5, polynomial in n of order 0 */
1753  -136, 63063,
1754  /* C4[3], coeff of eps^4, polynomial in n of order 1 */
1755  1024, -208, 105105,
1756  /* C4[3], coeff of eps^3, polynomial in n of order 2 */
1757  3584, -3328, 1144, 315315,
1758  /* C4[4], coeff of eps^5, polynomial in n of order 0 */
1759  -128, 135135,
1760  /* C4[4], coeff of eps^4, polynomial in n of order 1 */
1761  -2560, 832, 405405,
1762  /* C4[5], coeff of eps^5, polynomial in n of order 0 */
1763  128, 99099,
1764  };
1765  int o = 0, k = 0, l, j;
1766  for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */
1767  for (j = nC4 - 1; j >= l; --j) { /* coeff of eps^j */
1768  int m = nC4 - j - 1; /* order of polynomial in n */
1769  g->C4x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1770  o += m + 2;
1771  }
1772  }
1773 }
1774 
1775 int transit(real lon1, real lon2) {
1776  real lon12;
1777  /* Return 1 or -1 if crossing prime meridian in east or west direction.
1778  * Otherwise return zero. */
1779  /* Compute lon12 the same way as Geodesic::Inverse. */
1780  lon1 = AngNormalize(lon1);
1781  lon2 = AngNormalize(lon2);
1782  lon12 = AngDiff(lon1, lon2, 0);
1783  return lon1 <= 0 && lon2 > 0 && lon12 > 0 ? 1 :
1784  (lon2 <= 0 && lon1 > 0 && lon12 < 0 ? -1 : 0);
1785 }
1786 
1787 int transitdirect(real lon1, real lon2) {
1788 #if HAVE_C99_MATH
1789  lon1 = remainder(lon1, (real)(720));
1790  lon2 = remainder(lon2, (real)(720));
1791  return ( (lon2 >= 0 && lon2 < 360 ? 0 : 1) -
1792  (lon1 >= 0 && lon1 < 360 ? 0 : 1) );
1793 #else
1794  lon1 = fmod(lon1, (real)(720));
1795  lon2 = fmod(lon2, (real)(720));
1796  return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
1797  ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
1798 #endif
1799 }
1800 
1801 void accini(real s[]) {
1802  /* Initialize an accumulator; this is an array with two elements. */
1803  s[0] = s[1] = 0;
1804 }
1805 
1806 void acccopy(const real s[], real t[]) {
1807  /* Copy an accumulator; t = s. */
1808  t[0] = s[0]; t[1] = s[1];
1809 }
1810 
1811 void accadd(real s[], real y) {
1812  /* Add y to an accumulator. */
1813  real u, z = sumx(y, s[1], &u);
1814  s[0] = sumx(z, s[0], &s[1]);
1815  if (s[0] == 0)
1816  s[0] = u;
1817  else
1818  s[1] = s[1] + u;
1819 }
1820 
1821 real accsum(const real s[], real y) {
1822  /* Return accumulator + y (but don't add to accumulator). */
1823  real t[2];
1824  acccopy(s, t);
1825  accadd(t, y);
1826  return t[0];
1827 }
1828 
1829 void accneg(real s[]) {
1830  /* Negate an accumulator. */
1831  s[0] = -s[0]; s[1] = -s[1];
1832 }
1833 
1834 void geod_polygon_init(struct geod_polygon* p, boolx polylinep) {
1835  p->polyline = (polylinep != 0);
1836  geod_polygon_clear(p);
1837 }
1838 
1839 void geod_polygon_clear(struct geod_polygon* p) {
1840  p->lat0 = p->lon0 = p->lat = p->lon = NaN;
1841  accini(p->P);
1842  accini(p->A);
1843  p->num = p->crossings = 0;
1844 }
1845 
1846 void geod_polygon_addpoint(const struct geod_geodesic* g,
1847  struct geod_polygon* p,
1848  real lat, real lon) {
1849  lon = AngNormalize(lon);
1850  if (p->num == 0) {
1851  p->lat0 = p->lat = lat;
1852  p->lon0 = p->lon = lon;
1853  } else {
1854  real s12, S12 = 0; /* Initialize S12 to stop Visual Studio warning */
1855  geod_geninverse(g, p->lat, p->lon, lat, lon,
1856  &s12, 0, 0, 0, 0, 0, p->polyline ? 0 : &S12);
1857  accadd(p->P, s12);
1858  if (!p->polyline) {
1859  accadd(p->A, S12);
1860  p->crossings += transit(p->lon, lon);
1861  }
1862  p->lat = lat; p->lon = lon;
1863  }
1864  ++p->num;
1865 }
1866 
1867 void geod_polygon_addedge(const struct geod_geodesic* g,
1868  struct geod_polygon* p,
1869  real azi, real s) {
1870  if (p->num) { /* Do nothing is num is zero */
1871  real lat, lon, S12 = 0; /* Initialize S12 to stop Visual Studio warning */
1872  geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s,
1873  &lat, &lon, 0,
1874  0, 0, 0, 0, p->polyline ? 0 : &S12);
1875  accadd(p->P, s);
1876  if (!p->polyline) {
1877  accadd(p->A, S12);
1878  p->crossings += transitdirect(p->lon, lon);
1879  }
1880  p->lat = lat; p->lon = lon;
1881  ++p->num;
1882  }
1883 }
1884 
1885 unsigned geod_polygon_compute(const struct geod_geodesic* g,
1886  const struct geod_polygon* p,
1887  boolx reverse, boolx sign,
1888  real* pA, real* pP) {
1889  real s12, S12, t[2], area0;
1890  int crossings;
1891  if (p->num < 2) {
1892  if (pP) *pP = 0;
1893  if (!p->polyline && pA) *pA = 0;
1894  return p->num;
1895  }
1896  if (p->polyline) {
1897  if (pP) *pP = p->P[0];
1898  return p->num;
1899  }
1900  geod_geninverse(g, p->lat, p->lon, p->lat0, p->lon0,
1901  &s12, 0, 0, 0, 0, 0, &S12);
1902  if (pP) *pP = accsum(p->P, s12);
1903  acccopy(p->A, t);
1904  accadd(t, S12);
1905  crossings = p->crossings + transit(p->lon, p->lon0);
1906  area0 = 4 * pi * g->c2;
1907  if (crossings & 1)
1908  accadd(t, (t[0] < 0 ? 1 : -1) * area0/2);
1909  /* area is with the clockwise sense. If !reverse convert to
1910  * counter-clockwise convention. */
1911  if (!reverse)
1912  accneg(t);
1913  /* If sign put area in (-area0/2, area0/2], else put area in [0, area0) */
1914  if (sign) {
1915  if (t[0] > area0/2)
1916  accadd(t, -area0);
1917  else if (t[0] <= -area0/2)
1918  accadd(t, +area0);
1919  } else {
1920  if (t[0] >= area0)
1921  accadd(t, -area0);
1922  else if (t[0] < 0)
1923  accadd(t, +area0);
1924  }
1925  if (pA) *pA = 0 + t[0];
1926  return p->num;
1927 }
1928 
1929 unsigned geod_polygon_testpoint(const struct geod_geodesic* g,
1930  const struct geod_polygon* p,
1931  real lat, real lon,
1932  boolx reverse, boolx sign,
1933  real* pA, real* pP) {
1934  real perimeter, tempsum, area0;
1935  int crossings, i;
1936  unsigned num = p->num + 1;
1937  if (num == 1) {
1938  if (pP) *pP = 0;
1939  if (!p->polyline && pA) *pA = 0;
1940  return num;
1941  }
1942  perimeter = p->P[0];
1943  tempsum = p->polyline ? 0 : p->A[0];
1944  crossings = p->crossings;
1945  for (i = 0; i < (p->polyline ? 1 : 2); ++i) {
1946  real s12, S12 = 0; /* Initialize S12 to stop Visual Studio warning */
1947  geod_geninverse(g,
1948  i == 0 ? p->lat : lat, i == 0 ? p->lon : lon,
1949  i != 0 ? p->lat0 : lat, i != 0 ? p->lon0 : lon,
1950  &s12, 0, 0, 0, 0, 0, p->polyline ? 0 : &S12);
1951  perimeter += s12;
1952  if (!p->polyline) {
1953  tempsum += S12;
1954  crossings += transit(i == 0 ? p->lon : lon,
1955  i != 0 ? p->lon0 : lon);
1956  }
1957  }
1958 
1959  if (pP) *pP = perimeter;
1960  if (p->polyline)
1961  return num;
1962 
1963  area0 = 4 * pi * g->c2;
1964  if (crossings & 1)
1965  tempsum += (tempsum < 0 ? 1 : -1) * area0/2;
1966  /* area is with the clockwise sense. If !reverse convert to
1967  * counter-clockwise convention. */
1968  if (!reverse)
1969  tempsum *= -1;
1970  /* If sign put area in (-area0/2, area0/2], else put area in [0, area0) */
1971  if (sign) {
1972  if (tempsum > area0/2)
1973  tempsum -= area0;
1974  else if (tempsum <= -area0/2)
1975  tempsum += area0;
1976  } else {
1977  if (tempsum >= area0)
1978  tempsum -= area0;
1979  else if (tempsum < 0)
1980  tempsum += area0;
1981  }
1982  if (pA) *pA = 0 + tempsum;
1983  return num;
1984 }
1985 
1986 unsigned geod_polygon_testedge(const struct geod_geodesic* g,
1987  const struct geod_polygon* p,
1988  real azi, real s,
1989  boolx reverse, boolx sign,
1990  real* pA, real* pP) {
1991  real perimeter, tempsum, area0;
1992  int crossings;
1993  unsigned num = p->num + 1;
1994  if (num == 1) { /* we don't have a starting point! */
1995  if (pP) *pP = NaN;
1996  if (!p->polyline && pA) *pA = NaN;
1997  return 0;
1998  }
1999  perimeter = p->P[0] + s;
2000  if (p->polyline) {
2001  if (pP) *pP = perimeter;
2002  return num;
2003  }
2004 
2005  tempsum = p->A[0];
2006  crossings = p->crossings;
2007  {
2008  real lat, lon, s12, S12;
2009  geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s,
2010  &lat, &lon, 0,
2011  0, 0, 0, 0, &S12);
2012  tempsum += S12;
2013  crossings += transitdirect(p->lon, lon);
2014  geod_geninverse(g, lat, lon, p->lat0, p->lon0,
2015  &s12, 0, 0, 0, 0, 0, &S12);
2016  perimeter += s12;
2017  tempsum += S12;
2018  crossings += transit(lon, p->lon0);
2019  }
2020 
2021  area0 = 4 * pi * g->c2;
2022  if (crossings & 1)
2023  tempsum += (tempsum < 0 ? 1 : -1) * area0/2;
2024  /* area is with the clockwise sense. If !reverse convert to
2025  * counter-clockwise convention. */
2026  if (!reverse)
2027  tempsum *= -1;
2028  /* If sign put area in (-area0/2, area0/2], else put area in [0, area0) */
2029  if (sign) {
2030  if (tempsum > area0/2)
2031  tempsum -= area0;
2032  else if (tempsum <= -area0/2)
2033  tempsum += area0;
2034  } else {
2035  if (tempsum >= area0)
2036  tempsum -= area0;
2037  else if (tempsum < 0)
2038  tempsum += area0;
2039  }
2040  if (pP) *pP = perimeter;
2041  if (pA) *pA = 0 + tempsum;
2042  return num;
2043 }
2044 
2045 void geod_polygonarea(const struct geod_geodesic* g,
2046  real lats[], real lons[], int n,
2047  real* pA, real* pP) {
2048  int i;
2049  struct geod_polygon p;
2050  geod_polygon_init(&p, FALSE);
2051  for (i = 0; i < n; ++i)
2052  geod_polygon_addpoint(g, &p, lats[i], lons[i]);
2053  geod_polygon_compute(g, &p, FALSE, TRUE, pA, pP);
2054 }
2055 
Matrix3f m
static Matrix A1
Jet< T, N > cos(const Jet< T, N > &f)
Definition: jet.h:426
float real
Definition: datatypes.h:10
Scalar * y
unsigned geod_polygon_testedge(const struct geod_geodesic *g, const struct geod_polygon *p, double azi, double s, int reverse, int sign, double *pA, double *pP)
void geod_directline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, unsigned caps)
double geod_genposition(const struct geod_geodesicline *l, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
Scalar * b
Definition: benchVecAdd.cpp:17
static const Pose3 T3(Rot3::Rodrigues(-90, 0, 0), Point3(1, 2, 3))
void geod_gendirectline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, unsigned caps)
static const double lat
#define FALSE
Definition: ccolamd.c:751
int n
Scalar Scalar * c
Definition: benchVecAdd.cpp:17
#define M_PI
Definition: main.h:106
double lon
Definition: geodesic.h:208
Jet< T, N > sin(const Jet< T, N > &f)
Definition: jet.h:439
const Eigen::CwiseBinaryOp< Eigen::internal::scalar_pow_op< typename Derived::Scalar, typename ExponentDerived::Scalar >, const Derived, const ExponentDerived > pow(const Eigen::ArrayBase< Derived > &x, const Eigen::ArrayBase< ExponentDerived > &exponents)
void geod_polygon_addedge(const struct geod_geodesic *g, struct geod_polygon *p, double azi, double s)
unsigned num
Definition: geodesic.h:217
#define N
Definition: gksort.c:12
DiscreteKey S(1, 2)
Real fabs(const Real &a)
void geod_position(const struct geod_geodesicline *l, double s12, double *plat2, double *plon2, double *pazi2)
double f
Definition: geodesic.h:170
EIGEN_DEVICE_FUNC const LogReturnType log() const
void geod_lineinit(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned caps)
void g(const string &key, int i)
Definition: testBTree.cpp:41
void geod_setdistance(struct geod_geodesicline *l, double s13)
unsigned caps
Definition: geodesic.h:198
static double epsilon
Definition: testRot3.cpp:37
EIGEN_DEVICE_FUNC const AtanReturnType atan() const
EIGEN_DEVICE_FUNC const FloorReturnType floor() const
const double degree
static const Line3 l(Rot3(), 1, 1)
EIGEN_STRONG_INLINE EIGEN_DEVICE_FUNC bfloat16 fmod(const bfloat16 &a, const bfloat16 &b)
Definition: BFloat16.h:567
void geod_inverseline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, unsigned caps)
Array< int, Dynamic, 1 > v
EIGEN_DEVICE_FUNC const SignReturnType sign() const
double geod_geninverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2, double *pm12, double *pM12, double *pM21, double *pS12)
Eigen::Triplet< double > T
void geod_polygon_addpoint(const struct geod_geodesic *g, struct geod_polygon *p, double lat, double lon)
Definition: main.h:100
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
RealScalar s
static const double r2
EIGEN_DEVICE_FUNC const Scalar & q
void geod_polygon_clear(struct geod_polygon *p)
void geod_polygon_init(struct geod_polygon *p, int polylinep)
void geod_direct(const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, double *plat2, double *plon2, double *pazi2)
static const double r3
unsigned geod_polygon_compute(const struct geod_geodesic *g, const struct geod_polygon *p, int reverse, int sign, double *pA, double *pP)
RowVector3d w
AnnoyingScalar atan2(const AnnoyingScalar &y, const AnnoyingScalar &x)
void geod_polygonarea(const struct geod_geodesic *g, double lats[], double lons[], int n, double *pA, double *pP)
#define TRUE
Definition: ccolamd.c:750
void geod_gensetdistance(struct geod_geodesicline *l, unsigned flags, double s13_a13)
double a
Definition: geodesic.h:169
Point2 pA(size_t i)
DiscreteKey E(5, 2)
double geod_gendirect(const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
void reverse(const MatrixType &m)
unsigned geod_polygon_testpoint(const struct geod_geodesic *g, const struct geod_polygon *p, double lat, double lon, int reverse, int sign, double *pA, double *pP)
float * p
static const double lon
void geod_inverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2)
Jet< T, N > sqrt(const Jet< T, N > &f)
Definition: jet.h:418
void geod_init(struct geod_geodesic *g, double a, double f)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
double lat
Definition: geodesic.h:207
double norm2(const Point2 &p, OptionalJacobian< 1, 2 > H)
Distance of the point from the origin, with Jacobian.
Definition: Point2.cpp:27
std::ptrdiff_t j
Point2 t(10, 10)
API for the geodesic routines in C.


gtsam
Author(s):
autogenerated on Tue Jul 4 2023 02:34:17