geodesic_wgs84 1.32.17 → 1.44.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d05f76ec707266ede381b02ed6734f911f2e8af6
4
- data.tar.gz: 8a1eaba21553245498a8309dc606491839c55427
3
+ metadata.gz: c45c045313d94c86f6486192b2ab4e721e9651ca
4
+ data.tar.gz: 8b4b139acfe9387ad9ffecfe77ee29d849564ba8
5
5
  SHA512:
6
- metadata.gz: 365788de78244ea88b7294536cd72f56de439d6bef89075bd80f67e4ebfcbbb1899466c334ae80b031ecb84cbb1113e87eb27b12bb7548dfa2f37ccc88c0751a
7
- data.tar.gz: 19904afe323151bd542c10ac0a8ebb1b1ebf5c88270ba9a8bde8a86a8757b0019dfae851f088b0d36295d4c7c26017e8334d5ba2e0d058dc7fe5a9780ab596d9
6
+ metadata.gz: b623d79f1ac14608b19dfe37d07ec05889e3f6e0d4fa50b5290ca38b0fbd640cb82a204473232e3e14be165c0b63bbba18f5fbb054ddf502911758ef8114fc0b
7
+ data.tar.gz: b57d30db4536ad153f163b0ff13286ff55e4e30244f23195bb84ffa357f8fd5b19b8bb10994bb40baa041669c2ef4ec63204af57f9d5c115bc7c6483ab3fcb71
data/Makefile CHANGED
@@ -9,14 +9,14 @@ all: build
9
9
  rel: build
10
10
  vim lib/geodesic_wgs84/version.rb
11
11
  git commit -a
12
- sudo gem uninstall geodesic_wgs84 --all
12
+ gem uninstall geodesic_wgs84 --all
13
13
  rake release
14
14
 
15
15
  install: build
16
16
  git commit -a
17
- sudo gem uninstall geodesic_wgs84 --all
18
- sudo rake install
19
- sudo rm -rf pkg
17
+ gem uninstall geodesic_wgs84 --all
18
+ rake install
19
+ rm -rf pkg
20
20
 
21
21
  build:
22
22
  rake compile
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # GeodesicWgs84 -- Distance calculations on the Earth's surface
2
2
 
3
3
  This an implementation of the geodesic algorithms described in
4
- C. F. F. Karney "Algorithms for geodesics" ( http://dx.doi.org/10.1007/s00190-012-0578-z ).
4
+ C. F. F. Karney "Algorithms for geodesics" ( https://dx.doi.org/10.1007/s00190-012-0578-z ).
5
5
  It uses the WGS84 standard as a reference ( http://en.wikipedia.org/wiki/World_Geodetic_System ).
6
6
 
7
7
  ### From the abstract of this article
@@ -17,6 +17,8 @@ of geodesics to be computed.
17
17
  The files geodesic.c and geodesic.h make up for the real work and can be found
18
18
  at ( http://geographiclib.sourceforge.net/html/C/ ).
19
19
 
20
+ The version of this gem aims to follow the author's version.
21
+
20
22
  ## Installation
21
23
 
22
24
  Add this line to your application's Gemfile:
@@ -13,12 +13,12 @@
13
13
  * C. F. F. Karney,
14
14
  * Algorithms for geodesics,
15
15
  * J. Geodesy <b>87</b>, 43--55 (2013);
16
- * http://dx.doi.org/10.1007/s00190-012-0578-z
16
+ * https://dx.doi.org/10.1007/s00190-012-0578-z
17
17
  * Addenda: http://geographiclib.sf.net/geod-addenda.html
18
18
  *
19
19
  * See the comments in geodesic.h for documentation.
20
20
  *
21
- * Copyright (c) Charles Karney (2012-2013) <charles@karney.com> and licensed
21
+ * Copyright (c) Charles Karney (2012-2015) <charles@karney.com> and licensed
22
22
  * under the MIT/X11 License. For more information, see
23
23
  * http://geographiclib.sourceforge.net/
24
24
  */
@@ -27,8 +27,10 @@
27
27
  #include <math.h>
28
28
 
29
29
  #define GEOGRAPHICLIB_GEODESIC_ORDER 6
30
+ #define nA1 GEOGRAPHICLIB_GEODESIC_ORDER
30
31
  #define nC1 GEOGRAPHICLIB_GEODESIC_ORDER
31
32
  #define nC1p GEOGRAPHICLIB_GEODESIC_ORDER
33
+ #define nA2 GEOGRAPHICLIB_GEODESIC_ORDER
32
34
  #define nC2 GEOGRAPHICLIB_GEODESIC_ORDER
33
35
  #define nA3 GEOGRAPHICLIB_GEODESIC_ORDER
34
36
  #define nA3x nA3
@@ -36,6 +38,7 @@
36
38
  #define nC3x ((nC3 * (nC3 - 1)) / 2)
37
39
  #define nC4 GEOGRAPHICLIB_GEODESIC_ORDER
38
40
  #define nC4x ((nC4 * (nC4 + 1)) / 2)
41
+ #define nC (GEOGRAPHICLIB_GEODESIC_ORDER + 1)
39
42
 
40
43
  typedef double real;
41
44
  typedef int boolx;
@@ -137,6 +140,12 @@ static real sumx(real u, real v, real* t) {
137
140
  return s;
138
141
  }
139
142
 
143
+ static real polyval(int N, const real p[], real x) {
144
+ real y = N < 0 ? 0 : *p++;
145
+ while (--N >= 0) y = y * x + *p++;
146
+ return y;
147
+ }
148
+
140
149
  static real minx(real x, real y)
141
150
  { return x < y ? x : y; }
142
151
 
@@ -146,24 +155,29 @@ static real maxx(real x, real y)
146
155
  static void swapx(real* x, real* y)
147
156
  { real t = *x; *x = *y; *y = t; }
148
157
 
149
- static void SinCosNorm(real* sinx, real* cosx) {
158
+ static void norm2(real* sinx, real* cosx) {
150
159
  real r = hypotx(*sinx, *cosx);
151
160
  *sinx /= r;
152
161
  *cosx /= r;
153
162
  }
154
163
 
155
- static real AngNormalize(real x)
156
- { return x >= 180 ? x - 360 : (x < -180 ? x + 360 : x); }
157
- static real AngNormalize2(real x)
158
- { return AngNormalize(fmod(x, (real)(360))); }
164
+ static real AngNormalize(real x) {
165
+ x = fmod(x, (real)(360));
166
+ return x < -180 ? x + 360 : (x < 180 ? x : x - 360);
167
+ }
168
+
169
+ static real LatFix(real x)
170
+ { return fabs(x) > 90 ? NaN : x; }
159
171
 
160
172
  static real AngDiff(real x, real y) {
161
- real t, d = sumx(-x, y, &t);
162
- if ((d - (real)(180)) + t > (real)(0)) /* y - x > 180 */
163
- d -= (real)(360); /* exact */
164
- else if ((d + (real)(180)) + t <= (real)(0)) /* y - x <= -180 */
165
- d += (real)(360); /* exact */
166
- return d + t;
173
+ real t, d = - AngNormalize(sumx(AngNormalize(x), AngNormalize(-y), &t));
174
+ /* Here y - x = d - t (mod 360), exactly, where d is in (-180,180] and
175
+ * abs(t) <= eps (eps = 2^-45 for doubles). The only case where the
176
+ * addition of t takes the result outside the range (-180,180] is d = 180
177
+ * and t < 0. The case, d = -180 + eps, t = eps, can't happen, since
178
+ * sum would have returned the exact result in such a case (i.e., given t
179
+ * = 0). */
180
+ return (d == 180 && t < 0 ? -180 : d) - t;
167
181
  }
168
182
 
169
183
  static real AngRound(real x) {
@@ -171,7 +185,49 @@ static real AngRound(real x) {
171
185
  volatile real y = fabs(x);
172
186
  /* The compiler mustn't "simplify" z - (z - y) to y */
173
187
  y = y < z ? z - (z - y) : y;
174
- return x < 0 ? -y : y;
188
+ return x < 0 ? 0 - y : y;
189
+ }
190
+
191
+ static void sincosdx(real x, real* sinx, real* cosx) {
192
+ /* In order to minimize round-off errors, this function exactly reduces
193
+ * the argument to the range [-45, 45] before converting it to radians. */
194
+ real r, s, c; int q;
195
+ r = fmod(x, (real)(360));
196
+ q = (int)(floor(r / 90 + (real)(0.5)));
197
+ r -= 90 * q;
198
+ /* now abs(r) <= 45 */
199
+ r *= degree;
200
+ /* Possibly could call the gnu extension sincos */
201
+ s = sin(r); c = cos(r);
202
+ switch ((unsigned)q & 3U) {
203
+ case 0U: *sinx = s; *cosx = c; break;
204
+ case 1U: *sinx = c; *cosx = 0 - s; break;
205
+ case 2U: *sinx = 0 - s; *cosx = 0 - c; break;
206
+ default: *sinx = 0 - c; *cosx = s; break; /* case 3U */
207
+ }
208
+ }
209
+
210
+ static real atan2dx(real y, real x) {
211
+ /* In order to minimize round-off errors, this function rearranges the
212
+ * arguments so that result of atan2 is in the range [-pi/4, pi/4] before
213
+ * converting it to degrees and mapping the result to the correct
214
+ * quadrant. */
215
+ int q = 0; real ang;
216
+ if (fabs(y) > fabs(x)) { swapx(&x, &y); q = 2; }
217
+ if (x < 0) { x = -x; ++q; }
218
+ /* here x >= 0 and x >= abs(y), so angle is in [-pi/4, pi/4] */
219
+ ang = atan2(y, x) / degree;
220
+ switch (q) {
221
+ /* Note that atan2d(-0.0, 1.0) will return -0. However, we expect that
222
+ * atan2d will not be called with y = -0. If need be, include
223
+ *
224
+ * case 0: ang = 0 + ang; break;
225
+ */
226
+ case 1: ang = (y > 0 ? 180 : -180) - ang; break;
227
+ case 2: ang = 90 - ang; break;
228
+ case 3: ang = -90 + ang; break;
229
+ }
230
+ return ang;
175
231
  }
176
232
 
177
233
  static void A3coeff(struct geod_geodesic* g);
@@ -186,9 +242,9 @@ static void Lengths(const struct geod_geodesic* g,
186
242
  real ssig2, real csig2, real dn2,
187
243
  real cbet1, real cbet2,
188
244
  real* ps12b, real* pm12b, real* pm0,
189
- boolx scalep, real* pM12, real* pM21,
190
- /* Scratch areas of the right size */
191
- real C1a[], real C2a[]);
245
+ real* pM12, real* pM21,
246
+ /* Scratch area of the right size */
247
+ real Ca[]);
192
248
  static real Astroid(real x, real y);
193
249
  static real InverseStart(const struct geod_geodesic* g,
194
250
  real sbet1, real cbet1, real dn1,
@@ -199,8 +255,8 @@ static real InverseStart(const struct geod_geodesic* g,
199
255
  real* psalp2, real* pcalp2,
200
256
  /* Only updated for short lines */
201
257
  real* pdnm,
202
- /* Scratch areas of the right size */
203
- real C1a[], real C2a[]);
258
+ /* Scratch area of the right size */
259
+ real Ca[]);
204
260
  static real Lambda12(const struct geod_geodesic* g,
205
261
  real sbet1, real cbet1, real dn1,
206
262
  real sbet2, real cbet2, real dn2,
@@ -211,8 +267,8 @@ static real Lambda12(const struct geod_geodesic* g,
211
267
  real* pssig2, real* pcsig2,
212
268
  real* peps, real* pdomg12,
213
269
  boolx diffp, real* pdlam12,
214
- /* Scratch areas of the right size */
215
- real C1a[], real C2a[], real C3a[]);
270
+ /* Scratch area of the right size */
271
+ real Ca[]);
216
272
  static real A3f(const struct geod_geodesic* g, real eps);
217
273
  static void C3f(const struct geod_geodesic* g, real eps, real c[]);
218
274
  static void C4f(const struct geod_geodesic* g, real eps, real c[]);
@@ -222,6 +278,7 @@ static void C1pf(real eps, real c[]);
222
278
  static real A2m1f(real eps);
223
279
  static void C2f(real eps, real c[]);
224
280
  static int transit(real lon1, real lon2);
281
+ static int transitdirect(real lon1, real lon2);
225
282
  static void accini(real s[]);
226
283
  static void acccopy(const real s[], real t[]);
227
284
  static void accadd(real s[], real y);
@@ -261,7 +318,7 @@ void geod_init(struct geod_geodesic* g, real a, real f) {
261
318
  void geod_lineinit(struct geod_geodesicline* l,
262
319
  const struct geod_geodesic* g,
263
320
  real lat1, real lon1, real azi1, unsigned caps) {
264
- real alp1, cbet1, sbet1, phi, eps;
321
+ real cbet1, sbet1, eps;
265
322
  l->a = g->a;
266
323
  l->f = g->f;
267
324
  l->b = g->b;
@@ -269,25 +326,18 @@ void geod_lineinit(struct geod_geodesicline* l,
269
326
  l->f1 = g->f1;
270
327
  /* If caps is 0 assume the standard direct calculation */
271
328
  l->caps = (caps ? caps : GEOD_DISTANCE_IN | GEOD_LONGITUDE) |
272
- GEOD_LATITUDE | GEOD_AZIMUTH; /* Always allow latitude and azimuth */
329
+ /* always allow latitude and azimuth and unrolling of longitude */
330
+ GEOD_LATITUDE | GEOD_AZIMUTH | GEOD_LONG_UNROLL;
273
331
 
274
- /* Guard against underflow in salp0 */
275
- azi1 = AngRound(AngNormalize(azi1));
276
- lon1 = AngNormalize(lon1);
277
- l->lat1 = lat1;
332
+ l->lat1 = LatFix(lat1);
278
333
  l->lon1 = lon1;
279
- l->azi1 = azi1;
280
- /* alp1 is in [0, pi] */
281
- alp1 = azi1 * degree;
282
- /* Enforce sin(pi) == 0 and cos(pi/2) == 0. Better to face the ensuing
283
- * problems directly than to skirt them. */
284
- l->salp1 = azi1 == -180 ? 0 : sin(alp1);
285
- l->calp1 = fabs(azi1) == 90 ? 0 : cos(alp1);
286
- phi = lat1 * degree;
334
+ l->azi1 = AngNormalize(azi1);
335
+ /* Guard against underflow in salp0 */
336
+ sincosdx(AngRound(l->azi1), &l->salp1, &l->calp1);
337
+
338
+ sincosdx(AngRound(l->lat1), &sbet1, &cbet1); sbet1 *= l->f1;
287
339
  /* Ensure cbet1 = +epsilon at poles */
288
- sbet1 = l->f1 * sin(phi);
289
- cbet1 = fabs(lat1) == 90 ? tiny : cos(phi);
290
- SinCosNorm(&sbet1, &cbet1);
340
+ norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
291
341
  l->dn1 = sqrt(1 + g->ep2 * sq(sbet1));
292
342
 
293
343
  /* Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0), */
@@ -306,8 +356,8 @@ void geod_lineinit(struct geod_geodesicline* l,
306
356
  * With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi. */
307
357
  l->ssig1 = sbet1; l->somg1 = l->salp0 * sbet1;
308
358
  l->csig1 = l->comg1 = sbet1 != 0 || l->calp1 != 0 ? cbet1 * l->calp1 : 1;
309
- SinCosNorm(&l->ssig1, &l->csig1); /* sig1 in (-pi, pi] */
310
- /* SinCosNorm(somg1, comg1); -- don't need to normalize! */
359
+ norm2(&l->ssig1, &l->csig1); /* sig1 in (-pi, pi] */
360
+ /* norm2(somg1, comg1); -- don't need to normalize! */
311
361
 
312
362
  l->k2 = sq(l->calp0) * g->ep2;
313
363
  eps = l->k2 / (2 * (1 + sqrt(1 + l->k2)) + l->k2);
@@ -349,7 +399,7 @@ void geod_lineinit(struct geod_geodesicline* l,
349
399
  }
350
400
 
351
401
  real geod_genposition(const struct geod_geodesicline* l,
352
- boolx arcmode, real s12_a12,
402
+ unsigned flags, real s12_a12,
353
403
  real* plat2, real* plon2, real* pazi2,
354
404
  real* ps12, real* pm12,
355
405
  real* pM12, real* pM21,
@@ -371,18 +421,14 @@ real geod_genposition(const struct geod_geodesicline* l,
371
421
 
372
422
  outmask &= l->caps & OUT_ALL;
373
423
  if (!( TRUE /*Init()*/ &&
374
- (arcmode || (l->caps & GEOD_DISTANCE_IN & OUT_ALL)) ))
424
+ (flags & GEOD_ARCMODE || (l->caps & GEOD_DISTANCE_IN & OUT_ALL)) ))
375
425
  /* Uninitialized or impossible distance calculation requested */
376
426
  return NaN;
377
427
 
378
- if (arcmode) {
379
- real s12a;
428
+ if (flags & GEOD_ARCMODE) {
380
429
  /* Interpret s12_a12 as spherical arc length */
381
430
  sig12 = s12_a12 * degree;
382
- s12a = fabs(s12_a12);
383
- s12a -= 180 * floor(s12a / 180);
384
- ssig12 = s12a == 0 ? 0 : sin(sig12);
385
- csig12 = s12a == 90 ? 0 : cos(sig12);
431
+ sincosdx(s12_a12, &ssig12, &csig12);
386
432
  } else {
387
433
  /* Interpret s12_a12 as distance */
388
434
  real
@@ -435,7 +481,7 @@ real geod_genposition(const struct geod_geodesicline* l,
435
481
  csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
436
482
  dn2 = sqrt(1 + l->k2 * sq(ssig2));
437
483
  if (outmask & (GEOD_DISTANCE | GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) {
438
- if (arcmode || fabs(l->f) > 0.01)
484
+ if (flags & GEOD_ARCMODE || fabs(l->f) > 0.01)
439
485
  B12 = SinCosSeries(TRUE, ssig2, csig2, l->C1a, nC1);
440
486
  AB1 = (1 + l->A1m1) * (B12 - l->B11);
441
487
  }
@@ -446,34 +492,36 @@ real geod_genposition(const struct geod_geodesicline* l,
446
492
  if (cbet2 == 0)
447
493
  /* I.e., salp0 = 0, csig2 = 0. Break the degeneracy in this case */
448
494
  cbet2 = csig2 = tiny;
449
- /* tan(omg2) = sin(alp0) * tan(sig2) */
450
- somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */
451
495
  /* tan(alp0) = cos(sig2)*tan(alp2) */
452
496
  salp2 = l->salp0; calp2 = l->calp0 * csig2; /* No need to normalize */
453
- /* omg12 = omg2 - omg1 */
454
- omg12 = atan2(somg2 * l->comg1 - comg2 * l->somg1,
455
- comg2 * l->comg1 + somg2 * l->somg1);
456
497
 
457
498
  if (outmask & GEOD_DISTANCE)
458
- s12 = arcmode ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12;
499
+ s12 = flags & GEOD_ARCMODE ? l->b * ((1 + l->A1m1) * sig12 + AB1) : s12_a12;
459
500
 
460
501
  if (outmask & GEOD_LONGITUDE) {
502
+ int E = l->salp0 < 0 ? -1 : 1; /* east or west going? */
503
+ /* tan(omg2) = sin(alp0) * tan(sig2) */
504
+ somg2 = l->salp0 * ssig2; comg2 = csig2; /* No need to normalize */
505
+ /* omg12 = omg2 - omg1 */
506
+ omg12 = flags & GEOD_LONG_UNROLL
507
+ ? E * (sig12
508
+ - (atan2( ssig2, csig2) - atan2( l->ssig1, l->csig1))
509
+ + (atan2(E * somg2, comg2) - atan2(E * l->somg1, l->comg1)))
510
+ : atan2(somg2 * l->comg1 - comg2 * l->somg1,
511
+ comg2 * l->comg1 + somg2 * l->somg1);
461
512
  lam12 = omg12 + l->A3c *
462
513
  ( sig12 + (SinCosSeries(TRUE, ssig2, csig2, l->C3a, nC3-1)
463
514
  - l->B31));
464
515
  lon12 = lam12 / degree;
465
- /* Use AngNormalize2 because longitude might have wrapped multiple
466
- * times. */
467
- lon12 = AngNormalize2(lon12);
468
- lon2 = AngNormalize(l->lon1 + lon12);
516
+ lon2 = flags & GEOD_LONG_UNROLL ? l->lon1 + lon12 :
517
+ AngNormalize(AngNormalize(l->lon1) + AngNormalize(lon12));
469
518
  }
470
519
 
471
520
  if (outmask & GEOD_LATITUDE)
472
- lat2 = atan2(sbet2, l->f1 * cbet2) / degree;
521
+ lat2 = atan2dx(sbet2, l->f1 * cbet2);
473
522
 
474
523
  if (outmask & GEOD_AZIMUTH)
475
- /* minus signs give range [-180, 180). 0- converts -0 to +0. */
476
- azi2 = 0 - atan2(-salp2, calp2) / degree;
524
+ azi2 = atan2dx(salp2, calp2);
477
525
 
478
526
  if (outmask & (GEOD_REDUCEDLENGTH | GEOD_GEODESICSCALE)) {
479
527
  real
@@ -497,7 +545,7 @@ real geod_genposition(const struct geod_geodesicline* l,
497
545
  B42 = SinCosSeries(FALSE, ssig2, csig2, l->C4a, nC4);
498
546
  real salp12, calp12;
499
547
  if (l->calp0 == 0 || l->salp0 == 0) {
500
- /* alp12 = alp2 - alp1, used in atan2 so no need to normalized */
548
+ /* alp12 = alp2 - alp1, used in atan2 so no need to normalize */
501
549
  salp12 = salp2 * l->calp1 - calp2 * l->salp1;
502
550
  calp12 = calp2 * l->calp1 + salp2 * l->salp1;
503
551
  /* The right thing appears to happen if alp1 = +/-180 and alp2 = 0, viz
@@ -542,7 +590,7 @@ real geod_genposition(const struct geod_geodesicline* l,
542
590
  if (outmask & GEOD_AREA)
543
591
  *pS12 = S12;
544
592
 
545
- return arcmode ? s12_a12 : sig12 / degree;
593
+ return flags & GEOD_ARCMODE ? s12_a12 : sig12 / degree;
546
594
  }
547
595
 
548
596
  void geod_position(const struct geod_geodesicline* l, real s12,
@@ -552,7 +600,7 @@ void geod_position(const struct geod_geodesicline* l, real s12,
552
600
 
553
601
  real geod_gendirect(const struct geod_geodesic* g,
554
602
  real lat1, real lon1, real azi1,
555
- boolx arcmode, real s12_a12,
603
+ unsigned flags, real s12_a12,
556
604
  real* plat2, real* plon2, real* pazi2,
557
605
  real* ps12, real* pm12, real* pM12, real* pM21,
558
606
  real* pS12) {
@@ -568,8 +616,9 @@ real geod_gendirect(const struct geod_geodesic* g,
568
616
 
569
617
  geod_lineinit(&l, g, lat1, lon1, azi1,
570
618
  /* Automatically supply GEOD_DISTANCE_IN if necessary */
571
- outmask | (arcmode ? GEOD_NONE : GEOD_DISTANCE_IN));
572
- return geod_genposition(&l, arcmode, s12_a12,
619
+ outmask |
620
+ (flags & GEOD_ARCMODE ? GEOD_NONE : GEOD_DISTANCE_IN));
621
+ return geod_genposition(&l, flags, s12_a12,
573
622
  plat2, plon2, pazi2, ps12, pm12, pM12, pM21, pS12);
574
623
  }
575
624
 
@@ -577,7 +626,7 @@ void geod_direct(const struct geod_geodesic* g,
577
626
  real lat1, real lon1, real azi1,
578
627
  real s12,
579
628
  real* plat2, real* plon2, real* pazi2) {
580
- geod_gendirect(g, lat1, lon1, azi1, FALSE, s12, plat2, plon2, pazi2,
629
+ geod_gendirect(g, lat1, lon1, azi1, GEOD_NOFLAGS, s12, plat2, plon2, pazi2,
581
630
  0, 0, 0, 0, 0);
582
631
  }
583
632
 
@@ -588,11 +637,10 @@ real geod_geninverse(const struct geod_geodesic* g,
588
637
  real s12 = 0, azi1 = 0, azi2 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0;
589
638
  real lon12;
590
639
  int latsign, lonsign, swapp;
591
- real phi, sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
640
+ real sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
592
641
  real dn1, dn2, lam12, slam12, clam12;
593
642
  real a12 = 0, sig12, calp1 = 0, salp1 = 0, calp2 = 0, salp2 = 0;
594
- /* index zero elements of these arrays are unused */
595
- real C1a[nC1 + 1], C2a[nC2 + 1], C3a[nC3];
643
+ real Ca[nC];
596
644
  boolx meridian;
597
645
  real omg12 = 0;
598
646
 
@@ -607,15 +655,14 @@ real geod_geninverse(const struct geod_geodesic* g,
607
655
  /* Compute longitude difference (AngDiff does this carefully). Result is
608
656
  * in [-180, 180] but -180 is only for west-going geodesics. 180 is for
609
657
  * east-going and meridional geodesics. */
610
- lon12 = AngDiff(AngNormalize(lon1), AngNormalize(lon2));
611
658
  /* If very close to being on the same half-meridian, then make it so. */
612
- lon12 = AngRound(lon12);
659
+ lon12 = AngRound(AngDiff(lon1, lon2));
613
660
  /* Make longitude difference positive. */
614
661
  lonsign = lon12 >= 0 ? 1 : -1;
615
662
  lon12 *= lonsign;
616
663
  /* If really close to the equator, treat as on equator. */
617
- lat1 = AngRound(lat1);
618
- lat2 = AngRound(lat2);
664
+ lat1 = AngRound(LatFix(lat1));
665
+ lat2 = AngRound(LatFix(lat2));
619
666
  /* Swap points so that point with higher (abs) latitude is point 1 */
620
667
  swapp = fabs(lat1) >= fabs(lat2) ? 1 : -1;
621
668
  if (swapp < 0) {
@@ -638,17 +685,13 @@ real geod_geninverse(const struct geod_geodesic* g,
638
685
  * check, e.g., on verifying quadrants in atan2. In addition, this
639
686
  * enforces some symmetries in the results returned. */
640
687
 
641
- phi = lat1 * degree;
688
+ sincosdx(lat1, &sbet1, &cbet1); sbet1 *= g->f1;
642
689
  /* Ensure cbet1 = +epsilon at poles */
643
- sbet1 = g->f1 * sin(phi);
644
- cbet1 = lat1 == -90 ? tiny : cos(phi);
645
- SinCosNorm(&sbet1, &cbet1);
690
+ norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
646
691
 
647
- phi = lat2 * degree;
692
+ sincosdx(lat2, &sbet2, &cbet2); sbet2 *= g->f1;
648
693
  /* Ensure cbet2 = +epsilon at poles */
649
- sbet2 = g->f1 * sin(phi);
650
- cbet2 = fabs(lat2) == 90 ? tiny : cos(phi);
651
- SinCosNorm(&sbet2, &cbet2);
694
+ norm2(&sbet2, &cbet2); cbet2 = maxx(tiny, cbet2);
652
695
 
653
696
  /* If cbet1 < -sbet1, then cbet2 - cbet1 is a sensitive measure of the
654
697
  * |bet1| - |bet2|. Alternatively (cbet1 >= -sbet1), abs(sbet2) + sbet1 is
@@ -670,8 +713,7 @@ real geod_geninverse(const struct geod_geodesic* g,
670
713
  dn2 = sqrt(1 + g->ep2 * sq(sbet2));
671
714
 
672
715
  lam12 = lon12 * degree;
673
- slam12 = lon12 == 180 ? 0 : sin(lam12);
674
- clam12 = cos(lam12); /* lon12 == 90 isn't interesting */
716
+ sincosdx(lon12, &slam12, &clam12);
675
717
 
676
718
  meridian = lat1 == -90 || slam12 == 0;
677
719
 
@@ -691,20 +733,22 @@ real geod_geninverse(const struct geod_geodesic* g,
691
733
  /* sig12 = sig2 - sig1 */
692
734
  sig12 = atan2(maxx(csig1 * ssig2 - ssig1 * csig2, (real)(0)),
693
735
  csig1 * csig2 + ssig1 * ssig2);
694
- {
695
- real dummy;
696
- Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
697
- cbet1, cbet2, &s12x, &m12x, &dummy,
698
- (outmask & GEOD_GEODESICSCALE) != 0U, &M12, &M21, C1a, C2a);
699
- }
736
+ Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
737
+ cbet1, cbet2, &s12x, &m12x, 0,
738
+ outmask & GEOD_GEODESICSCALE ? &M12 : 0,
739
+ outmask & GEOD_GEODESICSCALE ? &M21 : 0,
740
+ Ca);
700
741
  /* Add the check for sig12 since zero length geodesics might yield m12 <
701
742
  * 0. Test case was
702
743
  *
703
- * echo 20.001 0 20.001 0 | Geod -i
744
+ * echo 20.001 0 20.001 0 | GeodSolve -i
704
745
  *
705
746
  * In fact, we will have sig12 > pi/2 for meridional geodesic which is
706
747
  * not a shortest path. */
707
748
  if (sig12 < 1 || m12x >= 0) {
749
+ /* Need at least 2, to handle 90 0 90 180 */
750
+ if (sig12 < 3 * tiny)
751
+ sig12 = m12x = s12x = 0;
708
752
  m12x *= g->b;
709
753
  s12x *= g->b;
710
754
  a12 = sig12 / degree;
@@ -737,7 +781,7 @@ real geod_geninverse(const struct geod_geodesic* g,
737
781
  sig12 = InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2,
738
782
  lam12,
739
783
  &salp1, &calp1, &salp2, &calp2, &dnm,
740
- C1a, C2a);
784
+ Ca);
741
785
 
742
786
  if (sig12 >= 0) {
743
787
  /* Short lines (InverseStart sets salp2, calp2, dnm) */
@@ -768,10 +812,10 @@ real geod_geninverse(const struct geod_geodesic* g,
768
812
  for (tripn = FALSE, tripb = FALSE; numit < maxit2; ++numit) {
769
813
  /* the WGS84 test set: mean = 1.47, sd = 1.25, max = 16
770
814
  * WGS84 and random input: mean = 2.85, sd = 0.60 */
771
- real dv,
815
+ real dv = 0,
772
816
  v = (Lambda12(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
773
817
  &salp2, &calp2, &sig12, &ssig1, &csig1, &ssig2, &csig2,
774
- &eps, &omg12, numit < maxit1, &dv, C1a, C2a, C3a)
818
+ &eps, &omg12, numit < maxit1, &dv, Ca)
775
819
  - lam12);
776
820
  /* 2 * tol0 is approximately 1 ulp for a number in [0, pi]. */
777
821
  /* Reversed test to allow escape with NaNs */
@@ -790,7 +834,7 @@ real geod_geninverse(const struct geod_geodesic* g,
790
834
  if (nsalp1 > 0 && fabs(dalp1) < pi) {
791
835
  calp1 = calp1 * cdalp1 - salp1 * sdalp1;
792
836
  salp1 = nsalp1;
793
- SinCosNorm(&salp1, &calp1);
837
+ norm2(&salp1, &calp1);
794
838
  /* In some regimes we don't get quadratic convergence because
795
839
  * slope -> 0. So use convergence conditions based on epsilon
796
840
  * instead of sqrt(epsilon). */
@@ -808,17 +852,15 @@ real geod_geninverse(const struct geod_geodesic* g,
808
852
  * WGS84 and random input: mean = 4.74, sd = 0.99 */
809
853
  salp1 = (salp1a + salp1b)/2;
810
854
  calp1 = (calp1a + calp1b)/2;
811
- SinCosNorm(&salp1, &calp1);
855
+ norm2(&salp1, &calp1);
812
856
  tripn = FALSE;
813
857
  tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb ||
814
858
  fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb);
815
859
  }
816
- {
817
- real dummy;
818
- Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
819
- cbet1, cbet2, &s12x, &m12x, &dummy,
820
- (outmask & GEOD_GEODESICSCALE) != 0U, &M12, &M21, C1a, C2a);
821
- }
860
+ Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
861
+ cbet1, cbet2, &s12x, &m12x, 0,
862
+ outmask & GEOD_GEODESICSCALE ? &M12 : 0,
863
+ outmask & GEOD_GEODESICSCALE ? &M21 : 0, Ca);
822
864
  m12x *= g->b;
823
865
  s12x *= g->b;
824
866
  a12 = sig12 / degree;
@@ -847,13 +889,12 @@ real geod_geninverse(const struct geod_geodesic* g,
847
889
  eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
848
890
  /* Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0). */
849
891
  A4 = sq(g->a) * calp0 * salp0 * g->e2;
850
- real C4a[nC4];
851
892
  real B41, B42;
852
- SinCosNorm(&ssig1, &csig1);
853
- SinCosNorm(&ssig2, &csig2);
854
- C4f(g, eps, C4a);
855
- B41 = SinCosSeries(FALSE, ssig1, csig1, C4a, nC4);
856
- B42 = SinCosSeries(FALSE, ssig2, csig2, C4a, nC4);
893
+ norm2(&ssig1, &csig1);
894
+ norm2(&ssig2, &csig2);
895
+ C4f(g, eps, Ca);
896
+ B41 = SinCosSeries(FALSE, ssig1, csig1, Ca, nC4);
897
+ B42 = SinCosSeries(FALSE, ssig2, csig2, Ca, nC4);
857
898
  S12 = A4 * (B42 - B41);
858
899
  } else
859
900
  /* Avoid problems with indeterminate sig1, sig2 on equator */
@@ -904,8 +945,8 @@ real geod_geninverse(const struct geod_geodesic* g,
904
945
 
905
946
  if (outmask & GEOD_AZIMUTH) {
906
947
  /* minus signs give range [-180, 180). 0- converts -0 to +0. */
907
- azi1 = 0 - atan2(-salp1, calp1) / degree;
908
- azi2 = 0 - atan2(-salp2, calp2) / degree;
948
+ azi1 = atan2dx(salp1, calp1);
949
+ azi2 = atan2dx(salp2, calp2);
909
950
  }
910
951
 
911
952
  if (outmask & GEOD_DISTANCE)
@@ -961,42 +1002,58 @@ void Lengths(const struct geod_geodesic* g,
961
1002
  real ssig2, real csig2, real dn2,
962
1003
  real cbet1, real cbet2,
963
1004
  real* ps12b, real* pm12b, real* pm0,
964
- boolx scalep, real* pM12, real* pM21,
965
- /* Scratch areas of the right size */
966
- real C1a[], real C2a[]) {
967
- real s12b = 0, m12b = 0, m0 = 0, M12 = 0, M21 = 0;
968
- real A1m1, AB1, A2m1, AB2, J12;
1005
+ real* pM12, real* pM21,
1006
+ /* Scratch area of the right size */
1007
+ real Ca[]) {
1008
+ real m0 = 0, J12 = 0, A1 = 0, A2 = 0;
1009
+ real Cb[nC];
969
1010
 
970
1011
  /* Return m12b = (reduced length)/b; also calculate s12b = distance/b,
971
1012
  * and m0 = coefficient of secular term in expression for reduced length. */
972
- C1f(eps, C1a);
973
- C2f(eps, C2a);
974
- A1m1 = A1m1f(eps);
975
- AB1 = (1 + A1m1) * (SinCosSeries(TRUE, ssig2, csig2, C1a, nC1) -
976
- SinCosSeries(TRUE, ssig1, csig1, C1a, nC1));
977
- A2m1 = A2m1f(eps);
978
- AB2 = (1 + A2m1) * (SinCosSeries(TRUE, ssig2, csig2, C2a, nC2) -
979
- SinCosSeries(TRUE, ssig1, csig1, C2a, nC2));
980
- m0 = A1m1 - A2m1;
981
- J12 = m0 * sig12 + (AB1 - AB2);
982
- /* Missing a factor of b.
983
- * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure accurate
984
- * cancellation in the case of coincident points. */
985
- m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) - csig1 * csig2 * J12;
986
- /* Missing a factor of b */
987
- s12b = (1 + A1m1) * sig12 + AB1;
988
- if (scalep) {
1013
+ boolx redlp = pm12b || pm0 || pM12 || pM21;
1014
+ if (ps12b || redlp) {
1015
+ A1 = A1m1f(eps);
1016
+ C1f(eps, Ca);
1017
+ if (redlp) {
1018
+ A2 = A2m1f(eps);
1019
+ C2f(eps, Cb);
1020
+ m0 = A1 - A2;
1021
+ A2 = 1 + A2;
1022
+ }
1023
+ A1 = 1 + A1;
1024
+ }
1025
+ if (ps12b) {
1026
+ real B1 = SinCosSeries(TRUE, ssig2, csig2, Ca, nC1) -
1027
+ SinCosSeries(TRUE, ssig1, csig1, Ca, nC1);
1028
+ /* Missing a factor of b */
1029
+ *ps12b = A1 * (sig12 + B1);
1030
+ if (redlp) {
1031
+ real B2 = SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
1032
+ SinCosSeries(TRUE, ssig1, csig1, Cb, nC2);
1033
+ J12 = m0 * sig12 + (A1 * B1 - A2 * B2);
1034
+ }
1035
+ } else if (redlp) {
1036
+ /* Assume here that nC1 >= nC2 */
1037
+ int l;
1038
+ for (l = 1; l <= nC2; ++l)
1039
+ Cb[l] = A1 * Ca[l] - A2 * Cb[l];
1040
+ J12 = m0 * sig12 + (SinCosSeries(TRUE, ssig2, csig2, Cb, nC2) -
1041
+ SinCosSeries(TRUE, ssig1, csig1, Cb, nC2));
1042
+ }
1043
+ if (pm0) *pm0 = m0;
1044
+ if (pm12b)
1045
+ /* Missing a factor of b.
1046
+ * Add parens around (csig1 * ssig2) and (ssig1 * csig2) to ensure
1047
+ * accurate cancellation in the case of coincident points. */
1048
+ *pm12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
1049
+ csig1 * csig2 * J12;
1050
+ if (pM12 || pM21) {
989
1051
  real csig12 = csig1 * csig2 + ssig1 * ssig2;
990
1052
  real t = g->ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
991
- M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
992
- M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
993
- }
994
- *ps12b = s12b;
995
- *pm12b = m12b;
996
- *pm0 = m0;
997
- if (scalep) {
998
- *pM12 = M12;
999
- *pM21 = M21;
1053
+ if (pM12)
1054
+ *pM12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
1055
+ if (pM21)
1056
+ *pM21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
1000
1057
  }
1001
1058
  }
1002
1059
 
@@ -1015,7 +1072,7 @@ real Astroid(real x, real y) {
1015
1072
  S = p * q / 4, /* S = r^3 * s */
1016
1073
  r2 = sq(r),
1017
1074
  r3 = r * r2,
1018
- /* The discrimant of the quadratic equation for T3. This is zero on
1075
+ /* The discriminant of the quadratic equation for T3. This is zero on
1019
1076
  * the evolute curve p^(1/3)+q^(1/3) = 1 */
1020
1077
  disc = S * (S + 2 * r3);
1021
1078
  real u = r;
@@ -1061,8 +1118,8 @@ real InverseStart(const struct geod_geodesic* g,
1061
1118
  real* psalp2, real* pcalp2,
1062
1119
  /* Only updated for short lines */
1063
1120
  real* pdnm,
1064
- /* Scratch areas of the right size */
1065
- real C1a[], real C2a[]) {
1121
+ /* Scratch area of the right size */
1122
+ real Ca[]) {
1066
1123
  real salp1 = 0, calp1 = 0, salp2 = 0, calp2 = 0, dnm = 0;
1067
1124
 
1068
1125
  /* Return a starting point for Newton's method in salp1 and calp1 (function
@@ -1073,6 +1130,10 @@ real InverseStart(const struct geod_geodesic* g,
1073
1130
  /* bet12 = bet2 - bet1 in [0, pi); bet12a = bet2 + bet1 in (-pi, 0] */
1074
1131
  sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
1075
1132
  cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
1133
+ real sbet12a;
1134
+ boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) &&
1135
+ cbet2 * lam12 < (real)(0.5);
1136
+ real omg12 = lam12, somg12, comg12, ssig12, csig12;
1076
1137
  #if defined(__GNUC__) && __GNUC__ == 4 && \
1077
1138
  (__GNUC_MINOR__ < 6 || defined(__MINGW32__))
1078
1139
  /* Volatile declaration needed to fix inverse cases
@@ -1081,18 +1142,14 @@ real InverseStart(const struct geod_geodesic* g,
1081
1142
  * 89.333123580033 0 -89.333123580032997687 179.99295812360148422
1082
1143
  * which otherwise fail with g++ 4.4.4 x86 -O3 (Linux)
1083
1144
  * and g++ 4.4.0 (mingw) and g++ 4.6.1 (tdm mingw). */
1084
- real sbet12a;
1085
1145
  {
1086
1146
  volatile real xx1 = sbet2 * cbet1;
1087
1147
  volatile real xx2 = cbet2 * sbet1;
1088
1148
  sbet12a = xx1 + xx2;
1089
1149
  }
1090
1150
  #else
1091
- real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
1151
+ sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
1092
1152
  #endif
1093
- boolx shortline = cbet12 >= 0 && sbet12 < (real)(0.5) &&
1094
- cbet2 * lam12 < (real)(0.5);
1095
- real omg12 = lam12, somg12, comg12, ssig12, csig12;
1096
1153
  if (shortline) {
1097
1154
  real sbetm2 = sq(sbet1 + sbet2);
1098
1155
  /* sin((bet1+bet2)/2)^2
@@ -1116,7 +1173,7 @@ real InverseStart(const struct geod_geodesic* g,
1116
1173
  salp2 = cbet1 * somg12;
1117
1174
  calp2 = sbet12 - cbet1 * sbet2 *
1118
1175
  (comg12 >= 0 ? sq(somg12) / (1 + comg12) : 1 - comg12);
1119
- SinCosNorm(&salp2, &calp2);
1176
+ norm2(&salp2, &calp2);
1120
1177
  /* Set return value */
1121
1178
  sig12 = atan2(ssig12, csig12);
1122
1179
  } else if (fabs(g->n) > (real)(0.1) || /* No astroid calc if too eccentric */
@@ -1148,13 +1205,12 @@ real InverseStart(const struct geod_geodesic* g,
1148
1205
  real
1149
1206
  cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
1150
1207
  bet12a = atan2(sbet12a, cbet12a);
1151
- real m12b, m0, dummy;
1208
+ real m12b, m0;
1152
1209
  /* In the case of lon12 = 180, this repeats a calculation made in
1153
1210
  * Inverse. */
1154
1211
  Lengths(g, g->n, pi + bet12a,
1155
1212
  sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
1156
- cbet1, cbet2, &dummy, &m12b, &m0, FALSE,
1157
- &dummy, &dummy, C1a, C2a);
1213
+ cbet1, cbet2, 0, &m12b, &m0, 0, 0, Ca);
1158
1214
  x = -1 + m12b / (cbet1 * cbet2 * m0 * pi);
1159
1215
  betscale = x < -(real)(0.01) ? sbet12a / x :
1160
1216
  -g->f * sq(cbet1) * pi;
@@ -1214,8 +1270,9 @@ real InverseStart(const struct geod_geodesic* g,
1214
1270
  calp1 = sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
1215
1271
  }
1216
1272
  }
1217
- if (salp1 > 0) /* Sanity check on starting guess */
1218
- SinCosNorm(&salp1, &calp1);
1273
+ /* Sanity check on starting guess. Backwards check allows NaN through. */
1274
+ if (!(salp1 <= 0))
1275
+ norm2(&salp1, &calp1);
1219
1276
  else {
1220
1277
  salp1 = 1; calp1 = 0;
1221
1278
  }
@@ -1241,8 +1298,8 @@ real Lambda12(const struct geod_geodesic* g,
1241
1298
  real* pssig2, real* pcsig2,
1242
1299
  real* peps, real* pdomg12,
1243
1300
  boolx diffp, real* pdlam12,
1244
- /* Scratch areas of the right size */
1245
- real C1a[], real C2a[], real C3a[]) {
1301
+ /* Scratch area of the right size */
1302
+ real Ca[]) {
1246
1303
  real salp2 = 0, calp2 = 0, sig12 = 0,
1247
1304
  ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0, dlam12 = 0;
1248
1305
  real salp0, calp0;
@@ -1262,8 +1319,8 @@ real Lambda12(const struct geod_geodesic* g,
1262
1319
  * tan(omg1) = sin(alp0) * tan(sig1) = tan(omg1)=tan(alp1)*sin(bet1) */
1263
1320
  ssig1 = sbet1; somg1 = salp0 * sbet1;
1264
1321
  csig1 = comg1 = calp1 * cbet1;
1265
- SinCosNorm(&ssig1, &csig1);
1266
- /* SinCosNorm(&somg1, &comg1); -- don't need to normalize! */
1322
+ norm2(&ssig1, &csig1);
1323
+ /* norm2(&somg1, &comg1); -- don't need to normalize! */
1267
1324
 
1268
1325
  /* Enforce symmetries in the case abs(bet2) = -bet1. Need to be careful
1269
1326
  * about this case, since this can yield singularities in the Newton
@@ -1284,8 +1341,8 @@ real Lambda12(const struct geod_geodesic* g,
1284
1341
  * tan(omg2) = sin(alp0) * tan(sig2). */
1285
1342
  ssig2 = sbet2; somg2 = salp0 * sbet2;
1286
1343
  csig2 = comg2 = calp2 * cbet2;
1287
- SinCosNorm(&ssig2, &csig2);
1288
- /* SinCosNorm(&somg2, &comg2); -- don't need to normalize! */
1344
+ norm2(&ssig2, &csig2);
1345
+ /* norm2(&somg2, &comg2); -- don't need to normalize! */
1289
1346
 
1290
1347
  /* sig12 = sig2 - sig1, limit to [0, pi] */
1291
1348
  sig12 = atan2(maxx(csig1 * ssig2 - ssig1 * csig2, (real)(0)),
@@ -1296,9 +1353,9 @@ real Lambda12(const struct geod_geodesic* g,
1296
1353
  comg1 * comg2 + somg1 * somg2);
1297
1354
  k2 = sq(calp0) * g->ep2;
1298
1355
  eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
1299
- C3f(g, eps, C3a);
1300
- B312 = (SinCosSeries(TRUE, ssig2, csig2, C3a, nC3-1) -
1301
- SinCosSeries(TRUE, ssig1, csig1, C3a, nC3-1));
1356
+ C3f(g, eps, Ca);
1357
+ B312 = (SinCosSeries(TRUE, ssig2, csig2, Ca, nC3-1) -
1358
+ SinCosSeries(TRUE, ssig1, csig1, Ca, nC3-1));
1302
1359
  h0 = -g->f * A3f(g, eps);
1303
1360
  domg12 = salp0 * h0 * (sig12 + B312);
1304
1361
  lam12 = omg12 + domg12;
@@ -1307,10 +1364,8 @@ real Lambda12(const struct geod_geodesic* g,
1307
1364
  if (calp2 == 0)
1308
1365
  dlam12 = - 2 * g->f1 * dn1 / sbet1;
1309
1366
  else {
1310
- real dummy;
1311
1367
  Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1312
- cbet1, cbet2, &dummy, &dlam12, &dummy,
1313
- FALSE, &dummy, &dummy, C1a, C2a);
1368
+ cbet1, cbet2, 0, &dlam12, 0, 0, 0, Ca);
1314
1369
  dlam12 *= g->f1 / (calp2 * cbet2);
1315
1370
  }
1316
1371
  }
@@ -1331,177 +1386,264 @@ real Lambda12(const struct geod_geodesic* g,
1331
1386
  }
1332
1387
 
1333
1388
  real A3f(const struct geod_geodesic* g, real eps) {
1334
- /* Evaluate sum(A3x[k] * eps^k, k, 0, nA3x-1) by Horner's method */
1335
- real v = 0;
1336
- int i;
1337
- for (i = nA3x; i; )
1338
- v = eps * v + g->A3x[--i];
1339
- return v;
1389
+ /* Evaluate A3 */
1390
+ return polyval(nA3 - 1, g->A3x, eps);
1340
1391
  }
1341
1392
 
1342
1393
  void C3f(const struct geod_geodesic* g, real eps, real c[]) {
1343
- /* Evaluate C3 coeffs by Horner's method
1394
+ /* Evaluate C3 coeffs
1344
1395
  * Elements c[1] thru c[nC3 - 1] are set */
1345
- int i, j, k;
1346
1396
  real mult = 1;
1347
- for (j = nC3x, k = nC3 - 1; k; ) {
1348
- real t = 0;
1349
- for (i = nC3 - k; i; --i)
1350
- t = eps * t + g->C3x[--j];
1351
- c[k--] = t;
1352
- }
1353
-
1354
- for (k = 1; k < nC3; ) {
1397
+ int o = 0, l;
1398
+ for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */
1399
+ int m = nC3 - l - 1; /* order of polynomial in eps */
1355
1400
  mult *= eps;
1356
- c[k++] *= mult;
1401
+ c[l] = mult * polyval(m, g->C3x + o, eps);
1402
+ o += m + 1;
1357
1403
  }
1358
1404
  }
1359
1405
 
1360
1406
  void C4f(const struct geod_geodesic* g, real eps, real c[]) {
1361
- /* Evaluate C4 coeffs by Horner's method
1407
+ /* Evaluate C4 coeffs
1362
1408
  * Elements c[0] thru c[nC4 - 1] are set */
1363
- int i, j, k;
1364
1409
  real mult = 1;
1365
- for (j = nC4x, k = nC4; k; ) {
1366
- real t = 0;
1367
- for (i = nC4 - k + 1; i; --i)
1368
- t = eps * t + g->C4x[--j];
1369
- c[--k] = t;
1370
- }
1371
-
1372
- for (k = 1; k < nC4; ) {
1410
+ int o = 0, l;
1411
+ for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */
1412
+ int m = nC4 - l - 1; /* order of polynomial in eps */
1413
+ c[l] = mult * polyval(m, g->C4x + o, eps);
1414
+ o += m + 1;
1373
1415
  mult *= eps;
1374
- c[k++] *= mult;
1375
1416
  }
1376
1417
  }
1377
1418
 
1378
- /* Generated by Maxima on 2010-09-04 10:26:17-04:00 */
1379
-
1380
1419
  /* The scale factor A1-1 = mean value of (d/dsigma)I1 - 1 */
1381
1420
  real A1m1f(real eps) {
1382
- real
1383
- eps2 = sq(eps),
1384
- t = eps2*(eps2*(eps2+4)+64)/256;
1421
+ static const real coeff[] = {
1422
+ /* (1-eps)*A1-1, polynomial in eps2 of order 3 */
1423
+ 1, 4, 64, 0, 256,
1424
+ };
1425
+ int m = nA1/2;
1426
+ real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1385
1427
  return (t + eps) / (1 - eps);
1386
1428
  }
1387
1429
 
1388
1430
  /* The coefficients C1[l] in the Fourier expansion of B1 */
1389
1431
  void C1f(real eps, real c[]) {
1432
+ static const real coeff[] = {
1433
+ /* C1[1]/eps^1, polynomial in eps2 of order 2 */
1434
+ -1, 6, -16, 32,
1435
+ /* C1[2]/eps^2, polynomial in eps2 of order 2 */
1436
+ -9, 64, -128, 2048,
1437
+ /* C1[3]/eps^3, polynomial in eps2 of order 1 */
1438
+ 9, -16, 768,
1439
+ /* C1[4]/eps^4, polynomial in eps2 of order 1 */
1440
+ 3, -5, 512,
1441
+ /* C1[5]/eps^5, polynomial in eps2 of order 0 */
1442
+ -7, 1280,
1443
+ /* C1[6]/eps^6, polynomial in eps2 of order 0 */
1444
+ -7, 2048,
1445
+ };
1390
1446
  real
1391
1447
  eps2 = sq(eps),
1392
1448
  d = eps;
1393
- c[1] = d*((6-eps2)*eps2-16)/32;
1394
- d *= eps;
1395
- c[2] = d*((64-9*eps2)*eps2-128)/2048;
1396
- d *= eps;
1397
- c[3] = d*(9*eps2-16)/768;
1398
- d *= eps;
1399
- c[4] = d*(3*eps2-5)/512;
1400
- d *= eps;
1401
- c[5] = -7*d/1280;
1402
- d *= eps;
1403
- c[6] = -7*d/2048;
1449
+ int o = 0, l;
1450
+ for (l = 1; l <= nC1; ++l) { /* l is index of C1p[l] */
1451
+ int m = (nC1 - l) / 2; /* order of polynomial in eps^2 */
1452
+ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1453
+ o += m + 2;
1454
+ d *= eps;
1455
+ }
1404
1456
  }
1405
1457
 
1406
1458
  /* The coefficients C1p[l] in the Fourier expansion of B1p */
1407
1459
  void C1pf(real eps, real c[]) {
1460
+ static const real coeff[] = {
1461
+ /* C1p[1]/eps^1, polynomial in eps2 of order 2 */
1462
+ 205, -432, 768, 1536,
1463
+ /* C1p[2]/eps^2, polynomial in eps2 of order 2 */
1464
+ 4005, -4736, 3840, 12288,
1465
+ /* C1p[3]/eps^3, polynomial in eps2 of order 1 */
1466
+ -225, 116, 384,
1467
+ /* C1p[4]/eps^4, polynomial in eps2 of order 1 */
1468
+ -7173, 2695, 7680,
1469
+ /* C1p[5]/eps^5, polynomial in eps2 of order 0 */
1470
+ 3467, 7680,
1471
+ /* C1p[6]/eps^6, polynomial in eps2 of order 0 */
1472
+ 38081, 61440,
1473
+ };
1408
1474
  real
1409
1475
  eps2 = sq(eps),
1410
1476
  d = eps;
1411
- c[1] = d*(eps2*(205*eps2-432)+768)/1536;
1412
- d *= eps;
1413
- c[2] = d*(eps2*(4005*eps2-4736)+3840)/12288;
1414
- d *= eps;
1415
- c[3] = d*(116-225*eps2)/384;
1416
- d *= eps;
1417
- c[4] = d*(2695-7173*eps2)/7680;
1418
- d *= eps;
1419
- c[5] = 3467*d/7680;
1420
- d *= eps;
1421
- c[6] = 38081*d/61440;
1477
+ int o = 0, l;
1478
+ for (l = 1; l <= nC1p; ++l) { /* l is index of C1p[l] */
1479
+ int m = (nC1p - l) / 2; /* order of polynomial in eps^2 */
1480
+ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1481
+ o += m + 2;
1482
+ d *= eps;
1483
+ }
1422
1484
  }
1423
1485
 
1424
1486
  /* The scale factor A2-1 = mean value of (d/dsigma)I2 - 1 */
1425
1487
  real A2m1f(real eps) {
1426
- real
1427
- eps2 = sq(eps),
1428
- t = eps2*(eps2*(25*eps2+36)+64)/256;
1429
- return t * (1 - eps) - eps;
1488
+ static const real coeff[] = {
1489
+ /* (eps+1)*A2-1, polynomial in eps2 of order 3 */
1490
+ -11, -28, -192, 0, 256,
1491
+ };
1492
+ int m = nA2/2;
1493
+ real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1494
+ return (t - eps) / (1 + eps);
1430
1495
  }
1431
1496
 
1432
1497
  /* The coefficients C2[l] in the Fourier expansion of B2 */
1433
1498
  void C2f(real eps, real c[]) {
1499
+ static const real coeff[] = {
1500
+ /* C2[1]/eps^1, polynomial in eps2 of order 2 */
1501
+ 1, 2, 16, 32,
1502
+ /* C2[2]/eps^2, polynomial in eps2 of order 2 */
1503
+ 35, 64, 384, 2048,
1504
+ /* C2[3]/eps^3, polynomial in eps2 of order 1 */
1505
+ 15, 80, 768,
1506
+ /* C2[4]/eps^4, polynomial in eps2 of order 1 */
1507
+ 7, 35, 512,
1508
+ /* C2[5]/eps^5, polynomial in eps2 of order 0 */
1509
+ 63, 1280,
1510
+ /* C2[6]/eps^6, polynomial in eps2 of order 0 */
1511
+ 77, 2048,
1512
+ };
1434
1513
  real
1435
1514
  eps2 = sq(eps),
1436
1515
  d = eps;
1437
- c[1] = d*(eps2*(eps2+2)+16)/32;
1438
- d *= eps;
1439
- c[2] = d*(eps2*(35*eps2+64)+384)/2048;
1440
- d *= eps;
1441
- c[3] = d*(15*eps2+80)/768;
1442
- d *= eps;
1443
- c[4] = d*(7*eps2+35)/512;
1444
- d *= eps;
1445
- c[5] = 63*d/1280;
1446
- d *= eps;
1447
- c[6] = 77*d/2048;
1516
+ int o = 0, l;
1517
+ for (l = 1; l <= nC2; ++l) { /* l is index of C2[l] */
1518
+ int m = (nC2 - l) / 2; /* order of polynomial in eps^2 */
1519
+ c[l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1520
+ o += m + 2;
1521
+ d *= eps;
1522
+ }
1448
1523
  }
1449
1524
 
1450
1525
  /* The scale factor A3 = mean value of (d/dsigma)I3 */
1451
1526
  void A3coeff(struct geod_geodesic* g) {
1452
- g->A3x[0] = 1;
1453
- g->A3x[1] = (g->n-1)/2;
1454
- g->A3x[2] = (g->n*(3*g->n-1)-2)/8;
1455
- g->A3x[3] = ((-g->n-3)*g->n-1)/16;
1456
- g->A3x[4] = (-2*g->n-3)/64;
1457
- g->A3x[5] = -3/(real)(128);
1527
+ static const real coeff[] = {
1528
+ /* A3, coeff of eps^5, polynomial in n of order 0 */
1529
+ -3, 128,
1530
+ /* A3, coeff of eps^4, polynomial in n of order 1 */
1531
+ -2, -3, 64,
1532
+ /* A3, coeff of eps^3, polynomial in n of order 2 */
1533
+ -1, -3, -1, 16,
1534
+ /* A3, coeff of eps^2, polynomial in n of order 2 */
1535
+ 3, -1, -2, 8,
1536
+ /* A3, coeff of eps^1, polynomial in n of order 1 */
1537
+ 1, -1, 2,
1538
+ /* A3, coeff of eps^0, polynomial in n of order 0 */
1539
+ 1, 1,
1540
+ };
1541
+ int o = 0, k = 0, j;
1542
+ for (j = nA3 - 1; j >= 0; --j) { /* coeff of eps^j */
1543
+ int m = nA3 - j - 1 < j ? nA3 - j - 1 : j; /* order of polynomial in n */
1544
+ g->A3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1545
+ o += m + 2;
1546
+ }
1458
1547
  }
1459
1548
 
1460
1549
  /* The coefficients C3[l] in the Fourier expansion of B3 */
1461
1550
  void C3coeff(struct geod_geodesic* g) {
1462
- g->C3x[0] = (1-g->n)/4;
1463
- g->C3x[1] = (1-g->n*g->n)/8;
1464
- g->C3x[2] = ((3-g->n)*g->n+3)/64;
1465
- g->C3x[3] = (2*g->n+5)/128;
1466
- g->C3x[4] = 3/(real)(128);
1467
- g->C3x[5] = ((g->n-3)*g->n+2)/32;
1468
- g->C3x[6] = ((-3*g->n-2)*g->n+3)/64;
1469
- g->C3x[7] = (g->n+3)/128;
1470
- g->C3x[8] = 5/(real)(256);
1471
- g->C3x[9] = (g->n*(5*g->n-9)+5)/192;
1472
- g->C3x[10] = (9-10*g->n)/384;
1473
- g->C3x[11] = 7/(real)(512);
1474
- g->C3x[12] = (7-14*g->n)/512;
1475
- g->C3x[13] = 7/(real)(512);
1476
- g->C3x[14] = 21/(real)(2560);
1551
+ static const real coeff[] = {
1552
+ /* C3[1], coeff of eps^5, polynomial in n of order 0 */
1553
+ 3, 128,
1554
+ /* C3[1], coeff of eps^4, polynomial in n of order 1 */
1555
+ 2, 5, 128,
1556
+ /* C3[1], coeff of eps^3, polynomial in n of order 2 */
1557
+ -1, 3, 3, 64,
1558
+ /* C3[1], coeff of eps^2, polynomial in n of order 2 */
1559
+ -1, 0, 1, 8,
1560
+ /* C3[1], coeff of eps^1, polynomial in n of order 1 */
1561
+ -1, 1, 4,
1562
+ /* C3[2], coeff of eps^5, polynomial in n of order 0 */
1563
+ 5, 256,
1564
+ /* C3[2], coeff of eps^4, polynomial in n of order 1 */
1565
+ 1, 3, 128,
1566
+ /* C3[2], coeff of eps^3, polynomial in n of order 2 */
1567
+ -3, -2, 3, 64,
1568
+ /* C3[2], coeff of eps^2, polynomial in n of order 2 */
1569
+ 1, -3, 2, 32,
1570
+ /* C3[3], coeff of eps^5, polynomial in n of order 0 */
1571
+ 7, 512,
1572
+ /* C3[3], coeff of eps^4, polynomial in n of order 1 */
1573
+ -10, 9, 384,
1574
+ /* C3[3], coeff of eps^3, polynomial in n of order 2 */
1575
+ 5, -9, 5, 192,
1576
+ /* C3[4], coeff of eps^5, polynomial in n of order 0 */
1577
+ 7, 512,
1578
+ /* C3[4], coeff of eps^4, polynomial in n of order 1 */
1579
+ -14, 7, 512,
1580
+ /* C3[5], coeff of eps^5, polynomial in n of order 0 */
1581
+ 21, 2560,
1582
+ };
1583
+ int o = 0, k = 0, l, j;
1584
+ for (l = 1; l < nC3; ++l) { /* l is index of C3[l] */
1585
+ for (j = nC3 - 1; j >= l; --j) { /* coeff of eps^j */
1586
+ int m = nC3 - j - 1 < j ? nC3 - j - 1 : j; /* order of polynomial in n */
1587
+ g->C3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1588
+ o += m + 2;
1589
+ }
1590
+ }
1477
1591
  }
1478
1592
 
1479
- /* Generated by Maxima on 2012-10-19 08:02:34-04:00 */
1480
-
1481
1593
  /* The coefficients C4[l] in the Fourier expansion of I4 */
1482
1594
  void C4coeff(struct geod_geodesic* g) {
1483
- g->C4x[0] = (g->n*(g->n*(g->n*(g->n*(100*g->n+208)+572)+3432)-12012)+30030)/
1484
- 45045;
1485
- g->C4x[1] = (g->n*(g->n*(g->n*(64*g->n+624)-4576)+6864)-3003)/15015;
1486
- g->C4x[2] = (g->n*((14144-10656*g->n)*g->n-4576)-858)/45045;
1487
- g->C4x[3] = ((-224*g->n-4784)*g->n+1573)/45045;
1488
- g->C4x[4] = (1088*g->n+156)/45045;
1489
- g->C4x[5] = 97/(real)(15015);
1490
- g->C4x[6] = (g->n*(g->n*((-64*g->n-624)*g->n+4576)-6864)+3003)/135135;
1491
- g->C4x[7] = (g->n*(g->n*(5952*g->n-11648)+9152)-2574)/135135;
1492
- g->C4x[8] = (g->n*(5792*g->n+1040)-1287)/135135;
1493
- g->C4x[9] = (468-2944*g->n)/135135;
1494
- g->C4x[10] = 1/(real)(9009);
1495
- g->C4x[11] = (g->n*((4160-1440*g->n)*g->n-4576)+1716)/225225;
1496
- g->C4x[12] = ((4992-8448*g->n)*g->n-1144)/225225;
1497
- g->C4x[13] = (1856*g->n-936)/225225;
1498
- g->C4x[14] = 8/(real)(10725);
1499
- g->C4x[15] = (g->n*(3584*g->n-3328)+1144)/315315;
1500
- g->C4x[16] = (1024*g->n-208)/105105;
1501
- g->C4x[17] = -136/(real)(63063);
1502
- g->C4x[18] = (832-2560*g->n)/405405;
1503
- g->C4x[19] = -128/(real)(135135);
1504
- g->C4x[20] = 128/(real)(99099);
1595
+ static const real coeff[] = {
1596
+ /* C4[0], coeff of eps^5, polynomial in n of order 0 */
1597
+ 97, 15015,
1598
+ /* C4[0], coeff of eps^4, polynomial in n of order 1 */
1599
+ 1088, 156, 45045,
1600
+ /* C4[0], coeff of eps^3, polynomial in n of order 2 */
1601
+ -224, -4784, 1573, 45045,
1602
+ /* C4[0], coeff of eps^2, polynomial in n of order 3 */
1603
+ -10656, 14144, -4576, -858, 45045,
1604
+ /* C4[0], coeff of eps^1, polynomial in n of order 4 */
1605
+ 64, 624, -4576, 6864, -3003, 15015,
1606
+ /* C4[0], coeff of eps^0, polynomial in n of order 5 */
1607
+ 100, 208, 572, 3432, -12012, 30030, 45045,
1608
+ /* C4[1], coeff of eps^5, polynomial in n of order 0 */
1609
+ 1, 9009,
1610
+ /* C4[1], coeff of eps^4, polynomial in n of order 1 */
1611
+ -2944, 468, 135135,
1612
+ /* C4[1], coeff of eps^3, polynomial in n of order 2 */
1613
+ 5792, 1040, -1287, 135135,
1614
+ /* C4[1], coeff of eps^2, polynomial in n of order 3 */
1615
+ 5952, -11648, 9152, -2574, 135135,
1616
+ /* C4[1], coeff of eps^1, polynomial in n of order 4 */
1617
+ -64, -624, 4576, -6864, 3003, 135135,
1618
+ /* C4[2], coeff of eps^5, polynomial in n of order 0 */
1619
+ 8, 10725,
1620
+ /* C4[2], coeff of eps^4, polynomial in n of order 1 */
1621
+ 1856, -936, 225225,
1622
+ /* C4[2], coeff of eps^3, polynomial in n of order 2 */
1623
+ -8448, 4992, -1144, 225225,
1624
+ /* C4[2], coeff of eps^2, polynomial in n of order 3 */
1625
+ -1440, 4160, -4576, 1716, 225225,
1626
+ /* C4[3], coeff of eps^5, polynomial in n of order 0 */
1627
+ -136, 63063,
1628
+ /* C4[3], coeff of eps^4, polynomial in n of order 1 */
1629
+ 1024, -208, 105105,
1630
+ /* C4[3], coeff of eps^3, polynomial in n of order 2 */
1631
+ 3584, -3328, 1144, 315315,
1632
+ /* C4[4], coeff of eps^5, polynomial in n of order 0 */
1633
+ -128, 135135,
1634
+ /* C4[4], coeff of eps^4, polynomial in n of order 1 */
1635
+ -2560, 832, 405405,
1636
+ /* C4[5], coeff of eps^5, polynomial in n of order 0 */
1637
+ 128, 99099,
1638
+ };
1639
+ int o = 0, k = 0, l, j;
1640
+ for (l = 0; l < nC4; ++l) { /* l is index of C4[l] */
1641
+ for (j = nC4 - 1; j >= l; --j) { /* coeff of eps^j */
1642
+ int m = nC4 - j - 1; /* order of polynomial in n */
1643
+ g->C4x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1644
+ o += m + 2;
1645
+ }
1646
+ }
1505
1647
  }
1506
1648
 
1507
1649
  int transit(real lon1, real lon2) {
@@ -1516,6 +1658,13 @@ int transit(real lon1, real lon2) {
1516
1658
  (lon2 < 0 && lon1 >= 0 && lon12 < 0 ? -1 : 0);
1517
1659
  }
1518
1660
 
1661
+ int transitdirect(real lon1, real lon2) {
1662
+ lon1 = fmod(lon1, (real)(720));
1663
+ lon2 = fmod(lon2, (real)(720));
1664
+ return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
1665
+ ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
1666
+ }
1667
+
1519
1668
  void accini(real s[]) {
1520
1669
  /* Initialize an accumulator; this is an array with two elements. */
1521
1670
  s[0] = s[1] = 0;
@@ -1583,13 +1732,13 @@ void geod_polygon_addedge(const struct geod_geodesic* g,
1583
1732
  real azi, real s) {
1584
1733
  if (p->num) { /* Do nothing is num is zero */
1585
1734
  real lat, lon, S12;
1586
- geod_gendirect(g, p->lat, p->lon, azi, FALSE, s,
1735
+ geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s,
1587
1736
  &lat, &lon, 0,
1588
1737
  0, 0, 0, 0, p->polyline ? 0 : &S12);
1589
1738
  accadd(p->P, s);
1590
1739
  if (!p->polyline) {
1591
1740
  accadd(p->A, S12);
1592
- p->crossings += transit(p->lon, lon);
1741
+ p->crossings += transitdirect(p->lon, lon);
1593
1742
  }
1594
1743
  p->lat = lat; p->lon = lon;
1595
1744
  ++p->num;
@@ -1720,11 +1869,11 @@ unsigned geod_polygon_testedge(const struct geod_geodesic* g,
1720
1869
  crossings = p->crossings;
1721
1870
  {
1722
1871
  real lat, lon, s12, S12;
1723
- geod_gendirect(g, p->lat, p->lon, azi, FALSE, s,
1872
+ geod_gendirect(g, p->lat, p->lon, azi, GEOD_LONG_UNROLL, s,
1724
1873
  &lat, &lon, 0,
1725
1874
  0, 0, 0, 0, &S12);
1726
1875
  tempsum += S12;
1727
- crossings += transit(p->lon, lon);
1876
+ crossings += transitdirect(p->lon, lon);
1728
1877
  geod_geninverse(g, lat, lon, p->lat0, p->lon0,
1729
1878
  &s12, 0, 0, 0, 0, 0, &S12);
1730
1879
  perimeter += s12;