29 #if !defined(HAVE_C99_MATH) 30 #define HAVE_C99_MATH 0 33 #define GEOGRAPHICLIB_GEODESIC_ORDER 6 34 #define nA1 GEOGRAPHICLIB_GEODESIC_ORDER 35 #define nC1 GEOGRAPHICLIB_GEODESIC_ORDER 36 #define nC1p GEOGRAPHICLIB_GEODESIC_ORDER 37 #define nA2 GEOGRAPHICLIB_GEODESIC_ORDER 38 #define nC2 GEOGRAPHICLIB_GEODESIC_ORDER 39 #define nA3 GEOGRAPHICLIB_GEODESIC_ORDER 41 #define nC3 GEOGRAPHICLIB_GEODESIC_ORDER 42 #define nC3x ((nC3 * (nC3 - 1)) / 2) 43 #define nC4 GEOGRAPHICLIB_GEODESIC_ORDER 44 #define nC4x ((nC4 * (nC4 + 1)) / 2) 45 #define nC (GEOGRAPHICLIB_GEODESIC_ORDER + 1) 50 static unsigned init = 0;
51 static const int FALSE = 0;
52 static const int TRUE = 1;
53 static unsigned digits, maxit1, maxit2;
55 tiny, tol0, tol1, tol2, tolb, xthresh;
59 #if defined(__DBL_MANT_DIG__) 60 digits = __DBL_MANT_DIG__;
64 #if defined(__DBL_EPSILON__) 69 #if defined(__DBL_MIN__) 70 realmin = __DBL_MIN__;
72 realmin =
pow(0.5, 1022);
77 pi =
atan2(0.0, -1.0);
80 maxit2 = maxit1 + digits + 10;
90 xthresh = 1000 * tol2;
114 #define copysignx copysign 126 return z == 0 ? x : x *
log(y) /
z;
131 y = log1px(2 * y/(1 - y))/2;
132 return x < 0 ? -y :
y;
136 return fabs(x) * (y < 0 || (y == 0 && 1/y < 0) ? -1 : 1);
140 {
return sqrt(x * x + y * y); }
144 return x < 0 ? -y :
y;
150 volatile real up = s -
v;
151 volatile real vpp = s - up;
154 if (t) *t = -(up + vpp);
162 real y = N < 0 ? 0 : *p++;
163 while (--N >= 0) y = y * x + *p++;
169 {
return (b < a) ? b :
a; }
172 {
return (a < b) ? b :
a; }
175 {
real t = *
x; *x = *
y; *y =
t; }
178 real r = hypotx(*sinx, *cosx);
186 return x != -180 ? x : 180;
189 return x <= -180 ? x + 360 : (x <= 180 ? x : x - 360);
194 {
return fabs(x) > 90 ? NaN :
x; }
197 real t,
d = AngNormalize(sumx(AngNormalize(-x), AngNormalize(y), &t));
204 return sumx(d == 180 && t > 0 ? -180 : d, t, e);
210 if (x == 0)
return 0;
213 y = y < z ? z - (z -
y) : y;
214 return x < 0 ? -y :
y;
221 #if HAVE_C99_MATH && !defined(__GNUC__) 234 switch ((
unsigned)q & 3
U) {
235 case 0U: *sinx =
s; *cosx =
c;
break;
236 case 1U: *sinx =
c; *cosx = -
s;
break;
237 case 2U: *sinx = -
s; *cosx = -
c;
break;
238 default: *sinx = -
c; *cosx =
s;
break;
240 if (x != 0) { *sinx += (
real)(0); *cosx += (
real)(0); }
249 if (
fabs(y) >
fabs(x)) { swapx(&x, &y); q = 2; }
250 if (x < 0) { x = -
x; ++
q; }
259 case 1: ang = (y >= 0 ? 180 : -180) - ang;
break;
260 case 2: ang = 90 - ang;
break;
261 case 3: ang = -90 + ang;
break;
269 static real SinCosSeries(boolx sinp,
271 const real c[],
int n);
304 boolx diffp,
real* pdlam12,
311 static void C1f(
real eps,
real c[]);
312 static void C1pf(
real eps,
real c[]);
314 static void C2f(
real eps,
real c[]);
315 static int transit(
real lon1,
real lon2);
316 static int transitdirect(
real lon1,
real lon2);
317 static void accini(
real s[]);
318 static void acccopy(
const real s[],
real t[]);
319 static void accadd(
real s[],
real y);
321 static void accneg(
real s[]);
328 g->e2 = g->
f * (2 - g->
f);
329 g->ep2 = g->e2 / sq(g->f1);
330 g->n = g->
f / ( 2 - g->
f);
332 g->c2 = (sq(g->
a) + sq(g->b) *
334 (g->e2 > 0 ? atanhx(
sqrt(g->e2)) :
atan(
sqrt(-g->e2))) /
345 g->etol2 = 0.1 * tol2 /
358 real cbet1, sbet1, eps;
369 l->
lat1 = LatFix(lat1);
375 sincosdx(AngRound(l->
lat1), &sbet1, &cbet1); sbet1 *= l->f1;
377 norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
378 l->dn1 =
sqrt(1 + g->ep2 * sq(sbet1));
381 l->salp0 = l->
salp1 * cbet1;
384 l->calp0 = hypotx(l->
calp1, l->
salp1 * sbet1);
394 l->ssig1 = sbet1; l->somg1 = l->salp0 * sbet1;
395 l->csig1 = l->comg1 = sbet1 != 0 || l->
calp1 != 0 ? cbet1 * l->
calp1 : 1;
396 norm2(&l->ssig1, &l->csig1);
399 l->k2 = sq(l->calp0) * g->ep2;
400 eps = l->k2 / (2 * (1 +
sqrt(1 + l->k2)) + l->k2);
402 if (l->
caps & CAP_C1) {
404 l->A1m1 = A1m1f(eps);
406 l->B11 = SinCosSeries(
TRUE, l->ssig1, l->csig1, l->C1a, nC1);
407 s =
sin(l->B11); c =
cos(l->B11);
409 l->stau1 = l->ssig1 * c + l->csig1 *
s;
410 l->ctau1 = l->csig1 * c - l->ssig1 *
s;
415 if (l->
caps & CAP_C1p)
418 if (l->
caps & CAP_C2) {
419 l->A2m1 = A2m1f(eps);
421 l->B21 = SinCosSeries(
TRUE, l->ssig1, l->csig1, l->C2a, nC2);
424 if (l->
caps & CAP_C3) {
426 l->A3c = -l->
f * l->salp0 * A3f(g, eps);
427 l->B31 = SinCosSeries(
TRUE, l->ssig1, l->csig1, l->C3a, nC3-1);
430 if (l->
caps & CAP_C4) {
433 l->A4 = sq(l->
a) * l->calp0 * l->salp0 * g->e2;
434 l->B41 = SinCosSeries(
FALSE, l->ssig1, l->csig1, l->C4a, nC4);
444 azi1 = AngNormalize(azi1);
446 sincosdx(AngRound(azi1), &salp1, &calp1);
447 geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps);
453 unsigned flags,
real a12_s12,
462 real s12,
unsigned caps) {
467 unsigned flags,
real s12_a12,
472 real lat2 = 0, lon2 = 0, azi2 = 0, s12 = 0,
473 m12 = 0, M12 = 0, M21 = 0, S12 = 0;
475 real sig12, ssig12, csig12, B12 = 0, AB1 = 0;
476 real omg12, lam12, lon12;
477 real ssig2, csig2, sbet2, cbet2, somg2, comg2, salp2, calp2, dn2;
496 sincosdx(s12_a12, &ssig12, &csig12);
500 tau12 = s12_a12 / (l->b * (1 + l->A1m1)),
504 B12 = - SinCosSeries(
TRUE,
505 l->stau1 * c + l->ctau1 * s,
506 l->ctau1 * c - l->stau1 * s,
508 sig12 = tau12 - (B12 - l->B11);
509 ssig12 =
sin(sig12); csig12 =
cos(sig12);
510 if (
fabs(l->
f) > 0.01) {
533 ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12;
534 csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
535 B12 = SinCosSeries(
TRUE, ssig2, csig2, l->C1a, nC1);
536 serr = (1 + l->A1m1) * (sig12 + (B12 - l->B11)) - s12_a12 / l->b;
537 sig12 = sig12 - serr /
sqrt(1 + l->k2 * sq(ssig2));
538 ssig12 =
sin(sig12); csig12 =
cos(sig12);
544 ssig2 = l->ssig1 * csig12 + l->csig1 * ssig12;
545 csig2 = l->csig1 * csig12 - l->ssig1 * ssig12;
546 dn2 =
sqrt(1 + l->k2 * sq(ssig2));
548 if (flags & GEOD_ARCMODE ||
fabs(l->
f) > 0.01)
549 B12 = SinCosSeries(
TRUE, ssig2, csig2, l->C1a, nC1);
550 AB1 = (1 + l->A1m1) * (B12 - l->B11);
553 sbet2 = l->calp0 * ssig2;
555 cbet2 = hypotx(l->salp0, l->calp0 * csig2);
558 cbet2 = csig2 = tiny;
560 salp2 = l->salp0; calp2 = l->calp0 * csig2;
563 s12 = flags & GEOD_ARCMODE ?
564 l->b * ((1 + l->A1m1) * sig12 + AB1) :
568 real E = copysignx(1, l->salp0);
570 somg2 = l->salp0 * ssig2; comg2 = csig2;
574 - (
atan2( ssig2, csig2) -
atan2( l->ssig1, l->csig1))
575 + (
atan2(E * somg2, comg2) -
atan2(E * l->somg1, l->comg1)))
576 :
atan2(somg2 * l->comg1 - comg2 * l->somg1,
577 comg2 * l->comg1 + somg2 * l->somg1);
578 lam12 = omg12 + l->A3c *
579 ( sig12 + (SinCosSeries(
TRUE, ssig2, csig2, l->C3a, nC3-1)
583 AngNormalize(AngNormalize(l->
lon1) + AngNormalize(lon12));
587 lat2 = atan2dx(sbet2, l->f1 * cbet2);
590 azi2 = atan2dx(salp2, calp2);
594 B22 = SinCosSeries(
TRUE, ssig2, csig2, l->C2a, nC2),
595 AB2 = (1 + l->A2m1) * (B22 - l->B21),
596 J12 = (l->A1m1 - l->A2m1) * sig12 + (AB1 - AB2);
600 m12 = l->b * ((dn2 * (l->csig1 * ssig2) - l->dn1 * (l->ssig1 * csig2))
601 - l->csig1 * csig2 * J12);
603 real t = l->k2 * (ssig2 - l->ssig1) * (ssig2 + l->ssig1) /
605 M12 = csig12 + (t * ssig2 - csig2 * J12) * l->ssig1 / l->dn1;
606 M21 = csig12 - (t * l->ssig1 - l->csig1 * J12) * ssig2 / dn2;
612 B42 = SinCosSeries(
FALSE, ssig2, csig2, l->C4a, nC4);
614 if (l->calp0 == 0 || l->salp0 == 0) {
627 salp12 = l->calp0 * l->salp0 *
628 (csig12 <= 0 ? l->csig1 * (1 - csig12) + ssig12 * l->ssig1 :
629 ssig12 * (l->csig1 * ssig12 / (1 + csig12) + l->ssig1));
630 calp12 = sq(l->salp0) + sq(l->calp0) * l->csig1 * csig2;
632 S12 = l->c2 *
atan2(salp12, calp12) + l->A4 * (B42 - l->B41);
635 if (outmask & GEOD_LATITUDE)
637 if (outmask & GEOD_LONGITUDE)
639 if (outmask & GEOD_AZIMUTH)
641 if (outmask & GEOD_DISTANCE)
643 if (outmask & GEOD_REDUCEDLENGTH)
645 if (outmask & GEOD_GEODESICSCALE) {
646 if (pM12) *pM12 = M12;
647 if (pM21) *pM21 = M21;
649 if (outmask & GEOD_AREA)
652 return flags & GEOD_ARCMODE ? s12_a12 : sig12 /
degree;
657 l->
a13 =
geod_genposition(l,
GEOD_NOFLAGS, l->
s13, 0, 0, 0, 0, 0, 0, 0, 0);
661 l->
a13 = a13; l->
s13 = NaN;
662 geod_genposition(l, GEOD_ARCMODE, l->
a13, 0, 0, 0, &l->
s13, 0, 0, 0, 0);
666 unsigned flags,
real s13_a13) {
667 flags & GEOD_ARCMODE ?
668 geod_setarc(l, s13_a13) :
674 geod_genposition(l,
FALSE, s12, plat2, plon2, pazi2, 0, 0, 0, 0, 0);
679 unsigned flags,
real s12_a12,
685 (plat2 ? GEOD_LATITUDE : 0
U) |
686 (plon2 ? GEOD_LONGITUDE : 0U) |
687 (pazi2 ? GEOD_AZIMUTH : 0
U) |
688 (ps12 ? GEOD_DISTANCE : 0U) |
689 (pm12 ? GEOD_REDUCEDLENGTH : 0
U) |
690 (pM12 || pM21 ? GEOD_GEODESICSCALE : 0U) |
691 (pS12 ? GEOD_AREA : 0
U);
698 plat2, plon2, pazi2, ps12, pm12, pM12, pM21, pS12);
716 real s12 = 0, m12 = 0, M12 = 0, M21 = 0, S12 = 0;
718 int latsign, lonsign, swapp;
719 real sbet1, cbet1, sbet2, cbet2, s12x = 0, m12x = 0;
720 real dn1, dn2, lam12, slam12, clam12;
721 real a12 = 0, sig12, calp1 = 0, salp1 = 0, calp2 = 0, salp2 = 0;
725 real omg12 = 0, somg12 = 2, comg12 = 0;
728 (ps12 ? GEOD_DISTANCE : 0
U) |
729 (pm12 ? GEOD_REDUCEDLENGTH : 0U) |
730 (pM12 || pM21 ? GEOD_GEODESICSCALE : 0
U) |
731 (pS12 ? GEOD_AREA : 0U);
737 lon12 = AngDiff(lon1, lon2, &lon12s);
739 lonsign = lon12 >= 0 ? 1 : -1;
741 lon12 = lonsign * AngRound(lon12);
742 lon12s = AngRound((180 - lon12) - lonsign * lon12s);
745 sincosdx(lon12s, &slam12, &clam12);
748 sincosdx(lon12, &slam12, &clam12);
751 lat1 = AngRound(LatFix(lat1));
752 lat2 = AngRound(LatFix(lat2));
755 swapp =
fabs(lat1) <
fabs(lat2) ? -1 : 1;
761 latsign = lat1 < 0 ? 1 : -1;
776 sincosdx(lat1, &sbet1, &cbet1); sbet1 *= g->f1;
778 norm2(&sbet1, &cbet1); cbet1 = maxx(tiny, cbet1);
780 sincosdx(lat2, &sbet2, &cbet2); sbet2 *= g->f1;
782 norm2(&sbet2, &cbet2); cbet2 = maxx(tiny, cbet2);
792 if (cbet1 < -sbet1) {
794 sbet2 = sbet2 < 0 ? sbet1 : -sbet1;
796 if (
fabs(sbet2) == -sbet1)
800 dn1 =
sqrt(1 + g->ep2 * sq(sbet1));
801 dn2 =
sqrt(1 + g->ep2 * sq(sbet2));
803 meridian = lat1 == -90 || slam12 == 0;
810 real ssig1, csig1, ssig2, csig2;
811 calp1 = clam12; salp1 = slam12;
812 calp2 = 1; salp2 = 0;
815 ssig1 = sbet1; csig1 = calp1 * cbet1;
816 ssig2 = sbet2; csig2 = calp2 * cbet2;
819 sig12 =
atan2(maxx((
real)(0), csig1 * ssig2 - ssig1 * csig2),
820 csig1 * csig2 + ssig1 * ssig2);
821 Lengths(g, g->n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
822 cbet1, cbet2, &s12x, &m12x, 0,
823 outmask & GEOD_GEODESICSCALE ? &M12 : 0,
824 outmask & GEOD_GEODESICSCALE ? &M21 : 0,
833 if (sig12 < 1 || m12x >= 0) {
835 if (sig12 < 3 * tiny)
836 sig12 = m12x = s12x = 0;
848 (g->
f <= 0 || lon12s >= g->
f * 180)) {
851 calp1 = calp2 = 0; salp1 = salp2 = 1;
853 sig12 = omg12 = lam12 / g->f1;
854 m12x = g->b *
sin(sig12);
855 if (outmask & GEOD_GEODESICSCALE)
856 M12 = M21 =
cos(sig12);
859 }
else if (!meridian) {
866 sig12 = InverseStart(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2,
867 lam12, slam12, clam12,
868 &salp1, &calp1, &salp2, &calp2, &dnm,
873 s12x = sig12 * g->b * dnm;
874 m12x = sq(dnm) * g->b *
sin(sig12 / dnm);
875 if (outmask & GEOD_GEODESICSCALE)
876 M12 = M21 =
cos(sig12 / dnm);
878 omg12 = lam12 / (g->f1 * dnm);
892 real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0, domg12 = 0;
895 real salp1a = tiny, calp1a = 1, salp1b = tiny, calp1b = -1;
897 for (tripn =
FALSE, tripb =
FALSE; numit < maxit2; ++numit) {
901 v = Lambda12(g, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
903 &salp2, &calp2, &sig12, &ssig1, &csig1, &ssig2, &csig2,
904 &eps, &domg12, numit < maxit1, &dv, Ca);
907 if (tripb || !(
fabs(v) >= (tripn ? 8 : 1) * tol0))
break;
909 if (v > 0 && (numit > maxit1 || calp1/salp1 > calp1b/salp1b))
911 else if (v < 0 && (numit > maxit1 || calp1/salp1 < calp1a/salp1a))
913 if (numit < maxit1 && dv > 0) {
917 sdalp1 =
sin(dalp1), cdalp1 =
cos(dalp1),
918 nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
919 if (nsalp1 > 0 &&
fabs(dalp1) < pi) {
920 calp1 = calp1 * cdalp1 - salp1 * sdalp1;
922 norm2(&salp1, &calp1);
926 tripn =
fabs(v) <= 16 * tol0;
938 salp1 = (salp1a + salp1b)/2;
939 calp1 = (calp1a + calp1b)/2;
940 norm2(&salp1, &calp1);
942 tripb = (
fabs(salp1a - salp1) + (calp1a -
calp1) < tolb ||
943 fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb);
945 Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
946 cbet1, cbet2, &s12x, &m12x, 0,
947 outmask & GEOD_GEODESICSCALE ? &M12 : 0,
948 outmask & GEOD_GEODESICSCALE ? &M21 : 0, Ca);
952 if (outmask & GEOD_AREA) {
954 real sdomg12 =
sin(domg12), cdomg12 =
cos(domg12);
955 somg12 = slam12 * cdomg12 - clam12 * sdomg12;
956 comg12 = clam12 * cdomg12 + slam12 * sdomg12;
961 if (outmask & GEOD_DISTANCE)
964 if (outmask & GEOD_REDUCEDLENGTH)
967 if (outmask & GEOD_AREA) {
970 salp0 = salp1 * cbet1,
971 calp0 = hypotx(calp1, salp1 * sbet1);
973 if (calp0 != 0 && salp0 != 0) {
976 ssig1 = sbet1, csig1 = calp1 * cbet1,
977 ssig2 = sbet2, csig2 = calp2 * cbet2,
978 k2 = sq(calp0) * g->ep2,
979 eps = k2 / (2 * (1 +
sqrt(1 + k2)) + k2),
981 A4 = sq(g->
a) * calp0 * salp0 * g->e2;
983 norm2(&ssig1, &csig1);
984 norm2(&ssig2, &csig2);
986 B41 = SinCosSeries(
FALSE, ssig1, csig1, Ca, nC4);
987 B42 = SinCosSeries(
FALSE, ssig2, csig2, Ca, nC4);
988 S12 = A4 * (B42 - B41);
993 if (!meridian && somg12 > 1) {
994 somg12 =
sin(omg12); comg12 =
cos(omg12);
999 comg12 > -(
real)(0.7071) &&
1000 sbet2 - sbet1 < (
real)(1.75)) {
1005 domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
1006 alp12 = 2 *
atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
1007 domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) );
1011 salp12 = salp2 * calp1 - calp2 *
salp1,
1012 calp12 = calp2 * calp1 + salp2 *
salp1;
1017 if (salp12 == 0 && calp12 < 0) {
1018 salp12 = tiny *
calp1;
1021 alp12 =
atan2(salp12, calp12);
1023 S12 += g->c2 * alp12;
1024 S12 *= swapp * lonsign * latsign;
1031 swapx(&salp1, &salp2);
1032 swapx(&calp1, &calp2);
1033 if (outmask & GEOD_GEODESICSCALE)
1037 salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
1038 salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
1040 if (psalp1) *psalp1 =
salp1;
1041 if (pcalp1) *pcalp1 =
calp1;
1042 if (psalp2) *psalp2 = salp2;
1043 if (pcalp2) *pcalp2 = calp2;
1045 if (outmask & GEOD_DISTANCE)
1047 if (outmask & GEOD_REDUCEDLENGTH)
1049 if (outmask & GEOD_GEODESICSCALE) {
1050 if (pM12) *pM12 = M12;
1051 if (pM21) *pM21 = M21;
1053 if (outmask & GEOD_AREA)
1065 a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, ps12,
1066 &salp1, &calp1, &salp2, &calp2,
1067 pm12, pM12, pM21, pS12);
1068 if (pazi1) *pazi1 = atan2dx(salp1, calp1);
1069 if (pazi2) *pazi2 = atan2dx(salp2, calp2);
1078 a12 = geod_geninverse_int(g, lat1, lon1, lat2, lon2, 0,
1079 &salp1, &calp1, 0, 0,
1081 azi1 = atan2dx(salp1, calp1);
1085 geod_lineinit_int(l, g, lat1, lon1, azi1, salp1, calp1, caps);
1086 geod_setarc(l, a12);
1092 geod_geninverse(g, lat1, lon1, lat2, lon2, ps12, pazi1, pazi2, 0, 0, 0, 0);
1103 ar = 2 * (cosx - sinx) * (cosx + sinx);
1104 y0 = n & 1 ? *--c : 0; y1 = 0;
1109 y1 = ar * y0 - y1 + *--
c;
1110 y0 = ar * y1 - y0 + *--
c;
1113 ? 2 * sinx * cosx * y0
1126 real m0 = 0, J12 = 0, A1 = 0, A2 = 0;
1131 boolx redlp = pm12b || pm0 || pM12 || pM21;
1132 if (ps12b || redlp) {
1144 real B1 = SinCosSeries(
TRUE, ssig2, csig2, Ca, nC1) -
1145 SinCosSeries(
TRUE, ssig1, csig1, Ca, nC1);
1147 *ps12b = A1 * (sig12 + B1);
1149 real B2 = SinCosSeries(
TRUE, ssig2, csig2, Cb, nC2) -
1150 SinCosSeries(
TRUE, ssig1, csig1, Cb, nC2);
1151 J12 = m0 * sig12 + (A1 * B1 - A2 * B2);
1156 for (l = 1; l <= nC2; ++
l)
1157 Cb[l] = A1 * Ca[l] - A2 * Cb[l];
1158 J12 = m0 * sig12 + (SinCosSeries(
TRUE, ssig2, csig2, Cb, nC2) -
1159 SinCosSeries(
TRUE, ssig1, csig1, Cb, nC2));
1166 *pm12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
1167 csig1 * csig2 * J12;
1169 real csig12 = csig1 * csig2 + ssig1 * ssig2;
1170 real t = g->ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
1172 *pM12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
1174 *pM21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
1185 r = (p + q - 1) / 6;
1186 if ( !(q == 0 && r <= 0) ) {
1195 disc = S * (S + 2 *
r3);
1203 T3 += T3 < 0 ? -
sqrt(disc) : sqrt(disc);
1207 u += T + (T != 0 ? r2 / T : 0);
1213 u += 2 * r *
cos(ang / 3);
1215 v =
sqrt(sq(u) + q);
1217 uv = u < 0 ? q / (v - u) : u + v;
1218 w = (uv -
q) / (2 * v);
1221 k = uv / (
sqrt(uv + sq(w)) +
w);
1241 real salp1 = 0, calp1 = 0, salp2 = 0, calp2 = 0, dnm = 0;
1249 sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
1250 cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
1252 boolx shortline = cbet12 >= 0 && sbet12 < (
real)(0.5) &&
1253 cbet2 * lam12 < (
real)(0.5);
1254 real somg12, comg12, ssig12, csig12;
1255 #if defined(__GNUC__) && __GNUC__ == 4 && \ 1256 (__GNUC_MINOR__ < 6 || defined(__MINGW32__)) 1264 volatile real xx1 = sbet2 * cbet1;
1265 volatile real xx2 = cbet2 * sbet1;
1266 sbet12a = xx1 + xx2;
1269 sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
1272 real sbetm2 = sq(sbet1 + sbet2), omg12;
1275 sbetm2 /= sbetm2 + sq(cbet1 + cbet2);
1276 dnm =
sqrt(1 + g->ep2 * sbetm2);
1277 omg12 = lam12 / (g->f1 * dnm);
1278 somg12 =
sin(omg12); comg12 =
cos(omg12);
1280 somg12 = slam12; comg12 = clam12;
1283 salp1 = cbet2 * somg12;
1284 calp1 = comg12 >= 0 ?
1285 sbet12 + cbet2 * sbet1 * sq(somg12) / (1 + comg12) :
1286 sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
1288 ssig12 = hypotx(salp1, calp1);
1289 csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
1291 if (shortline && ssig12 < g->etol2) {
1293 salp2 = cbet1 * somg12;
1294 calp2 = sbet12 - cbet1 * sbet2 *
1295 (comg12 >= 0 ? sq(somg12) / (1 + comg12) : 1 - comg12);
1296 norm2(&salp2, &calp2);
1298 sig12 =
atan2(ssig12, csig12);
1299 }
else if (
fabs(g->n) > (
real)(0.1) ||
1301 ssig12 >= 6 *
fabs(g->n) * pi * sq(cbet1)) {
1306 real y, lamscale, betscale;
1316 k2 = sq(sbet1) * g->ep2,
1317 eps = k2 / (2 * (1 +
sqrt(1 + k2)) + k2);
1318 lamscale = g->
f * cbet1 * A3f(g, eps) * pi;
1320 betscale = lamscale * cbet1;
1322 x = lam12x / lamscale;
1323 y = sbet12a / betscale;
1327 cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
1328 bet12a =
atan2(sbet12a, cbet12a);
1332 Lengths(g, g->n, pi + bet12a,
1333 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
1334 cbet1, cbet2, 0, &m12b, &m0, 0, 0, Ca);
1335 x = -1 + m12b / (cbet1 * cbet2 * m0 * pi);
1336 betscale = x < -(
real)(0.01) ? sbet12a / x :
1337 -g->
f * sq(cbet1) * pi;
1338 lamscale = betscale / cbet1;
1339 y = lam12x / lamscale;
1342 if (y > -tol1 && x > -1 - xthresh) {
1345 salp1 = minx((
real)(1), -(
real)(x)); calp1 = -
sqrt(1 - sq(salp1));
1347 calp1 = maxx((
real)(x > -tol1 ? 0 : -1), (
real)(x));
1348 salp1 =
sqrt(1 - sq(calp1));
1385 real k = Astroid(x, y);
1387 omg12a = lamscale * ( g->
f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
1388 somg12 =
sin(omg12a); comg12 = -
cos(omg12a);
1390 salp1 = cbet2 * somg12;
1391 calp1 = sbet12a - cbet2 * sbet1 * sq(somg12) / (1 - comg12);
1396 norm2(&salp1, &calp1);
1398 salp1 = 1; calp1 = 0;
1423 boolx diffp,
real* pdlam12,
1426 real salp2 = 0, calp2 = 0, sig12 = 0,
1427 ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, eps = 0,
1428 domg12 = 0, dlam12 = 0;
1430 real somg1, comg1, somg2, comg2, somg12, comg12, lam12;
1433 if (sbet1 == 0 && calp1 == 0)
1439 salp0 = salp1 * cbet1;
1440 calp0 = hypotx(calp1, salp1 * sbet1);
1444 ssig1 = sbet1; somg1 = salp0 * sbet1;
1445 csig1 = comg1 = calp1 * cbet1;
1446 norm2(&ssig1, &csig1);
1453 salp2 = cbet2 != cbet1 ? salp0 / cbet2 :
salp1;
1458 calp2 = cbet2 != cbet1 ||
fabs(sbet2) != -sbet1 ?
1459 sqrt(sq(calp1 * cbet1) +
1461 (cbet2 - cbet1) * (cbet1 + cbet2) :
1462 (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 :
1466 ssig2 = sbet2; somg2 = salp0 * sbet2;
1467 csig2 = comg2 = calp2 * cbet2;
1468 norm2(&ssig2, &csig2);
1472 sig12 =
atan2(maxx((
real)(0), csig1 * ssig2 - ssig1 * csig2),
1473 csig1 * csig2 + ssig1 * ssig2);
1476 somg12 = maxx((
real)(0), comg1 * somg2 - somg1 * comg2);
1477 comg12 = comg1 * comg2 + somg1 * somg2;
1479 eta =
atan2(somg12 * clam120 - comg12 * slam120,
1480 comg12 * clam120 + somg12 * slam120);
1481 k2 = sq(calp0) * g->ep2;
1482 eps = k2 / (2 * (1 +
sqrt(1 + k2)) + k2);
1484 B312 = (SinCosSeries(
TRUE, ssig2, csig2, Ca, nC3-1) -
1485 SinCosSeries(
TRUE, ssig1, csig1, Ca, nC3-1));
1486 domg12 = -g->
f * A3f(g, eps) * salp0 * (sig12 + B312);
1487 lam12 = eta + domg12;
1491 dlam12 = - 2 * g->f1 * dn1 / sbet1;
1493 Lengths(g, eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1494 cbet1, cbet2, 0, &dlam12, 0, 0, 0, Ca);
1495 dlam12 *= g->f1 / (calp2 * cbet2);
1516 return polyval(nA3 - 1, g->A3x, eps);
1524 for (l = 1; l < nC3; ++
l) {
1525 int m = nC3 - l - 1;
1527 c[
l] = mult * polyval(m, g->C3x + o, eps);
1537 for (l = 0; l < nC4; ++
l) {
1538 int m = nC4 - l - 1;
1539 c[
l] = mult * polyval(m, g->C4x + o, eps);
1547 static const real coeff[] = {
1552 real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1553 return (t + eps) / (1 - eps);
1558 static const real coeff[] = {
1576 for (l = 1; l <= nC1; ++
l) {
1577 int m = (nC1 -
l) / 2;
1578 c[
l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1586 static const real coeff[] = {
1588 205, -432, 768, 1536,
1590 4005, -4736, 3840, 12288,
1604 for (l = 1; l <= nC1p; ++
l) {
1605 int m = (nC1p -
l) / 2;
1606 c[
l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1614 static const real coeff[] = {
1616 -11, -28, -192, 0, 256,
1619 real t = polyval(m, coeff, sq(eps)) / coeff[m + 1];
1620 return (t - eps) / (1 + eps);
1625 static const real coeff[] = {
1643 for (l = 1; l <= nC2; ++
l) {
1644 int m = (nC2 -
l) / 2;
1645 c[
l] = d * polyval(m, coeff + o, eps2) / coeff[o + m + 1];
1653 static const real coeff[] = {
1667 int o = 0, k = 0,
j;
1668 for (
j = nA3 - 1;
j >= 0; --
j) {
1669 int m = nA3 -
j - 1 <
j ? nA3 -
j - 1 :
j;
1670 g->A3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1677 static const real coeff[] = {
1709 int o = 0, k = 0,
l,
j;
1710 for (l = 1; l < nC3; ++
l) {
1711 for (j = nC3 - 1; j >=
l; --
j) {
1712 int m = nC3 - j - 1 < j ? nC3 - j - 1 :
j;
1713 g->C3x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1721 static const real coeff[] = {
1727 -224, -4784, 1573, 45045,
1729 -10656, 14144, -4576, -858, 45045,
1731 64, 624, -4576, 6864, -3003, 15015,
1733 100, 208, 572, 3432, -12012, 30030, 45045,
1739 5792, 1040, -1287, 135135,
1741 5952, -11648, 9152, -2574, 135135,
1743 -64, -624, 4576, -6864, 3003, 135135,
1749 -8448, 4992, -1144, 225225,
1751 -1440, 4160, -4576, 1716, 225225,
1757 3584, -3328, 1144, 315315,
1765 int o = 0, k = 0,
l,
j;
1766 for (l = 0; l < nC4; ++
l) {
1767 for (j = nC4 - 1; j >=
l; --
j) {
1768 int m = nC4 - j - 1;
1769 g->C4x[k++] = polyval(m, coeff + o, g->n) / coeff[o + m + 1];
1775 int transit(
real lon1,
real lon2) {
1780 lon1 = AngNormalize(lon1);
1781 lon2 = AngNormalize(lon2);
1782 lon12 = AngDiff(lon1, lon2, 0);
1783 return lon1 <= 0 && lon2 > 0 && lon12 > 0 ? 1 :
1784 (lon2 <= 0 && lon1 > 0 && lon12 < 0 ? -1 : 0);
1787 int transitdirect(
real lon1,
real lon2) {
1791 return ( (lon2 >= 0 && lon2 < 360 ? 0 : 1) -
1792 (lon1 >= 0 && lon1 < 360 ? 0 : 1) );
1796 return ( ((lon2 >= 0 && lon2 < 360) || lon2 < -360 ? 0 : 1) -
1797 ((lon1 >= 0 && lon1 < 360) || lon1 < -360 ? 0 : 1) );
1801 void accini(
real s[]) {
1806 void acccopy(
const real s[],
real t[]) {
1808 t[0] = s[0]; t[1] = s[1];
1813 real u, z = sumx(y, s[1], &u);
1814 s[0] = sumx(z, s[0], &s[1]);
1829 void accneg(
real s[]) {
1831 s[0] = -s[0]; s[1] = -s[1];
1835 p->polyline = (polylinep != 0);
1840 p->lat0 = p->lon0 = p->
lat = p->
lon = NaN;
1843 p->
num = p->crossings = 0;
1849 lon = AngNormalize(lon);
1856 &s12, 0, 0, 0, 0, 0, p->polyline ? 0 : &S12);
1860 p->crossings += transit(p->
lon, lon);
1874 0, 0, 0, 0, p->polyline ? 0 : &S12);
1878 p->crossings += transitdirect(p->
lon, lon);
1889 real s12, S12, t[2], area0;
1893 if (!p->polyline && pA) *pA = 0;
1897 if (pP) *pP = p->P[0];
1901 &s12, 0, 0, 0, 0, 0, &S12);
1902 if (pP) *pP = accsum(p->P, s12);
1905 crossings = p->crossings + transit(p->
lon, p->lon0);
1906 area0 = 4 * pi * g->c2;
1908 accadd(t, (t[0] < 0 ? 1 : -1) * area0/2);
1917 else if (t[0] <= -area0/2)
1925 if (pA) *pA = 0 + t[0];
1932 boolx reverse, boolx sign,
1934 real perimeter, tempsum, area0;
1936 unsigned num = p->
num + 1;
1939 if (!p->polyline && pA) *pA = 0;
1942 perimeter = p->P[0];
1943 tempsum = p->polyline ? 0 : p->A[0];
1944 crossings = p->crossings;
1945 for (i = 0; i < (p->polyline ? 1 : 2); ++
i) {
1948 i == 0 ? p->
lat : lat, i == 0 ? p->
lon : lon,
1949 i != 0 ? p->lat0 : lat, i != 0 ? p->lon0 : lon,
1950 &s12, 0, 0, 0, 0, 0, p->polyline ? 0 : &S12);
1954 crossings += transit(i == 0 ? p->
lon : lon,
1955 i != 0 ? p->lon0 : lon);
1959 if (pP) *pP = perimeter;
1963 area0 = 4 * pi * g->c2;
1965 tempsum += (tempsum < 0 ? 1 : -1) * area0/2;
1972 if (tempsum > area0/2)
1974 else if (tempsum <= -area0/2)
1977 if (tempsum >= area0)
1979 else if (tempsum < 0)
1982 if (pA) *pA = 0 + tempsum;
1989 boolx reverse, boolx sign,
1991 real perimeter, tempsum, area0;
1993 unsigned num = p->
num + 1;
1996 if (!p->polyline && pA) *pA = NaN;
1999 perimeter = p->P[0] +
s;
2001 if (pP) *pP = perimeter;
2006 crossings = p->crossings;
2013 crossings += transitdirect(p->
lon, lon);
2015 &s12, 0, 0, 0, 0, 0, &S12);
2018 crossings += transit(lon, p->lon0);
2021 area0 = 4 * pi * g->c2;
2023 tempsum += (tempsum < 0 ? 1 : -1) * area0/2;
2030 if (tempsum > area0/2)
2032 else if (tempsum <= -area0/2)
2035 if (tempsum >= area0)
2037 else if (tempsum < 0)
2040 if (pP) *pP = perimeter;
2041 if (pA) *pA = 0 + tempsum;
2051 for (i = 0; i <
n; ++
i)
unsigned geod_polygon_testedge(const struct geod_geodesic *g, const struct geod_polygon *p, double azi, double s, int reverse, int sign, double *pA, double *pP)
void geod_directline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, unsigned caps)
double geod_genposition(const struct geod_geodesicline *l, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
static const Pose3 T3(Rot3::Rodrigues(-90, 0, 0), Point3(1, 2, 3))
void geod_gendirectline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, unsigned caps)
EIGEN_DEVICE_FUNC const LogReturnType log() const
EIGEN_DEVICE_FUNC const SqrtReturnType sqrt() const
void geod_polygon_addedge(const struct geod_geodesic *g, struct geod_polygon *p, double azi, double s)
void geod_position(const struct geod_geodesicline *l, double s12, double *plat2, double *plon2, double *pazi2)
void geod_lineinit(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned caps)
const mpreal remainder(const mpreal &x, const mpreal &y, mp_rnd_t rnd_mode=mpreal::get_default_rnd())
void g(const string &key, int i)
void geod_setdistance(struct geod_geodesicline *l, double s13)
EIGEN_DEVICE_FUNC const CosReturnType cos() const
internal::enable_if< !(internal::is_same< typename Derived::Scalar, ScalarExponent >::value)&&EIGEN_SCALAR_BINARY_SUPPORTED(pow, typename Derived::Scalar, ScalarExponent), const EIGEN_EXPR_BINARYOP_SCALAR_RETURN_TYPE(Derived, ScalarExponent, pow) >::type pow(const Eigen::ArrayBase< Derived > &x, const ScalarExponent &exponent)
static const Line3 l(Rot3(), 1, 1)
EIGEN_DEVICE_FUNC const SignReturnType sign() const
double norm2(const Point2 &p, OptionalJacobian< 1, 2 > H)
Distance of the point from the origin, with Jacobian.
void geod_inverseline(struct geod_geodesicline *l, const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, unsigned caps)
double geod_geninverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2, double *pm12, double *pM12, double *pM21, double *pS12)
Eigen::Triplet< double > T
void geod_polygon_addpoint(const struct geod_geodesic *g, struct geod_polygon *p, double lat, double lon)
EIGEN_DEVICE_FUNC const AtanReturnType atan() const
Point2(* f)(const Point3 &, OptionalJacobian< 2, 3 >)
Array< double, 1, 3 > e(1./3., 0.5, 2.)
EIGEN_DEVICE_FUNC const Scalar & q
void geod_polygon_clear(struct geod_polygon *p)
void geod_polygon_init(struct geod_polygon *p, int polylinep)
void geod_direct(const struct geod_geodesic *g, double lat1, double lon1, double azi1, double s12, double *plat2, double *plon2, double *pazi2)
unsigned geod_polygon_compute(const struct geod_geodesic *g, const struct geod_polygon *p, int reverse, int sign, double *pA, double *pP)
Jet< T, N > atan2(const Jet< T, N > &g, const Jet< T, N > &f)
void geod_polygonarea(const struct geod_geodesic *g, double lats[], double lons[], int n, double *pA, double *pP)
void geod_gensetdistance(struct geod_geodesicline *l, unsigned flags, double s13_a13)
double geod_gendirect(const struct geod_geodesic *g, double lat1, double lon1, double azi1, unsigned flags, double s12_a12, double *plat2, double *plon2, double *pazi2, double *ps12, double *pm12, double *pM12, double *pM21, double *pS12)
EIGEN_DEVICE_FUNC const FloorReturnType floor() const
void reverse(const MatrixType &m)
unsigned geod_polygon_testpoint(const struct geod_geodesic *g, const struct geod_polygon *p, double lat, double lon, int reverse, int sign, double *pA, double *pP)
void geod_inverse(const struct geod_geodesic *g, double lat1, double lon1, double lat2, double lon2, double *ps12, double *pazi1, double *pazi2)
EIGEN_DEVICE_FUNC const SinReturnType sin() const
const mpreal remquo(long *q, const mpreal &x, const mpreal &y, mp_rnd_t rnd_mode=mpreal::get_default_rnd())
void geod_init(struct geod_geodesic *g, double a, double f)
set noclip points set clip one set noclip two set bar set border lt lw set xdata set ydata set zdata set x2data set y2data set boxwidth set dummy x
EIGEN_DEVICE_FUNC EIGEN_ALWAYS_INLINE T fmod(const T &a, const T &b)
API for the geodesic routines in C.