34# pragma warning (disable: 4701)
42 : maxit2_(maxit1_ +
Math::digits() + 10)
46 , tiny_(sqrt(numeric_limits<real>::min()))
47 , tol0_(numeric_limits<real>::epsilon())
54 , xthresh_(1000 * tol2_)
60 , _ep2(_e2 /
Math::sq(_f1))
65 Math::eatanhe(real(1), (_f < 0 ? -1 : 1) * sqrt(fabs(_e2))) / _e2))
77 , _etol2(real(0.1) * tol2_ /
78 sqrt( fmax(real(0.001), fabs(_f)) * fmin(real(1), 1 - _f/2) / 2 ))
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");
101 const real c[],
int n) {
109 ar = 2 * (cosx - sinx) * (cosx + sinx),
110 y0 = n & 1 ? *--c : 0, y1 = 0;
115 y1 = ar * y0 - y1 + *--c;
116 y0 = ar * y1 - y0 + *--c;
119 ? 2 * sinx * cosx * y0
124 unsigned caps)
const {
129 bool arcmode, real s12_a12,
unsigned outmask,
130 real& lat2, real& lon2, real& azi2,
131 real& s12, real& m12, real& M12, real& M21,
134 return _geodexact.GenDirect(lat1, lon1, azi1, arcmode, s12_a12, outmask,
136 s12, m12, M12, M21, S12);
141 GenPosition(arcmode, s12_a12, outmask,
142 lat2, lon2, azi2, s12, m12, M12, M21, S12);
146 bool arcmode, real s12_a12,
147 unsigned caps)
const {
154 return GeodesicLine(*
this, lat1, lon1, azi1, salp1, calp1,
155 caps, arcmode, s12_a12);
159 unsigned caps)
const {
164 real a12,
unsigned caps)
const {
169 unsigned outmask,
real& s12,
175 return _geodexact.GenInverse(lat1, lon1, lat2, lon2,
177 salp1, calp1, salp2, calp2,
182 int lonsign = signbit(lon12) ? -1 : 1;
183 lon12 *= lonsign; lon12s *= lonsign;
190 lon12s = (
Math::hd - lon12) - lon12s;
197 int swapp = fabs(lat1) < fabs(lat2) || isnan(lat2) ? -1 : 1;
203 int latsign = signbit(lat1) ? 1 : -1;
223 Math::norm(sbet1, cbet1); cbet1 = fmax(tiny_, cbet1);
227 Math::norm(sbet2, cbet2); cbet2 = fmax(tiny_, cbet2);
237 if (cbet1 < -sbet1) {
239 sbet2 = copysign(sbet1, sbet2);
241 if (fabs(sbet2) == -sbet1)
246 dn1 = sqrt(1 + _ep2 *
Math::sq(sbet1)),
247 dn2 = sqrt(1 + _ep2 *
Math::sq(sbet2));
253 bool meridian = lat1 == -
Math::qd || slam12 == 0;
260 calp1 = clam12; salp1 = slam12;
261 calp2 = 1; salp2 = 0;
265 ssig1 = sbet1, csig1 = calp1 * cbet1,
266 ssig2 = sbet2, csig2 = calp2 * cbet2;
269 sig12 = atan2(fmax(
real(0), csig1 * ssig2 - ssig1 * csig2) +
real(0),
270 csig1 * csig2 + ssig1 * ssig2);
273 Lengths(_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
275 s12x, m12x, dummy, M12, M21, Ca);
281 if (sig12 < tol2_ || m12x >= 0) {
283 if (sig12 < 3 * tiny_ ||
285 (sig12 < tol0_ && (s12x < 0 || m12x < 0)))
286 sig12 = m12x = s12x = 0;
296 real omg12 = 0, somg12 = 2, comg12 = 0;
299 (_f <= 0 || lon12s >= _f *
Math::hd)) {
302 calp1 = calp2 = 0; salp1 = salp2 = 1;
304 sig12 = omg12 = lam12 / _f1;
305 m12x = _b * sin(sig12);
307 M12 = M21 = cos(sig12);
310 }
else if (!meridian) {
317 sig12 = InverseStart(sbet1, cbet1, dn1, sbet2, cbet2, dn2,
318 lam12, slam12, clam12,
319 salp1, calp1, salp2, calp2, dnm,
324 s12x = sig12 * _b * dnm;
325 m12x =
Math::sq(dnm) * _b * sin(sig12 / dnm);
327 M12 = M21 = cos(sig12 / dnm);
329 omg12 = lam12 / (_f1 * dnm);
345 real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0;
348 real salp1a = tiny_, calp1a = 1, salp1b = tiny_, calp1b = -1;
349 for (
bool tripn =
false, tripb =
false;; ++numit) {
353 real v = Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
355 salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
356 eps, domg12, numit < maxit1_, dv, Ca);
359 !(fabs(v) >= (tripn ? 8 : 1) * tol0_) ||
364 if (v > 0 && (numit > maxit1_ || calp1/salp1 > calp1b/salp1b))
365 { salp1b = salp1; calp1b = calp1; }
366 else if (v < 0 && (numit > maxit1_ || calp1/salp1 < calp1a/salp1a))
367 { salp1a = salp1; calp1a = calp1; }
368 if (numit < maxit1_ && dv > 0) {
376 sdalp1 = sin(dalp1), cdalp1 = cos(dalp1),
377 nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
379 calp1 = calp1 * cdalp1 - salp1 * sdalp1;
385 tripn = fabs(v) <= 16 * tol0_;
398 salp1 = (salp1a + salp1b)/2;
399 calp1 = (calp1a + calp1b)/2;
402 tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb_ ||
403 fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb_);
409 unsigned lengthmask = outmask |
411 Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
412 cbet1, cbet2, lengthmask, s12x, m12x, dummy, M12, M21, Ca);
417 if (outmask &
AREA) {
419 real sdomg12 = sin(domg12), cdomg12 = cos(domg12);
420 somg12 = slam12 * cdomg12 - clam12 * sdomg12;
421 comg12 = clam12 * cdomg12 + slam12 * sdomg12;
427 s12 =
real(0) + s12x;
430 m12 =
real(0) + m12x;
432 if (outmask &
AREA) {
435 salp0 = salp1 * cbet1,
436 calp0 = hypot(calp1, salp1 * sbet1);
438 if (calp0 != 0 && salp0 != 0) {
441 ssig1 = sbet1, csig1 = calp1 * cbet1,
442 ssig2 = sbet2, csig2 = calp2 * cbet2,
444 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2),
446 A4 =
Math::sq(_a) * calp0 * salp0 * _e2;
451 B41 = SinCosSeries(
false, ssig1, csig1, Ca, nC4_),
452 B42 = SinCosSeries(
false, ssig2, csig2, Ca, nC4_);
453 S12 = A4 * (B42 - B41);
457 if (!meridian && somg12 == 2) {
458 somg12 = sin(omg12); comg12 = cos(omg12);
463 comg12 > -
real(0.7071) &&
464 sbet2 - sbet1 <
real(1.75)) {
468 real domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
469 alp12 = 2 * atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
470 domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) );
474 salp12 = salp2 * calp1 - calp2 * salp1,
475 calp12 = calp2 * calp1 + salp2 * salp1;
480 if (salp12 == 0 && calp12 < 0) {
481 salp12 = tiny_ * calp1;
484 alp12 = atan2(salp12, calp12);
487 S12 *= swapp * lonsign * latsign;
500 salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
501 salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
506 Math::real Geodesic::GenInverse(real lat1, real lon1, real lat2, real lon2,
508 real& s12, real& azi1, real& azi2,
509 real& m12, real& M12, real& M21,
512 real salp1, calp1, salp2, calp2,
513 a12 = GenInverse(lat1, lon1, lat2, lon2,
514 outmask, s12, salp1, calp1, salp2, calp2,
524 real lat2, real lon2,
525 unsigned caps)
const {
526 real t, salp1, calp1, salp2, calp2,
527 a12 = GenInverse(lat1, lon1, lat2, lon2,
529 0u, t, salp1, calp1, salp2, calp2,
535 GeodesicLine(*
this, lat1, lon1, azi1, salp1, calp1, caps,
true, a12);
538 void Geodesic::Lengths(
real eps,
real sig12,
541 real cbet1,
real cbet2,
unsigned outmask,
554 real m0x = 0, J12 = 0, A1 = 0, A2 = 0;
568 real B1 = SinCosSeries(
true, ssig2, csig2, Ca, nC1_) -
569 SinCosSeries(
true, ssig1, csig1, Ca, nC1_);
571 s12b = A1 * (sig12 + B1);
573 real B2 = SinCosSeries(
true, ssig2, csig2, Cb, nC2_) -
574 SinCosSeries(
true, ssig1, csig1, Cb, nC2_);
575 J12 = m0x * sig12 + (A1 * B1 - A2 * B2);
579 for (
int l = 1; l <= nC2_; ++l)
580 Cb[l] = A1 * Ca[l] - A2 * Cb[l];
581 J12 = m0x * sig12 + (SinCosSeries(
true, ssig2, csig2, Cb, nC2_) -
582 SinCosSeries(
true, ssig1, csig1, Cb, nC2_));
589 m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
593 real csig12 = csig1 * csig2 + ssig1 * ssig2;
594 real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
595 M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
596 M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
608 if ( !(q == 0 && r <= 0) ) {
617 disc = S * (S + 2 * r3);
624 T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc);
628 u += T + (T != 0 ? r2 / T : 0);
631 real
ang = atan2(sqrt(-disc), -(S + r3));
634 u += 2 * r * cos(
ang / 3);
639 uv = u < 0 ? q / (v - u) : u + v,
640 w = (uv - q) / (2 * v);
643 k = uv / (sqrt(uv +
Math::sq(w)) + w);
668 sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
669 cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
670 real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
671 bool shortline = cbet12 >= 0 && sbet12 <
real(0.5) &&
672 cbet2 * lam12 <
real(0.5);
675 real sbetm2 =
Math::sq(sbet1 + sbet2);
678 sbetm2 /= sbetm2 +
Math::sq(cbet1 + cbet2);
679 dnm = sqrt(1 + _ep2 * sbetm2);
680 real omg12 = lam12 / (_f1 * dnm);
681 somg12 = sin(omg12); comg12 = cos(omg12);
683 somg12 = slam12; comg12 = clam12;
686 salp1 = cbet2 * somg12;
687 calp1 = comg12 >= 0 ?
688 sbet12 + cbet2 * sbet1 *
Math::sq(somg12) / (1 + comg12) :
689 sbet12a - cbet2 * sbet1 * Math::sq(somg12) / (1 - comg12);
692 ssig12 = hypot(salp1, calp1),
693 csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
695 if (shortline && ssig12 < _etol2) {
697 salp2 = cbet1 * somg12;
698 calp2 = sbet12 - cbet1 * sbet2 *
699 (comg12 >= 0 ?
Math::sq(somg12) / (1 + comg12) : 1 - comg12);
702 sig12 = atan2(ssig12, csig12);
703 }
else if (fabs(_n) >
real(0.1) ||
710 real x, y, lamscale, betscale;
711 real lam12x = atan2(-slam12, -clam12);
717 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
718 lamscale = _f * cbet1 * A3f(eps) *
Math::pi();
720 betscale = lamscale * cbet1;
722 x = lam12x / lamscale;
723 y = sbet12a / betscale;
727 cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
728 bet12a = atan2(sbet12a, cbet12a);
729 real m12b, m0, dummy;
733 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
736 x = -1 + m12b / (cbet1 * cbet2 * m0 *
Math::pi());
737 betscale = x < -
real(0.01) ? sbet12a / x :
739 lamscale = betscale / cbet1;
740 y = lam12x / lamscale;
743 if (y > -tol1_ && x > -1 - xthresh_) {
747 salp1 = fmin(
real(1), -x); calp1 = - sqrt(1 -
Math::sq(salp1));
749 calp1 = fmax(
real(x > -tol1_ ? 0 : -1), x);
787 real k = Astroid(x, y);
789 omg12a = lamscale * ( _f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
790 somg12 = sin(omg12a); comg12 = -cos(omg12a);
792 salp1 = cbet2 * somg12;
793 calp1 = sbet12a - cbet2 * sbet1 *
Math::sq(somg12) / (1 - comg12);
800 salp1 = 1; calp1 = 0;
814 bool diffp,
real& dlam12,
818 if (sbet1 == 0 && calp1 == 0)
825 salp0 = salp1 * cbet1,
826 calp0 = hypot(calp1, salp1 * sbet1);
828 real somg1, comg1, somg2, comg2, somg12, comg12, lam12;
831 ssig1 = sbet1; somg1 = salp0 * sbet1;
832 csig1 = comg1 = calp1 * cbet1;
840 salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
845 calp2 = cbet2 != cbet1 || fabs(sbet2) != -sbet1 ?
848 (cbet2 - cbet1) * (cbet1 + cbet2) :
849 (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 :
853 ssig2 = sbet2; somg2 = salp0 * sbet2;
854 csig2 = comg2 = calp2 * cbet2;
859 sig12 = atan2(fmax(
real(0), csig1 * ssig2 - ssig1 * csig2) +
real(0),
860 csig1 * csig2 + ssig1 * ssig2);
863 somg12 = fmax(
real(0), comg1 * somg2 - somg1 * comg2) +
real(0);
864 comg12 = comg1 * comg2 + somg1 * somg2;
866 real eta = atan2(somg12 * clam120 - comg12 * slam120,
867 comg12 * clam120 + somg12 * slam120);
870 eps = k2 / (2 * (1 + sqrt(1 + k2)) + k2);
872 B312 = (SinCosSeries(
true, ssig2, csig2, Ca, nC3_-1) -
873 SinCosSeries(
true, ssig1, csig1, Ca, nC3_-1));
874 domg12 = -_f * A3f(eps) * salp0 * (sig12 + B312);
875 lam12 = eta + domg12;
879 dlam12 = - 2 * _f1 * dn1 / sbet1;
882 Lengths(eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
884 dummy, dlam12, dummy, dummy, dummy, Ca);
885 dlam12 *= _f1 / (calp2 * cbet2);
897 void Geodesic::C3f(
real eps,
real c[])
const {
902 for (
int l = 1; l < nC3_; ++l) {
903 int m = nC3_ - l - 1;
911 void Geodesic::C4f(
real eps,
real c[])
const {
916 for (
int l = 0; l < nC4_; ++l) {
917 int m = nC4_ - l - 1;
951#if GEOGRAPHICLIB_GEODESIC_ORDER/2 == 1
952 static const real coeff[] = {
956#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 2
957 static const real coeff[] = {
961#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 3
962 static const real coeff[] = {
966#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 4
967 static const real coeff[] = {
969 25, 64, 256, 4096, 0, 16384,
972#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
974 static_assert(
sizeof(coeff) /
sizeof(real) == nA1_/2 + 2,
975 "Coefficient array size mismatch in A1m1f");
978 return (t + eps) / (1 - eps);
982 void Geodesic::C1f(
real eps,
real c[]) {
984#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
985 static const real coeff[] = {
993#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
994 static const real coeff[] = {
1004#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1005 static const real coeff[] = {
1017#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1018 static const real coeff[] = {
1032#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1033 static const real coeff[] = {
1035 19, -64, 384, -1024, 2048,
1049#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1050 static const real coeff[] = {
1052 19, -64, 384, -1024, 2048,
1054 7, -18, 128, -256, 4096,
1058 -11, 96, -160, 16384,
1069#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1071 static_assert(
sizeof(coeff) /
sizeof(real) ==
1072 (nC1_*nC1_ + 7*nC1_ - 2*(nC1_/2)) / 4,
1073 "Coefficient array size mismatch in C1f");
1078 for (
int l = 1; l <= nC1_; ++l) {
1079 int m = (nC1_ - l) / 2;
1080 c[l] = d *
Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1088 void Geodesic::C1pf(
real eps,
real c[]) {
1090#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1091 static const real coeff[] = {
1099#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1100 static const real coeff[] = {
1110#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1111 static const real coeff[] = {
1113 205, -432, 768, 1536,
1123#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1124 static const real coeff[] = {
1126 205, -432, 768, 1536,
1128 4005, -4736, 3840, 12288,
1138#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1139 static const real coeff[] = {
1141 -4879, 9840, -20736, 36864, 73728,
1143 4005, -4736, 3840, 12288,
1145 8703, -7200, 3712, 12288,
1149 -141115, 41604, 92160,
1155#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1156 static const real coeff[] = {
1158 -4879, 9840, -20736, 36864, 73728,
1160 -86171, 120150, -142080, 115200, 368640,
1162 8703, -7200, 3712, 12288,
1164 1082857, -688608, 258720, 737280,
1166 -141115, 41604, 92160,
1168 -2200311, 533134, 860160,
1172 109167851, 82575360,
1175#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1177 static_assert(
sizeof(coeff) /
sizeof(real) ==
1178 (nC1p_*nC1p_ + 7*nC1p_ - 2*(nC1p_/2)) / 4,
1179 "Coefficient array size mismatch in C1pf");
1184 for (
int l = 1; l <= nC1p_; ++l) {
1185 int m = (nC1p_ - l) / 2;
1186 c[l] = d *
Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1196#if GEOGRAPHICLIB_GEODESIC_ORDER/2 == 1
1197 static const real coeff[] = {
1201#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 2
1202 static const real coeff[] = {
1206#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 3
1207 static const real coeff[] = {
1209 -11, -28, -192, 0, 256,
1211#elif GEOGRAPHICLIB_GEODESIC_ORDER/2 == 4
1212 static const real coeff[] = {
1214 -375, -704, -1792, -12288, 0, 16384,
1217#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1219 static_assert(
sizeof(coeff) /
sizeof(real) == nA2_/2 + 2,
1220 "Coefficient array size mismatch in A2m1f");
1223 return (t - eps) / (1 + eps);
1227 void Geodesic::C2f(
real eps,
real c[]) {
1229#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1230 static const real coeff[] = {
1238#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1239 static const real coeff[] = {
1249#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1250 static const real coeff[] = {
1262#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1263 static const real coeff[] = {
1277#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1278 static const real coeff[] = {
1280 41, 64, 128, 1024, 2048,
1294#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1295 static const real coeff[] = {
1297 41, 64, 128, 1024, 2048,
1299 47, 70, 128, 768, 4096,
1303 133, 224, 1120, 16384,
1314#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1316 static_assert(
sizeof(coeff) /
sizeof(real) ==
1317 (nC2_*nC2_ + 7*nC2_ - 2*(nC2_/2)) / 4,
1318 "Coefficient array size mismatch in C2f");
1323 for (
int l = 1; l <= nC2_; ++l) {
1324 int m = (nC2_ - l) / 2;
1325 c[l] = d *
Math::polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1333 void Geodesic::A3coeff() {
1335#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1336 static const real coeff[] = {
1344#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1345 static const real coeff[] = {
1355#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1356 static const real coeff[] = {
1368#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1369 static const real coeff[] = {
1383#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1384 static const real coeff[] = {
1400#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1401 static const real coeff[] = {
1409 -5, -20, -4, -6, 128,
1420#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1422 static_assert(
sizeof(coeff) /
sizeof(real) ==
1423 (nA3_*nA3_ + 7*nA3_ - 2*(nA3_/2)) / 4,
1424 "Coefficient array size mismatch in A3f");
1426 for (
int j = nA3_ - 1; j >= 0; --j) {
1427 int m = min(nA3_ - j - 1, j);
1428 _aA3x[k++] =
Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
1435 void Geodesic::C3coeff() {
1437#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1438 static const real coeff[] = {
1446#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1447 static const real coeff[] = {
1463#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1464 static const real coeff[] = {
1486#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1487 static const real coeff[] = {
1519#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1520 static const real coeff[] = {
1564#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1565 static const real coeff[] = {
1599 10, -6, -10, 9, 384,
1609 -7, 20, -28, 14, 1024,
1624#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1626 static_assert(
sizeof(coeff) /
sizeof(real) ==
1627 ((nC3_-1)*(nC3_*nC3_ + 7*nC3_ - 2*(nC3_/2)))/8,
1628 "Coefficient array size mismatch in C3coeff");
1630 for (
int l = 1; l < nC3_; ++l) {
1631 for (
int j = nC3_ - 1; j >= l; --j) {
1632 int m = min(nC3_ - j - 1, j);
1633 _cC3x[k++] =
Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
1640 void Geodesic::C4coeff() {
1642#if GEOGRAPHICLIB_GEODESIC_ORDER == 3
1643 static const real coeff[] = {
1657#elif GEOGRAPHICLIB_GEODESIC_ORDER == 4
1658 static const real coeff[] = {
1666 4, 24, -84, 210, 315,
1680#elif GEOGRAPHICLIB_GEODESIC_ORDER == 5
1681 static const real coeff[] = {
1687 1088, -352, -66, 3465,
1689 48, -352, 528, -231, 1155,
1691 16, 44, 264, -924, 2310, 3465,
1697 -896, 704, -198, 10395,
1699 -48, 352, -528, 231, 10395,
1705 320, -352, 132, 17325,
1713#elif GEOGRAPHICLIB_GEODESIC_ORDER == 6
1714 static const real coeff[] = {
1720 -224, -4784, 1573, 45045,
1722 -10656, 14144, -4576, -858, 45045,
1724 64, 624, -4576, 6864, -3003, 15015,
1726 100, 208, 572, 3432, -12012, 30030, 45045,
1732 5792, 1040, -1287, 135135,
1734 5952, -11648, 9152, -2574, 135135,
1736 -64, -624, 4576, -6864, 3003, 135135,
1742 -8448, 4992, -1144, 225225,
1744 -1440, 4160, -4576, 1716, 225225,
1750 3584, -3328, 1144, 315315,
1758#elif GEOGRAPHICLIB_GEODESIC_ORDER == 7
1759 static const real coeff[] = {
1765 -4480, 1088, 156, 45045,
1767 10736, -224, -4784, 1573, 45045,
1769 1664, -10656, 14144, -4576, -858, 45045,
1771 16, 64, 624, -4576, 6864, -3003, 15015,
1773 56, 100, 208, 572, 3432, -12012, 30030, 45045,
1779 3840, -2944, 468, 135135,
1781 -10704, 5792, 1040, -1287, 135135,
1783 -768, 5952, -11648, 9152, -2574, 135135,
1785 -16, -64, -624, 4576, -6864, 3003, 135135,
1791 1664, 1856, -936, 225225,
1793 6784, -8448, 4992, -1144, 225225,
1795 128, -1440, 4160, -4576, 1716, 225225,
1801 -2048, 1024, -208, 105105,
1803 -1792, 3584, -3328, 1144, 315315,
1809 3072, -2560, 832, 405405,
1817#elif GEOGRAPHICLIB_GEODESIC_ORDER == 8
1818 static const real coeff[] = {
1824 20960, -7888, 4947, 765765,
1826 12480, -76160, 18496, 2652, 765765,
1828 -154048, 182512, -3808, -81328, 26741, 765765,
1830 3232, 28288, -181152, 240448, -77792, -14586, 765765,
1832 96, 272, 1088, 10608, -77792, 116688, -51051, 255255,
1834 588, 952, 1700, 3536, 9724, 58344, -204204, 510510, 765765,
1840 -39840, 1904, 255, 2297295,
1842 52608, 65280, -50048, 7956, 2297295,
1844 103744, -181968, 98464, 17680, -21879, 2297295,
1846 -1344, -13056, 101184, -198016, 155584, -43758, 2297295,
1848 -96, -272, -1088, -10608, 77792, -116688, 51051, 2297295,
1852 -928, -612, 3828825,
1854 64256, -28288, 2856, 3828825,
1856 -126528, 28288, 31552, -15912, 3828825,
1858 -41472, 115328, -143616, 84864, -19448, 3828825,
1860 160, 2176, -24480, 70720, -77792, 29172, 3828825,
1864 -16384, 1088, 5360355,
1866 -2560, 30464, -11560, 5360355,
1868 35840, -34816, 17408, -3536, 1786785,
1870 7168, -30464, 60928, -56576, 19448, 5360355,
1874 26624, -8704, 6891885,
1876 -77824, 34816, -6528, 6891885,
1878 -32256, 52224, -43520, 14144, 6891885,
1882 24576, -4352, 8423415,
1884 45056, -34816, 10880, 8423415,
1888 -28672, 8704, 9954945,
1893#error "Bad value for GEOGRAPHICLIB_GEODESIC_ORDER"
1895 static_assert(
sizeof(coeff) /
sizeof(real) ==
1896 (nC4_ * (nC4_ + 1) * (nC4_ + 5)) / 6,
1897 "Coefficient array size mismatch in C4coeff");
1899 for (
int l = 0; l < nC4_; ++l) {
1900 for (
int j = nC4_ - 1; j >= l; --j) {
1901 int m = nC4_ - j - 1;
1902 _cC4x[k++] =
Math::polyval(m, coeff + o, _n) / coeff[o + m + 1];
GeographicLib::Math::real real
Header for GeographicLib::GeodesicLine class.
Header for GeographicLib::Geodesic class.
Exact geodesic calculations.
GeodesicLine InverseLine(real lat1, real lon1, real lat2, real lon2, unsigned caps=ALL) const
static const Geodesic & WGS84()
GeodesicLine ArcDirectLine(real lat1, real lon1, real azi1, real a12, unsigned caps=ALL) const
GeodesicLine Line(real lat1, real lon1, real azi1, unsigned caps=ALL) const
GeodesicLine GenDirectLine(real lat1, real lon1, real azi1, bool arcmode, real s12_a12, unsigned caps=ALL) const
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
GeodesicLine DirectLine(real lat1, real lon1, real azi1, real s12, unsigned caps=ALL) const
Geodesic(real a, real f, bool exact=false)
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)