GeographicLib: Geodesic.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
31
32#if defined(_MSC_VER)
33
34# pragma warning (disable: 4701)
35#endif
36
38
39 using namespace std;
40
42 : maxit2_(maxit1_ + Math::digits() + 10)
43
44
45
46 , tiny_(sqrt(numeric_limits::min()))
47 , tol0_(numeric_limits::epsilon())
48
49
50
51 , tol1_(200 * tol0_)
52 , tol2_(sqrt(tol0_))
53 , tolb_(tol0_)
54 , xthresh_(1000 * tol2_)
55 , _a(a)
56 , _f(f)
57 , _exact(exact)
58 , _f1(1 - _f)
59 , _e2(_f * (2 - _f))
60 , _ep2(_e2 / Math::sq(_f1))
61 , _n(_f / ( 2 - _f))
62 , _b(_a * _f1)
63 , _c2((Math::sq(_a) + Math::sq(_b) *
64 (_e2 == 0 ? 1 :
65 Math::eatanhe(real(1), (_f < 0 ? -1 : 1) * sqrt(fabs(_e2))) / _e2))
66 / 2)
67
68
69
70
71
72
73
74
75
76
77 , _etol2(real(0.1) * tol2_ /
78 sqrt( fmax(real(0.001), fabs(_f)) * fmin(real(1), 1 - _f/2) / 2 ))
80 {
81 if (_exact)
82 _c2 = _geodexact._c2;
83 else {
84 if (!(isfinite(_a) && _a > 0))
85 throw GeographicErr("Equatorial radius is not positive");
86 if (!(isfinite(_b) && _b > 0))
87 throw GeographicErr("Polar semi-axis is not positive");
88 A3coeff();
89 C3coeff();
90 C4coeff();
91 }
92 }
93
98
99 Math::real Geodesic::SinCosSeries(bool sinp,
101 const real c[], int n) {
102
103
104
105
106
107 c += (n + sinp);
109 ar = 2 * (cosx - sinx) * (cosx + sinx),
110 y0 = n & 1 ? *--c : 0, y1 = 0;
111
112 n /= 2;
113 while (n--) {
114
115 y1 = ar * y0 - y1 + *--c;
116 y0 = ar * y1 - y0 + *--c;
117 }
118 return sinp
119 ? 2 * sinx * cosx * y0
120 : cosx * (y0 - y1);
121 }
122
124 unsigned caps) const {
125 return GeodesicLine(*this, lat1, lon1, azi1, caps);
126 }
127
129 bool arcmode, real s12_a12, unsigned outmask,
130 real& lat2, real& lon2, real& azi2,
131 real& s12, real& m12, real& M12, real& M21,
132 real& S12) const {
133 if (_exact)
134 return _geodexact.GenDirect(lat1, lon1, azi1, arcmode, s12_a12, outmask,
135 lat2, lon2, azi2,
136 s12, m12, M12, M21, S12);
137
139 return GeodesicLine(*this, lat1, lon1, azi1, outmask)
140 .
141 GenPosition(arcmode, s12_a12, outmask,
142 lat2, lon2, azi2, s12, m12, M12, M21, S12);
143 }
144
146 bool arcmode, real s12_a12,
147 unsigned caps) const {
149 real salp1, calp1;
150
152
154 return GeodesicLine(*this, lat1, lon1, azi1, salp1, calp1,
155 caps, arcmode, s12_a12);
156 }
157
159 unsigned caps) const {
160 return GenDirectLine(lat1, lon1, azi1, false, s12, caps);
161 }
162
164 real a12, unsigned caps) const {
165 return GenDirectLine(lat1, lon1, azi1, true, a12, caps);
166 }
167
169 unsigned outmask, real& s12,
173 real& S12) const {
174 if (_exact)
175 return _geodexact.GenInverse(lat1, lon1, lat2, lon2,
176 outmask, s12,
177 salp1, calp1, salp2, calp2,
178 m12, M12, M21, S12);
179
180 using std::isnan;
182
183 int lonsign = signbit(lon12) ? -1 : 1;
184 lon12 *= lonsign; lon12s *= lonsign;
187 slam12, clam12;
188
190
191 lon12s = (Math::hd - lon12) - lon12s;
192
193
196
197
198 int swapp = fabs(lat1) < fabs(lat2) || isnan(lat2) ? -1 : 1;
199 if (swapp < 0) {
200 lonsign *= -1;
201 swap(lat1, lat2);
202 }
203
204 int latsign = signbit(lat1) ? 1 : -1;
205 lat1 *= latsign;
206 lat2 *= latsign;
207
208
209
210
211
212
213
214
215
216
217
218
219 real sbet1, cbet1, sbet2, cbet2, s12x, m12x = Math::NaN();
220
222
223
224 Math::norm(sbet1, cbet1); cbet1 = fmax(tiny_, cbet1);
225
227
228 Math::norm(sbet2, cbet2); cbet2 = fmax(tiny_, cbet2);
229
230
231
232
233
234
235
236
237
238 if (cbet1 < -sbet1) {
239 if (cbet2 == cbet1)
240 sbet2 = copysign(sbet1, sbet2);
241 } else {
242 if (fabs(sbet2) == -sbet1)
243 cbet2 = cbet1;
244 }
245
247 dn1 = sqrt(1 + _ep2 * Math::sq(sbet1)),
248 dn2 = sqrt(1 + _ep2 * Math::sq(sbet2));
249
250 real a12, sig12;
251
252 real Ca[nC_];
253
254 bool meridian = lat1 == -Math::qd || slam12 == 0;
255
256 if (meridian) {
257
258
259
260
261 calp1 = clam12; salp1 = slam12;
262 calp2 = 1; salp2 = 0;
263
265
266 ssig1 = sbet1, csig1 = calp1 * cbet1,
267 ssig2 = sbet2, csig2 = calp2 * cbet2;
268
269
270 sig12 = atan2(fmax(real(0), csig1 * ssig2 - ssig1 * csig2) + real(0),
271 csig1 * csig2 + ssig1 * ssig2);
272 {
274 Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
276 s12x, m12x, dummy, M12, M21, Ca);
277 }
278
279
280
281
282
283
284
285
286
287
288
289
290 if (sig12 < 1 || m12x >= 0) {
291
292 if (sig12 < 3 * tiny_ ||
293
294 (sig12 < tol0_ && (s12x < 0 || m12x < 0)))
295 sig12 = m12x = s12x = 0;
296 m12x *= _b;
297 s12x *= _b;
299 } else
300
301 meridian = false;
302 }
303
304
305 real omg12 = 0, somg12 = 2, comg12 = 0;
306 if (!meridian &&
307 sbet1 == 0 &&
308 (_f <= 0 || lon12s >= _f * Math::hd)) {
309
310
311 calp1 = calp2 = 0; salp1 = salp2 = 1;
312 s12x = _a * lam12;
313 sig12 = omg12 = lam12 / _f1;
314 m12x = _b * sin(sig12);
316 M12 = M21 = cos(sig12);
317 a12 = lon12 / _f1;
318
319 } else if (!meridian) {
320
321
322
323
324
326 sig12 = InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
327 lam12, slam12, clam12,
328 salp1, calp1, salp2, calp2, dnm,
329 Ca);
330
331 if (sig12 >= 0) {
332
333 s12x = sig12 * _b * dnm;
334 m12x = Math::sq(dnm) * _b * sin(sig12 / dnm);
336 M12 = M21 = cos(sig12 / dnm);
338 omg12 = lam12 / (_f1 * dnm);
339 } else {
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0;
355 unsigned numit = 0;
356
357 real salp1a = tiny_, calp1a = 1, salp1b = tiny_, calp1b = -1;
358 for (bool tripn = false, tripb = false;; ++numit) {
359
360
362 real v = Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
363 slam12, clam12,
364 salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
365 eps, domg12, numit < maxit1_, dv, Ca);
366 if (tripb ||
367
368 !(fabs(v) >= (tripn ? 8 : 1) * tol0_) ||
369
370 numit == maxit2_)
371 break;
372
373 if (v > 0 && (numit > maxit1_ || calp1/salp1 > calp1b/salp1b))
374 { salp1b = salp1; calp1b = calp1; }
375 else if (v < 0 && (numit > maxit1_ || calp1/salp1 < calp1a/salp1a))
376 { salp1a = salp1; calp1a = calp1; }
377 if (numit < maxit1_ && dv > 0) {
379 dalp1 = -v/dv;
380
381
382
383 if (fabs(dalp1) < Math::pi()) {
385 sdalp1 = sin(dalp1), cdalp1 = cos(dalp1),
386 nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
387 if (nsalp1 > 0) {
388 calp1 = calp1 * cdalp1 - salp1 * sdalp1;
389 salp1 = nsalp1;
391
392
393
394 tripn = fabs(v) <= 16 * tol0_;
395 continue;
396 }
397 }
398 }
399
400
401
402
403
404
405
406
407 salp1 = (salp1a + salp1b)/2;
408 calp1 = (calp1a + calp1b)/2;
410 tripn = false;
411 tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb_ ||
412 fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb_);
413 }
414 {
416
417
418 unsigned lengthmask = outmask |
420 Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
421 cbet1, cbet2, lengthmask, s12x, m12x, dummy, M12, M21, Ca);
422 }
423 m12x *= _b;
424 s12x *= _b;
426 if (outmask & AREA) {
427
428 real sdomg12 = sin(domg12), cdomg12 = cos(domg12);
429 somg12 = slam12 * cdomg12 - clam12 * sdomg12;
430 comg12 = clam12 * cdomg12 + slam12 * sdomg12;
431 }
432 }
433 }
434
436 s12 = real(0) + s12x;
437
439 m12 = real(0) + m12x;
440
441 if (outmask & AREA) {
443
444 salp0 = salp1 * cbet1,
445 calp0 = hypot(calp1, salp1 * sbet1);
447 if (calp0 != 0 && salp0 != 0) {
449
450 ssig1 = sbet1, csig1 = calp1 * cbet1,
451 ssig2 = sbet2, csig2 = calp2 * cbet2,
453 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
454
455 A4 = Math::sq(_a) * calp0 * salp0 * _e2;
458 C4f(eps, Ca);
460 B41 = SinCosSeries(false, ssig1, csig1, Ca, nC4_),
461 B42 = SinCosSeries(false, ssig2, csig2, Ca, nC4_);
462 S12 = A4 * (B42 - B41);
463 } else
464
465 S12 = 0;
466 if (!meridian && somg12 == 2) {
467 somg12 = sin(omg12); comg12 = cos(omg12);
468 }
469
470 if (!meridian &&
471
472 comg12 > -real(0.7071) &&
473 sbet2 - sbet1 < real(1.75)) {
474
475
476
477 real domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
478 alp12 = 2 * atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
479 domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) );
480 } else {
481
483 salp12 = salp2 * calp1 - calp2 * salp1,
484 calp12 = calp2 * calp1 + salp2 * salp1;
485
486
487
488
489 if (salp12 == 0 && calp12 < 0) {
490 salp12 = tiny_ * calp1;
491 calp12 = -1;
492 }
493 alp12 = atan2(salp12, calp12);
494 }
495 S12 += _c2 * alp12;
496 S12 *= swapp * lonsign * latsign;
497
498 S12 += 0;
499 }
500
501
502 if (swapp < 0) {
503 swap(salp1, salp2);
504 swap(calp1, calp2);
506 swap(M12, M21);
507 }
508
509 salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
510 salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
511
512 return a12;
513 }
514
515 Math::real Geodesic::GenInverse(real lat1, real lon1, real lat2, real lon2,
516 unsigned outmask,
517 real& s12, real& azi1, real& azi2,
518 real& m12, real& M12, real& M21,
519 real& S12) const {
520 outmask &= OUT_MASK;
521 real salp1, calp1, salp2, calp2,
522 a12 = GenInverse(lat1, lon1, lat2, lon2,
523 outmask, s12, salp1, calp1, salp2, calp2,
524 m12, M12, M21, S12);
528 }
529 return a12;
530 }
531
533 real lat2, real lon2,
534 unsigned caps) const {
535 real t, salp1, calp1, salp2, calp2,
536 a12 = GenInverse(lat1, lon1, lat2, lon2,
537
538 0u, t, salp1, calp1, salp2, calp2,
539 t, t, t, t),
541
543 return
544 GeodesicLine(*this, lat1, lon1, azi1, salp1, calp1, caps, true, a12);
545 }
546
547 void Geodesic::Lengths(real eps, real sig12,
550 real cbet1, real cbet2, unsigned outmask,
553
554 real Ca[]) const {
555
556
557
558 outmask &= OUT_MASK;
559
560
561
562
563 real m0x = 0, J12 = 0, A1 = 0, A2 = 0;
564 real Cb[nC2_ + 1];
566 A1 = A1m1f(eps);
567 C1f(eps, Ca);
569 A2 = A2m1f(eps);
570 C2f(eps, Cb);
571 m0x = A1 - A2;
572 A2 = 1 + A2;
573 }
574 A1 = 1 + A1;
575 }
577 real B1 = SinCosSeries(true, ssig2, csig2, Ca, nC1_) -
578 SinCosSeries(true, ssig1, csig1, Ca, nC1_);
579
580 s12b = A1 * (sig12 + B1);
582 real B2 = SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
583 SinCosSeries(true, ssig1, csig1, Cb, nC2_);
584 J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
585 }
587
588 for (int l = 1; l <= nC2_; ++l)
589 Cb[l] = A1 * Ca[l] - A2 * Cb[l];
590 J12 = m0x * sig12 + (SinCosSeries(true, ssig2, csig2, Cb, nC2_) -
591 SinCosSeries(true, ssig1, csig1, Cb, nC2_));
592 }
594 m0 = m0x;
595
596
597
598 m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
599 csig1 * csig2 * J12;
600 }
602 real csig12 = csig1 * csig2 + ssig1 * ssig2;
603 real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
604 M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
605 M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
606 }
607 }
608
610
611
616 r = (p + q - 1) / 6;
617 if ( !(q == 0 && r <= 0) ) {
619
620
621 S = p * q / 4,
623 r3 = r * r2,
624
625
626 disc = S * (S + 2 * r3);
628 if (disc >= 0) {
629 real T3 = S + r3;
630
631
632
633 T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc);
634
635 real T = cbrt(T3);
636
637 u += T + (T != 0 ? r2 / T : 0);
638 } else {
639
640 real ang = atan2(sqrt(-disc), -(S + r3));
641
642
643 u += 2 * r * cos(ang / 3);
644 }
646 v = sqrt(Math::sq(u) + q),
647
648 uv = u < 0 ? q / (v - u) : u + v,
649 w = (uv - q) / (2 * v);
650
651
652 k = uv / (sqrt(uv + Math::sq(w)) + w);
653 } else {
654
655
656 k = 0;
657 }
658 return k;
659 }
660
665
667
669
670 real Ca[]) const {
671
672
673
675 sig12 = -1,
676
677 sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
678 cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
679 real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
680 bool shortline = cbet12 >= 0 && sbet12 < real(0.5) &&
681 cbet2 * lam12 < real(0.5);
682 real somg12, comg12;
683 if (shortline) {
685
686
687 sbetm2 /= sbetm2 + Math::sq(cbet1 + cbet2);
688 dnm = sqrt(1 + _ep2 * sbetm2);
689 real omg12 = lam12 / (_f1 * dnm);
690 somg12 = sin(omg12); comg12 = cos(omg12);
691 } else {
692 somg12 = slam12; comg12 = clam12;
693 }
694
695 salp1 = cbet2 * somg12;
696 calp1 = comg12 >= 0 ?
697 sbet12 + cbet2 * sbet1 * Math::sq(somg12) / (1 + comg12) :
698 sbet12a - cbet2 * sbet1 * Math::sq(somg12) / (1 - comg12);
699
701 ssig12 = hypot(salp1, calp1),
702 csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
703
704 if (shortline && ssig12 < _etol2) {
705
706 salp2 = cbet1 * somg12;
707 calp2 = sbet12 - cbet1 * sbet2 *
708 (comg12 >= 0 ? Math::sq(somg12) / (1 + comg12) : 1 - comg12);
710
711 sig12 = atan2(ssig12, csig12);
712 } else if (fabs(_n) > real(0.1) ||
713 csig12 >= 0 ||
715
716 } else {
717
718
719 real x, y, lamscale, betscale;
720 real lam12x = atan2(-slam12, -clam12);
721 if (_f >= 0) {
722
723 {
726 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
727 lamscale = _f * cbet1 * A3f(eps) * Math::pi();
728 }
729 betscale = lamscale * cbet1;
730
731 x = lam12x / lamscale;
732 y = sbet12a / betscale;
733 } else {
734
736 cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
737 bet12a = atan2(sbet12a, cbet12a);
738 real m12b, m0, dummy;
739
740
741 Lengths(_n, Math::pi() + bet12a,
742 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
743 cbet1, cbet2,
744 REDUCEDLENGTH, dummy, m12b, m0, dummy, dummy, Ca);
745 x = -1 + m12b / (cbet1 * cbet2 * m0 * Math::pi());
746 betscale = x < -real(0.01) ? sbet12a / x :
748 lamscale = betscale / cbet1;
749 y = lam12x / lamscale;
750 }
751
752 if (y > -tol1_ && x > -1 - xthresh_) {
753
754
755 if (_f >= 0) {
756 salp1 = fmin(real(1), -x); calp1 = - sqrt(1 - Math::sq(salp1));
757 } else {
758 calp1 = fmax(real(x > -tol1_ ? 0 : -1), x);
759 salp1 = sqrt(1 - Math::sq(calp1));
760 }
761 } else {
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796 real k = Astroid(x, y);
798 omg12a = lamscale * ( _f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
799 somg12 = sin(omg12a); comg12 = -cos(omg12a);
800
801 salp1 = cbet2 * somg12;
802 calp1 = sbet12a - cbet2 * sbet1 * Math::sq(somg12) / (1 - comg12);
803 }
804 }
805
806 if (!(salp1 <= 0))
808 else {
809 salp1 = 1; calp1 = 0;
810 }
811 return sig12;
812 }
813
823 bool diffp, real& dlam12,
824
825 real Ca[]) const {
826
827 if (sbet1 == 0 && calp1 == 0)
828
829
830 calp1 = -tiny_;
831
833
834 salp0 = salp1 * cbet1,
835 calp0 = hypot(calp1, salp1 * sbet1);
836
837 real somg1, comg1, somg2, comg2, somg12, comg12, lam12;
838
839
840 ssig1 = sbet1; somg1 = salp0 * sbet1;
841 csig1 = comg1 = calp1 * cbet1;
843
844
845
846
847
848
849 salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
850
851
852
853
854 calp2 = cbet2 != cbet1 || fabs(sbet2) != -sbet1 ?
855 sqrt(Math::sq(calp1 * cbet1) +
856 (cbet1 < -sbet1 ?
857 (cbet2 - cbet1) * (cbet1 + cbet2) :
858 (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 :
859 fabs(calp1);
860
861
862 ssig2 = sbet2; somg2 = salp0 * sbet2;
863 csig2 = comg2 = calp2 * cbet2;
865
866
867
868 sig12 = atan2(fmax(real(0), csig1 * ssig2 - ssig1 * csig2) + real(0),
869 csig1 * csig2 + ssig1 * ssig2);
870
871
872 somg12 = fmax(real(0), comg1 * somg2 - somg1 * comg2) + real(0);
873 comg12 = comg1 * comg2 + somg1 * somg2;
874
875 real eta = atan2(somg12 * clam120 - comg12 * slam120,
876 comg12 * clam120 + somg12 * slam120);
879 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
880 C3f(eps, Ca);
881 B312 = (SinCosSeries(true, ssig2, csig2, Ca, nC3_-1) -
882 SinCosSeries(true, ssig1, csig1, Ca, nC3_-1));
883 domg12 = -_f * A3f(eps) * salp0 * (sig12 + B312);
884 lam12 = eta + domg12;
885
886 if (diffp) {
887 if (calp2 == 0)
888 dlam12 = - 2 * _f1 * dn1 / sbet1;
889 else {
891 Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
893 dummy, dlam12, dummy, dummy, dummy, Ca);
894 dlam12 *= _f1 / (calp2 * cbet2);
895 }
896 }
897
898 return lam12;
899 }
900
902
904 }
905
906 void Geodesic::C3f(real eps, real c[]) const {
907
908
909 real mult = 1;
910 int o = 0;
911 for (int l = 1; l < nC3_; ++l) {
912 int m = nC3_ - l - 1;
913 mult *= eps;
915 o += m + 1;
916 }
917
918 }
919
920 void Geodesic::C4f(real eps, real c[]) const {
921
922
923 real mult = 1;
924 int o = 0;
925 for (int l = 0; l < nC4_; ++l) {
926 int m = nC4_ - l - 1;
928 o += m + 1;
929 mult *= eps;
930 }
931
932 }
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
959
960#if GEOGRAPHICLIB_GEODESIC_ORDER/2 == 1
961 static const real coeff[] = {
962
963 1, 0, 4,
964 };
965#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 2
966 static const real coeff[] = {
967
968 1, 16, 0, 64,
969 };
970#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 3
971 static const real coeff[] = {
972
973 1, 4, 64, 0, 256,
974 };
975#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 4
976 static const real coeff[] = {
977
978 25, 64, 256, 4096, 0, 16384,
979 };
980#else
981#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
982#endif
983 static_assert(sizeof(coeff) / sizeof(real) == nA1_/2 + 2,
984 "Coefficient array size mismatch in A1m1f");
985 int m = nA1_/2;
987 return (t + eps) / (1 - eps);
988 }
989
990
991 void Geodesic::C1f(real eps, real c[]) {
992
993#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
994 static const real coeff[] = {
995
996 3, -8, 16,
997
998 -1, 16,
999
1000 -1, 48,
1001 };
1002#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1003 static const real coeff[] = {
1004
1005 3, -8, 16,
1006
1007 1, -2, 32,
1008
1009 -1, 48,
1010
1011 -5, 512,
1012 };
1013#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1014 static const real coeff[] = {
1015
1016 -1, 6, -16, 32,
1017
1018 1, -2, 32,
1019
1020 9, -16, 768,
1021
1022 -5, 512,
1023
1024 -7, 1280,
1025 };
1026#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1027 static const real coeff[] = {
1028
1029 -1, 6, -16, 32,
1030
1031 -9, 64, -128, 2048,
1032
1033 9, -16, 768,
1034
1035 3, -5, 512,
1036
1037 -7, 1280,
1038
1039 -7, 2048,
1040 };
1041#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1042 static const real coeff[] = {
1043
1044 19, -64, 384, -1024, 2048,
1045
1046 -9, 64, -128, 2048,
1047
1048 -9, 72, -128, 6144,
1049
1050 3, -5, 512,
1051
1052 35, -56, 10240,
1053
1054 -7, 2048,
1055
1056 -33, 14336,
1057 };
1058#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1059 static const real coeff[] = {
1060
1061 19, -64, 384, -1024, 2048,
1062
1063 7, -18, 128, -256, 4096,
1064
1065 -9, 72, -128, 6144,
1066
1067 -11, 96, -160, 16384,
1068
1069 35, -56, 10240,
1070
1071 9, -14, 4096,
1072
1073 -33, 14336,
1074
1075 -429, 262144,
1076 };
1077#else
1078#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1079#endif
1080 static_assert(sizeof(coeff) / sizeof(real) ==
1081 (nC1_*nC1_ + 7*nC1_ - 2*(nC1_/2)) / 4,
1082 "Coefficient array size mismatch in C1f");
1085 d = eps;
1086 int o = 0;
1087 for (int l = 1; l <= nC1_; ++l) {
1088 int m = (nC1_ - l) / 2;
1089 c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1090 o += m + 2;
1091 d *= eps;
1092 }
1093
1094 }
1095
1096
1097 void Geodesic::C1pf(real eps, real c[]) {
1098
1099#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1100 static const real coeff[] = {
1101
1102 -9, 16, 32,
1103
1104 5, 16,
1105
1106 29, 96,
1107 };
1108#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1109 static const real coeff[] = {
1110
1111 -9, 16, 32,
1112
1113 -37, 30, 96,
1114
1115 29, 96,
1116
1117 539, 1536,
1118 };
1119#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1120 static const real coeff[] = {
1121
1122 205, -432, 768, 1536,
1123
1124 -37, 30, 96,
1125
1126 -225, 116, 384,
1127
1128 539, 1536,
1129
1130 3467, 7680,
1131 };
1132#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1133 static const real coeff[] = {
1134
1135 205, -432, 768, 1536,
1136
1137 4005, -4736, 3840, 12288,
1138
1139 -225, 116, 384,
1140
1141 -7173, 2695, 7680,
1142
1143 3467, 7680,
1144
1145 38081, 61440,
1146 };
1147#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1148 static const real coeff[] = {
1149
1150 -4879, 9840, -20736, 36864, 73728,
1151
1152 4005, -4736, 3840, 12288,
1153
1154 8703, -7200, 3712, 12288,
1155
1156 -7173, 2695, 7680,
1157
1158 -141115, 41604, 92160,
1159
1160 38081, 61440,
1161
1162 459485, 516096,
1163 };
1164#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1165 static const real coeff[] = {
1166
1167 -4879, 9840, -20736, 36864, 73728,
1168
1169 -86171, 120150, -142080, 115200, 368640,
1170
1171 8703, -7200, 3712, 12288,
1172
1173 1082857, -688608, 258720, 737280,
1174
1175 -141115, 41604, 92160,
1176
1177 -2200311, 533134, 860160,
1178
1179 459485, 516096,
1180
1181 109167851, 82575360,
1182 };
1183#else
1184#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1185#endif
1186 static_assert(sizeof(coeff) / sizeof(real) ==
1187 (nC1p_*nC1p_ + 7*nC1p_ - 2*(nC1p_/2)) / 4,
1188 "Coefficient array size mismatch in C1pf");
1191 d = eps;
1192 int o = 0;
1193 for (int l = 1; l <= nC1p_; ++l) {
1194 int m = (nC1p_ - l) / 2;
1195 c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1196 o += m + 2;
1197 d *= eps;
1198 }
1199
1200 }
1201
1202
1204
1205#if GEOGRAPHICLIB_GEODESIC_ORDER/2 == 1
1206 static const real coeff[] = {
1207
1208 -3, 0, 4,
1209 };
1210#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 2
1211 static const real coeff[] = {
1212
1213 -7, -48, 0, 64,
1214 };
1215#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 3
1216 static const real coeff[] = {
1217
1218 -11, -28, -192, 0, 256,
1219 };
1220#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 4
1221 static const real coeff[] = {
1222
1223 -375, -704, -1792, -12288, 0, 16384,
1224 };
1225#else
1226#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1227#endif
1228 static_assert(sizeof(coeff) / sizeof(real) == nA2_/2 + 2,
1229 "Coefficient array size mismatch in A2m1f");
1230 int m = nA2_/2;
1232 return (t - eps) / (1 + eps);
1233 }
1234
1235
1236 void Geodesic::C2f(real eps, real c[]) {
1237
1238#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1239 static const real coeff[] = {
1240
1241 1, 8, 16,
1242
1243 3, 16,
1244
1245 5, 48,
1246 };
1247#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1248 static const real coeff[] = {
1249
1250 1, 8, 16,
1251
1252 1, 6, 32,
1253
1254 5, 48,
1255
1256 35, 512,
1257 };
1258#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1259 static const real coeff[] = {
1260
1261 1, 2, 16, 32,
1262
1263 1, 6, 32,
1264
1265 15, 80, 768,
1266
1267 35, 512,
1268
1269 63, 1280,
1270 };
1271#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1272 static const real coeff[] = {
1273
1274 1, 2, 16, 32,
1275
1276 35, 64, 384, 2048,
1277
1278 15, 80, 768,
1279
1280 7, 35, 512,
1281
1282 63, 1280,
1283
1284 77, 2048,
1285 };
1286#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1287 static const real coeff[] = {
1288
1289 41, 64, 128, 1024, 2048,
1290
1291 35, 64, 384, 2048,
1292
1293 69, 120, 640, 6144,
1294
1295 7, 35, 512,
1296
1297 105, 504, 10240,
1298
1299 77, 2048,
1300
1301 429, 14336,
1302 };
1303#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1304 static const real coeff[] = {
1305
1306 41, 64, 128, 1024, 2048,
1307
1308 47, 70, 128, 768, 4096,
1309
1310 69, 120, 640, 6144,
1311
1312 133, 224, 1120, 16384,
1313
1314 105, 504, 10240,
1315
1316 33, 154, 4096,
1317
1318 429, 14336,
1319
1320 6435, 262144,
1321 };
1322#else
1323#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1324#endif
1325 static_assert(sizeof(coeff) / sizeof(real) ==
1326 (nC2_*nC2_ + 7*nC2_ - 2*(nC2_/2)) / 4,
1327 "Coefficient array size mismatch in C2f");
1330 d = eps;
1331 int o = 0;
1332 for (int l = 1; l <= nC2_; ++l) {
1333 int m = (nC2_ - l) / 2;
1334 c[l] = d * Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1335 o += m + 2;
1336 d *= eps;
1337 }
1338
1339 }
1340
1341
1342 void Geodesic::A3coeff() {
1343
1344#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1345 static const real coeff[] = {
1346
1347 -1, 4,
1348
1349 1, -1, 2,
1350
1351 1, 1,
1352 };
1353#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1354 static const real coeff[] = {
1355
1356 -1, 16,
1357
1358 -1, -2, 8,
1359
1360 1, -1, 2,
1361
1362 1, 1,
1363 };
1364#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1365 static const real coeff[] = {
1366
1367 -3, 64,
1368
1369 -3, -1, 16,
1370
1371 3, -1, -2, 8,
1372
1373 1, -1, 2,
1374
1375 1, 1,
1376 };
1377#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1378 static const real coeff[] = {
1379
1380 -3, 128,
1381
1382 -2, -3, 64,
1383
1384 -1, -3, -1, 16,
1385
1386 3, -1, -2, 8,
1387
1388 1, -1, 2,
1389
1390 1, 1,
1391 };
1392#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1393 static const real coeff[] = {
1394
1395 -5, 256,
1396
1397 -5, -3, 128,
1398
1399 -10, -2, -3, 64,
1400
1401 5, -1, -3, -1, 16,
1402
1403 3, -1, -2, 8,
1404
1405 1, -1, 2,
1406
1407 1, 1,
1408 };
1409#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1410 static const real coeff[] = {
1411
1412 -25, 2048,
1413
1414 -15, -20, 1024,
1415
1416 -5, -10, -6, 256,
1417
1418 -5, -20, -4, -6, 128,
1419
1420 5, -1, -3, -1, 16,
1421
1422 3, -1, -2, 8,
1423
1424 1, -1, 2,
1425
1426 1, 1,
1427 };
1428#else
1429#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1430#endif
1431 static_assert(sizeof(coeff) / sizeof(real) ==
1432 (nA3_*nA3_ + 7*nA3_ - 2*(nA3_/2)) / 4,
1433 "Coefficient array size mismatch in A3f");
1434 int o = 0, k = 0;
1435 for (int j = nA3_ - 1; j >= 0; --j) {
1436 int m = min(nA3_ - j - 1, j);
1437 _aA3x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
1438 o += m + 2;
1439 }
1440
1441 }
1442
1443
1444 void Geodesic::C3coeff() {
1445
1446#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1447 static const real coeff[] = {
1448
1449 1, 8,
1450
1451 -1, 1, 4,
1452
1453 1, 16,
1454 };
1455#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1456 static const real coeff[] = {
1457
1458 3, 64,
1459
1460
1461
1462 0, 1, 8,
1463
1464 -1, 1, 4,
1465
1466 3, 64,
1467
1468 -3, 2, 32,
1469
1470 5, 192,
1471 };
1472#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1473 static const real coeff[] = {
1474
1475 5, 128,
1476
1477 3, 3, 64,
1478
1479 -1, 0, 1, 8,
1480
1481 -1, 1, 4,
1482
1483 3, 128,
1484
1485 -2, 3, 64,
1486
1487 1, -3, 2, 32,
1488
1489 3, 128,
1490
1491 -9, 5, 192,
1492
1493 7, 512,
1494 };
1495#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1496 static const real coeff[] = {
1497
1498 3, 128,
1499
1500 2, 5, 128,
1501
1502 -1, 3, 3, 64,
1503
1504 -1, 0, 1, 8,
1505
1506 -1, 1, 4,
1507
1508 5, 256,
1509
1510 1, 3, 128,
1511
1512 -3, -2, 3, 64,
1513
1514 1, -3, 2, 32,
1515
1516 7, 512,
1517
1518 -10, 9, 384,
1519
1520 5, -9, 5, 192,
1521
1522 7, 512,
1523
1524 -14, 7, 512,
1525
1526 21, 2560,
1527 };
1528#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1529 static const real coeff[] = {
1530
1531 21, 1024,
1532
1533 11, 12, 512,
1534
1535 2, 2, 5, 128,
1536
1537 -5, -1, 3, 3, 64,
1538
1539 -1, 0, 1, 8,
1540
1541 -1, 1, 4,
1542
1543 27, 2048,
1544
1545 1, 5, 256,
1546
1547 -9, 2, 6, 256,
1548
1549 2, -3, -2, 3, 64,
1550
1551 1, -3, 2, 32,
1552
1553 3, 256,
1554
1555 -4, 21, 1536,
1556
1557 -6, -10, 9, 384,
1558
1559 -1, 5, -9, 5, 192,
1560
1561 9, 1024,
1562
1563 -10, 7, 512,
1564
1565 10, -14, 7, 512,
1566
1567 9, 1024,
1568
1569 -45, 21, 2560,
1570
1571 11, 2048,
1572 };
1573#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1574 static const real coeff[] = {
1575
1576 243, 16384,
1577
1578 10, 21, 1024,
1579
1580 3, 11, 12, 512,
1581
1582 -2, 2, 2, 5, 128,
1583
1584 -5, -1, 3, 3, 64,
1585
1586 -1, 0, 1, 8,
1587
1588 -1, 1, 4,
1589
1590 187, 16384,
1591
1592 69, 108, 8192,
1593
1594 -2, 1, 5, 256,
1595
1596 -6, -9, 2, 6, 256,
1597
1598 2, -3, -2, 3, 64,
1599
1600 1, -3, 2, 32,
1601
1602 139, 16384,
1603
1604 -1, 12, 1024,
1605
1606 -77, -8, 42, 3072,
1607
1608 10, -6, -10, 9, 384,
1609
1610 -1, 5, -9, 5, 192,
1611
1612 127, 16384,
1613
1614 -43, 72, 8192,
1615
1616 -7, -40, 28, 2048,
1617
1618 -7, 20, -28, 14, 1024,
1619
1620 99, 16384,
1621
1622 -15, 9, 1024,
1623
1624 75, -90, 42, 5120,
1625
1626 99, 16384,
1627
1628 -99, 44, 8192,
1629
1630 429, 114688,
1631 };
1632#else
1633#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1634#endif
1635 static_assert(sizeof(coeff) / sizeof(real) ==
1636 ((nC3_-1)*(nC3_*nC3_ + 7*nC3_ - 2*(nC3_/2)))/8,
1637 "Coefficient array size mismatch in C3coeff");
1638 int o = 0, k = 0;
1639 for (int l = 1; l < nC3_; ++l) {
1640 for (int j = nC3_ - 1; j >= l; --j) {
1641 int m = min(nC3_ - j - 1, j);
1642 _cC3x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
1643 o += m + 2;
1644 }
1645 }
1646
1647 }
1648
1649 void Geodesic::C4coeff() {
1650
1651#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1652 static const real coeff[] = {
1653
1654 -2, 105,
1655
1656 16, -7, 35,
1657
1658 8, -28, 70, 105,
1659
1660 -2, 105,
1661
1662 -16, 7, 315,
1663
1664 4, 525,
1665 };
1666#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1667 static const real coeff[] = {
1668
1669 11, 315,
1670
1671 -32, -6, 315,
1672
1673 -32, 48, -21, 105,
1674
1675 4, 24, -84, 210, 315,
1676
1677 -1, 105,
1678
1679 64, -18, 945,
1680
1681 32, -48, 21, 945,
1682
1683 -8, 1575,
1684
1685 -32, 12, 1575,
1686
1687 8, 2205,
1688 };
1689#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1690 static const real coeff[] = {
1691
1692 4, 1155,
1693
1694 -368, 121, 3465,
1695
1696 1088, -352, -66, 3465,
1697
1698 48, -352, 528, -231, 1155,
1699
1700 16, 44, 264, -924, 2310, 3465,
1701
1702 4, 1155,
1703
1704 80, -99, 10395,
1705
1706 -896, 704, -198, 10395,
1707
1708 -48, 352, -528, 231, 10395,
1709
1710 -8, 1925,
1711
1712 384, -88, 17325,
1713
1714 320, -352, 132, 17325,
1715
1716 -16, 8085,
1717
1718 -256, 88, 24255,
1719
1720 64, 31185,
1721 };
1722#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1723 static const real coeff[] = {
1724
1725 97, 15015,
1726
1727 1088, 156, 45045,
1728
1729 -224, -4784, 1573, 45045,
1730
1731 -10656, 14144, -4576, -858, 45045,
1732
1733 64, 624, -4576, 6864, -3003, 15015,
1734
1735 100, 208, 572, 3432, -12012, 30030, 45045,
1736
1737 1, 9009,
1738
1739 -2944, 468, 135135,
1740
1741 5792, 1040, -1287, 135135,
1742
1743 5952, -11648, 9152, -2574, 135135,
1744
1745 -64, -624, 4576, -6864, 3003, 135135,
1746
1747 8, 10725,
1748
1749 1856, -936, 225225,
1750
1751 -8448, 4992, -1144, 225225,
1752
1753 -1440, 4160, -4576, 1716, 225225,
1754
1755 -136, 63063,
1756
1757 1024, -208, 105105,
1758
1759 3584, -3328, 1144, 315315,
1760
1761 -128, 135135,
1762
1763 -2560, 832, 405405,
1764
1765 128, 99099,
1766 };
1767#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1768 static const real coeff[] = {
1769
1770 10, 9009,
1771
1772 -464, 291, 45045,
1773
1774 -4480, 1088, 156, 45045,
1775
1776 10736, -224, -4784, 1573, 45045,
1777
1778 1664, -10656, 14144, -4576, -858, 45045,
1779
1780 16, 64, 624, -4576, 6864, -3003, 15015,
1781
1782 56, 100, 208, 572, 3432, -12012, 30030, 45045,
1783
1784 10, 9009,
1785
1786 112, 15, 135135,
1787
1788 3840, -2944, 468, 135135,
1789
1790 -10704, 5792, 1040, -1287, 135135,
1791
1792 -768, 5952, -11648, 9152, -2574, 135135,
1793
1794 -16, -64, -624, 4576, -6864, 3003, 135135,
1795
1796 -4, 25025,
1797
1798 -1664, 168, 225225,
1799
1800 1664, 1856, -936, 225225,
1801
1802 6784, -8448, 4992, -1144, 225225,
1803
1804 128, -1440, 4160, -4576, 1716, 225225,
1805
1806 64, 315315,
1807
1808 1792, -680, 315315,
1809
1810 -2048, 1024, -208, 105105,
1811
1812 -1792, 3584, -3328, 1144, 315315,
1813
1814 -512, 405405,
1815
1816 2048, -384, 405405,
1817
1818 3072, -2560, 832, 405405,
1819
1820 -256, 495495,
1821
1822 -2048, 640, 495495,
1823
1824 512, 585585,
1825 };
1826#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1827 static const real coeff[] = {
1828
1829 193, 85085,
1830
1831 4192, 850, 765765,
1832
1833 20960, -7888, 4947, 765765,
1834
1835 12480, -76160, 18496, 2652, 765765,
1836
1837 -154048, 182512, -3808, -81328, 26741, 765765,
1838
1839 3232, 28288, -181152, 240448, -77792, -14586, 765765,
1840
1841 96, 272, 1088, 10608, -77792, 116688, -51051, 255255,
1842
1843 588, 952, 1700, 3536, 9724, 58344, -204204, 510510, 765765,
1844
1845 349, 2297295,
1846
1847 -1472, 510, 459459,
1848
1849 -39840, 1904, 255, 2297295,
1850
1851 52608, 65280, -50048, 7956, 2297295,
1852
1853 103744, -181968, 98464, 17680, -21879, 2297295,
1854
1855 -1344, -13056, 101184, -198016, 155584, -43758, 2297295,
1856
1857 -96, -272, -1088, -10608, 77792, -116688, 51051, 2297295,
1858
1859 464, 1276275,
1860
1861 -928, -612, 3828825,
1862
1863 64256, -28288, 2856, 3828825,
1864
1865 -126528, 28288, 31552, -15912, 3828825,
1866
1867 -41472, 115328, -143616, 84864, -19448, 3828825,
1868
1869 160, 2176, -24480, 70720, -77792, 29172, 3828825,
1870
1871 -16, 97461,
1872
1873 -16384, 1088, 5360355,
1874
1875 -2560, 30464, -11560, 5360355,
1876
1877 35840, -34816, 17408, -3536, 1786785,
1878
1879 7168, -30464, 60928, -56576, 19448, 5360355,
1880
1881 128, 2297295,
1882
1883 26624, -8704, 6891885,
1884
1885 -77824, 34816, -6528, 6891885,
1886
1887 -32256, 52224, -43520, 14144, 6891885,
1888
1889 -6784, 8423415,
1890
1891 24576, -4352, 8423415,
1892
1893 45056, -34816, 10880, 8423415,
1894
1895 -1024, 3318315,
1896
1897 -28672, 8704, 9954945,
1898
1899 1024, 1640925,
1900 };
1901#else
1902#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1903#endif
1904 static_assert(sizeof(coeff) / sizeof(real) ==
1905 (nC4_ * (nC4_ + 1) * (nC4_ + 5)) / 6,
1906 "Coefficient array size mismatch in C4coeff");
1907 int o = 0, k = 0;
1908 for (int l = 0; l < nC4_; ++l) {
1909 for (int j = nC4_ - 1; j >= l; --j) {
1910 int m = nC4_ - j - 1;
1911 _cC4x[k++] = Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
1912 o += m + 2;
1913 }
1914 }
1915
1916 }
1917
1918}
GeographicLib::Math::real real
Header for GeographicLib::GeodesicLine class.
Header for GeographicLib::Geodesic class.
Exact geodesic calculations.
Math::real GenDirect(real lat1, real lon1, real azi1, bool arcmode, real s12_a12, unsigned outmask, real &lat2, real &lon2, real &azi2, real &s12, real &m12, real &M12, real &M21, real &S12) const
GeodesicLine InverseLine(real lat1, real lon1, real lat2, real lon2, unsigned caps=ALL) const
Definition Geodesic.cpp:532
static const Geodesic & WGS84()
Definition Geodesic.cpp:94
GeodesicLine ArcDirectLine(real lat1, real lon1, real azi1, real a12, unsigned caps=ALL) const
Definition Geodesic.cpp:163
GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps=ALL) const
Definition Geodesic.cpp:123
GeodesicLine GenDirectLine(real lat1, real lon1, real azi1, bool arcmode, real s12_a12, unsigned caps=ALL) const
Definition Geodesic.cpp:145
friend class GeodesicLine
Math::real GenDirect(real lat1, real lon1, real azi1, bool arcmode, real s12_a12, unsigned outmask, real &lat2, real &lon2, real &azi2, real &s12, real &m12, real &M12, real &M21, real &S12) const
Definition Geodesic.cpp:128
GeodesicLine DirectLine(real lat1, real lon1, real azi1, real s12, unsigned caps=ALL) const
Definition Geodesic.cpp:158
Geodesic(real a, real f, bool exact=false)
Definition Geodesic.cpp:41
Exception handling for GeographicLib.
Mathematical functions needed by GeographicLib.
static void sincosd(T x, T &sinx, T &cosx)
static T atan2d(T y, T x)
static void norm(T &x, T &y)
static constexpr int qd
degrees per quarter turn
static T AngNormalize(T x)
static void sincosde(T x, T t, T &sinx, T &cosx)
static T polyval(int N, const T p[], T x)
static T AngDiff(T x, T y, T &e)
static constexpr int hd
degrees per half turn
Namespace for GeographicLib.
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)