36# pragma warning (disable: 4701 4127 5055 5054)
43 GeodesicExact::GeodesicExact(real a, real f)
44 : maxit2_(maxit1_ +
Math::digits() + 10)
48 , tiny_(sqrt(numeric_limits<real>::min()))
49 , tol0_(numeric_limits<real>::epsilon())
56 , xthresh_(1000 * tol2_)
61 , _ep2(_e2 /
Math::sq(_f1))
69 (_f > 0 ? asinh(sqrt(_ep2)) : atan(sqrt(-_e2))) /
81 , _etol2(real(0.1) * tol2_ /
82 sqrt( fmax(real(0.001), fabs(_f)) * fmin(real(1), 1 - _f/2) / 2 ))
84 if (!(isfinite(_a) && _a > 0))
86 if (!(isfinite(_b) && _b > 0))
300 static const int ndiv = 100;
320#if GEOGRAPHICLIB_PRECISION == 1
321 static const unsigned char narr[2*ndiv+1] = {
322 19,18,16,15,14,13,13,13,12,12,11,11,11,11,10,10,10,10,9,9,9,9,9,9,9,9,8,
323 8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,6,6,6,6,5,5,5,5,5,5,5,5,
324 5,5,5,5,5,5,5,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,
325 2,2,2,2,2,2,2,2,2,2,2,2,2,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,
326 4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,
327 6,6,6,6,6,6,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,8
329#elif GEOGRAPHICLIB_PRECISION == 2
330 static const unsigned char narr[2*ndiv+1] = {
331 22,21,19,18,17,17,16,15,15,15,14,14,14,13,13,13,13,13,13,12,12,12,12,12,
332 12,11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,10,9,9,9,9,9,9,9,9,
333 9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,7,7,7,7,7,7,7,6,6,6,6,6,6,
334 6,6,5,5,5,5,5,5,5,5,4,4,3,2,3,4,4,5,5,5,5,5,5,5,5,6,6,6,6,6,6,6,6,6,7,7,
335 7,7,7,7,7,7,7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,
336 9,9,9,9,9,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,12,12,
337 12,12,12,13,13,13,13,13,14,14,15,15,16,17,18,19
339#elif GEOGRAPHICLIB_PRECISION == 3
340 static const unsigned char narr[2*ndiv+1] = {
341 23,22,20,19,18,17,17,16,16,15,15,15,15,14,14,14,14,13,13,13,13,13,13,13,
342 12,12,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,
343 10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
344 7,7,7,7,7,6,6,6,6,6,6,5,5,5,5,5,4,2,4,5,5,5,5,5,6,6,6,6,6,6,6,7,7,7,7,7,
345 7,7,7,7,7,7,7,7,8,8,8,8,8,8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
346 10,10,10,10,10,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,11,12,12,12,
347 12,12,12,13,13,13,13,13,13,13,14,14,14,15,15,15,16,16,17,18,19,20
349#elif GEOGRAPHICLIB_PRECISION == 4
350 static const unsigned char narr[2*ndiv+1] = {
351 25,24,22,21,20,19,19,18,18,17,17,17,17,16,16,16,15,15,15,15,15,15,15,14,
352 14,14,14,14,14,13,13,13,13,13,13,13,13,13,13,13,13,12,12,12,12,12,12,12,
353 12,12,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,10,10,10,10,10,10,10,
354 10,10,10,9,9,9,9,9,9,9,9,9,9,9,9,9,8,8,8,8,8,8,7,7,7,7,7,6,2,6,7,7,7,7,7,
355 8,8,8,8,8,8,8,9,9,9,9,9,9,9,9,9,9,9,9,9,10,10,10,10,10,10,10,10,10,10,10,
356 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,12,12,12,12,12,12,12,12,12,
357 12,13,13,13,13,13,13,13,13,13,13,13,14,14,14,14,14,14,15,15,15,15,15,15,
358 15,16,16,16,17,17,17,17,18,18,19,20,21,23,24
360#elif GEOGRAPHICLIB_PRECISION == 5
361 static const unsigned char narr[2*ndiv+1] = {
362 27,26,24,23,22,22,21,21,20,20,20,19,19,19,19,18,18,18,18,18,17,17,17,17,
363 17,17,17,17,16,16,16,16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,14,
364 14,14,14,14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,13,13,13,13,13,
365 12,12,12,12,12,12,12,12,12,12,11,11,11,11,11,11,11,11,11,11,11,10,10,10,
366 10,9,9,9,2,9,9,9,10,10,10,10,10,11,11,11,11,11,11,11,11,11,11,12,12,12,
367 12,12,12,12,12,12,12,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,14,14,
368 14,14,14,14,14,14,14,14,14,15,15,15,15,15,15,15,15,15,15,15,15,16,16,16,
369 16,16,16,16,17,17,17,17,17,17,17,17,18,18,18,18,18,19,19,19,19,20,20,21,
373#error "Bad value for GEOGRAPHICLIB_PRECISION"
376 int j = ndiv + int(n < 0 ? floor(n) : ceil(n));
377 int N = int(narr[j]);
379 N = (N % 2 == 0 ? 2 : 3) * (1 << (N/2));
380#if GEOGRAPHICLIB_PRECISION == 5
385 while (N < M) N = N % 3 == 0 ? 4*N/3 : 3*N/2;
399 unsigned caps)
const {
404 bool arcmode, real s12_a12,
406 real& lat2, real& lon2, real& azi2,
407 real& s12, real& m12,
408 real& M12, real& M21,
414 GenPosition(arcmode, s12_a12, outmask,
415 lat2, lon2, azi2, s12, m12, M12, M21, S12);
420 bool arcmode, real s12_a12,
421 unsigned caps)
const {
429 caps, arcmode, s12_a12);
434 unsigned caps)
const {
440 unsigned caps)
const {
446 unsigned outmask,
real& s12,
457 int lonsign = signbit(lon12) ? -1 : 1;
458 lon12 *= lonsign; lon12s *= lonsign;
465 lon12s = (
Math::hd - lon12) - lon12s;
472 int swapp = fabs(lat1) < fabs(lat2) || isnan(lat2) ? -1 : 1;
478 int latsign = signbit(lat1) ? 1 : -1;
493 real sbet1, cbet1, sbet2, cbet2, s12x, m12x;
496 EllipticFunction E(-_ep2);
501 Math::norm(sbet1, cbet1); cbet1 = fmax(tiny_, cbet1);
505 Math::norm(sbet2, cbet2); cbet2 = fmax(tiny_, cbet2);
515 if (cbet1 < -sbet1) {
517 sbet2 = copysign(sbet1, sbet2);
519 if (fabs(sbet2) == -sbet1)
524 dn1 = (_f >= 0 ? sqrt(1 + _ep2 *
Math::sq(sbet1)) :
525 sqrt(1 - _e2 * Math::sq(cbet1)) / _f1),
526 dn2 = (_f >= 0 ? sqrt(1 + _ep2 * Math::sq(sbet2)) :
527 sqrt(1 - _e2 * Math::sq(cbet2)) / _f1);
531 bool meridian = lat1 == -
Math::qd || slam12 == 0;
538 calp1 = clam12; salp1 = slam12;
539 calp2 = 1; salp2 = 0;
543 ssig1 = sbet1, csig1 = calp1 * cbet1,
544 ssig2 = sbet2, csig2 = calp2 * cbet2;
547 sig12 = atan2(fmax(
real(0), csig1 * ssig2 - ssig1 * csig2),
548 csig1 * csig2 + ssig1 * ssig2);
551 Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
553 s12x, m12x, dummy, M12, M21);
562 if (sig12 < 1 || m12x >= 0) {
564 if (sig12 < 3 * tiny_ ||
566 (sig12 < tol0_ && (s12x < 0 || m12x < 0)))
567 sig12 = m12x = s12x = 0;
577 real omg12 = 0, somg12 = 2, comg12 = 0;
580 (_f <= 0 || lon12s >= _f *
Math::hd)) {
583 calp1 = calp2 = 0; salp1 = salp2 = 1;
585 sig12 = omg12 = lam12 / _f1;
586 m12x = _b * sin(sig12);
588 M12 = M21 = cos(sig12);
591 }
else if (!meridian) {
598 sig12 = InverseStart(E, sbet1, cbet1, dn1, sbet2, cbet2, dn2,
599 lam12, slam12, clam12,
600 salp1, calp1, salp2, calp2, dnm);
604 s12x = sig12 * _b * dnm;
605 m12x =
Math::sq(dnm) * _b * sin(sig12 / dnm);
607 M12 = M21 = cos(sig12 / dnm);
609 omg12 = lam12 / (_f1 * dnm);
625 real ssig1 = 0, csig1 = 0, ssig2 = 0, csig2 = 0, domg12 = 0;
628 real salp1a = tiny_, calp1a = 1, salp1b = tiny_, calp1b = -1;
629 for (
bool tripn =
false, tripb =
false;; ++numit) {
652 real v = Lambda12(sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
654 salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
655 E, domg12, numit < maxit1_, dv);
658 !(fabs(v) >= (tripn ? 8 : 1) * tol0_) ||
663 if (v > 0 && (numit > maxit1_ || calp1/salp1 > calp1b/salp1b))
664 { salp1b = salp1; calp1b = calp1; }
665 else if (v < 0 && (numit > maxit1_ || calp1/salp1 < calp1a/salp1a))
666 { salp1a = salp1; calp1a = calp1; }
667 if (numit < maxit1_ && dv > 0) {
675 sdalp1 = sin(dalp1), cdalp1 = cos(dalp1),
676 nsalp1 = salp1 * cdalp1 + calp1 * sdalp1;
678 calp1 = calp1 * cdalp1 - salp1 * sdalp1;
684 tripn = fabs(v) <= 16 * tol0_;
697 salp1 = (salp1a + salp1b)/2;
698 calp1 = (calp1a + calp1b)/2;
701 tripb = (fabs(salp1a - salp1) + (calp1a - calp1) < tolb_ ||
702 fabs(salp1 - salp1b) + (calp1 - calp1b) < tolb_);
706 Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
707 cbet1, cbet2, outmask, s12x, m12x, dummy, M12, M21);
712 if (outmask &
AREA) {
714 real sdomg12 = sin(domg12), cdomg12 = cos(domg12);
715 somg12 = slam12 * cdomg12 - clam12 * sdomg12;
716 comg12 = clam12 * cdomg12 + slam12 * sdomg12;
722 s12 =
real(0) + s12x;
725 m12 =
real(0) + m12x;
727 if (outmask &
AREA) {
730 salp0 = salp1 * cbet1,
731 calp0 = hypot(calp1, salp1 * sbet1);
734 A4 =
Math::sq(_a) * calp0 * salp0 * _e2;
739 ssig1 = sbet1, csig1 = calp1 * cbet1,
740 ssig2 = sbet2, csig2 = calp2 * cbet2;
743 I4Integrand i4(_ep2, k2);
744 vector<real> C4a(_nC4);
746 S12 = A4 *
DST::integral(ssig1, csig1, ssig2, csig2, C4a.data(), _nC4);
751 if (!meridian && somg12 == 2) {
752 somg12 = sin(omg12); comg12 = cos(omg12);
757 comg12 > -
real(0.7071) &&
758 sbet2 - sbet1 <
real(1.75)) {
762 real domg12 = 1 + comg12, dbet1 = 1 + cbet1, dbet2 = 1 + cbet2;
763 alp12 = 2 * atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
764 domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) );
768 salp12 = salp2 * calp1 - calp2 * salp1,
769 calp12 = calp2 * calp1 + salp2 * salp1;
774 if (salp12 == 0 && calp12 < 0) {
775 salp12 = tiny_ * calp1;
778 alp12 = atan2(salp12, calp12);
781 S12 *= swapp * lonsign * latsign;
794 salp1 *= swapp * lonsign; calp1 *= swapp * latsign;
795 salp2 *= swapp * lonsign; calp2 *= swapp * latsign;
802 real lat2, real lon2,
804 real& s12, real& azi1, real& azi2,
805 real& m12, real& M12, real& M21,
808 real salp1, calp1, salp2, calp2,
809 a12 = GenInverse(lat1, lon1, lat2, lon2,
810 outmask, s12, salp1, calp1, salp2, calp2,
820 real lat2, real lon2,
821 unsigned caps)
const {
822 real t, salp1, calp1, salp2, calp2,
823 a12 = GenInverse(lat1, lon1, lat2, lon2,
825 0u, t, salp1, calp1, salp2, calp2,
838 real cbet1,
real cbet2,
unsigned outmask,
855 (sig12 + (E.
deltaE(ssig2, csig2, dn2) - E.
deltaE(ssig1, csig1, dn1)));
860 (sig12 + (E.
deltaD(ssig2, csig2, dn2) - E.
deltaD(ssig1, csig1, dn1)));
866 m12b = dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
870 real csig12 = csig1 * csig2 + ssig1 * ssig2;
871 real t = _ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2);
872 M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1;
873 M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2;
886 if ( !(q == 0 && r <= 0) ) {
895 disc = S * (S + 2 * r3);
902 T3 += T3 < 0 ? -sqrt(disc) : sqrt(disc);
906 u += T + (T != 0 ? r2 / T : 0);
909 real ang = atan2(sqrt(-disc), -(S + r3));
912 u += 2 * r * cos(ang / 3);
917 uv = u < 0 ? q / (v - u) : u + v,
918 w = (uv - q) / (2 * v);
921 k = uv / (sqrt(uv +
Math::sq(w)) + w);
930 Math::real GeodesicExact::InverseStart(EllipticFunction& E,
945 sbet12 = sbet2 * cbet1 - cbet2 * sbet1,
946 cbet12 = cbet2 * cbet1 + sbet2 * sbet1;
947 real sbet12a = sbet2 * cbet1 + cbet2 * sbet1;
948 bool shortline = cbet12 >= 0 && sbet12 <
real(0.5) &&
949 cbet2 * lam12 <
real(0.5);
955 sbetm2 /= sbetm2 +
Math::sq(cbet1 + cbet2);
956 dnm = sqrt(1 + _ep2 * sbetm2);
957 real omg12 = lam12 / (_f1 * dnm);
958 somg12 = sin(omg12); comg12 = cos(omg12);
960 somg12 = slam12; comg12 = clam12;
963 salp1 = cbet2 * somg12;
964 calp1 = comg12 >= 0 ?
965 sbet12 + cbet2 * sbet1 *
Math::sq(somg12) / (1 + comg12) :
966 sbet12a - cbet2 * sbet1 *
Math::sq(somg12) / (1 - comg12);
969 ssig12 = hypot(salp1, calp1),
970 csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12;
972 if (shortline && ssig12 < _etol2) {
974 salp2 = cbet1 * somg12;
975 calp2 = sbet12 - cbet1 * sbet2 *
976 (comg12 >= 0 ?
Math::sq(somg12) / (1 + comg12) : 1 - comg12);
979 sig12 = atan2(ssig12, csig12);
980 }
else if (fabs(_n) >
real(0.1) ||
987 real x, y, lamscale, betscale;
988 real lam12x = atan2(-slam12, -clam12);
993 E.Reset(-k2, -_ep2, 1 + k2, 1 + _ep2);
994 lamscale = _e2/_f1 * cbet1 * 2 * E.H();
996 betscale = lamscale * cbet1;
998 x = lam12x / lamscale;
999 y = sbet12a / betscale;
1003 cbet12a = cbet2 * cbet1 - sbet2 * sbet1,
1004 bet12a = atan2(sbet12a, cbet12a);
1005 real m12b, m0, dummy;
1009 sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
1010 cbet1, cbet2,
REDUCEDLENGTH, dummy, m12b, m0, dummy, dummy);
1011 x = -1 + m12b / (cbet1 * cbet2 * m0 *
Math::pi());
1012 betscale = x < -
real(0.01) ? sbet12a / x :
1014 lamscale = betscale / cbet1;
1015 y = lam12x / lamscale;
1018 if (y > -tol1_ && x > -1 - xthresh_) {
1022 salp1 = fmin(
real(1), -x); calp1 = - sqrt(1 -
Math::sq(salp1));
1024 calp1 = fmax(
real(x > -tol1_ ? 0 : -1), x);
1062 real k = Astroid(x, y);
1064 omg12a = lamscale * ( _f >= 0 ? -x * k/(1 + k) : -y * (1 + k)/k );
1065 somg12 = sin(omg12a); comg12 = -cos(omg12a);
1067 salp1 = cbet2 * somg12;
1068 calp1 = sbet12a - cbet2 * sbet1 *
Math::sq(somg12) / (1 - comg12);
1075 salp1 = 1; calp1 = 0;
1088 EllipticFunction& E,
1090 bool diffp,
real& dlam12)
const
1093 if (sbet1 == 0 && calp1 == 0)
1100 salp0 = salp1 * cbet1,
1101 calp0 = hypot(calp1, salp1 * sbet1);
1103 real somg1, comg1, somg2, comg2, somg12, comg12, cchi1, cchi2, lam12;
1106 ssig1 = sbet1; somg1 = salp0 * sbet1;
1107 csig1 = comg1 = calp1 * cbet1;
1109 cchi1 = _f1 * dn1 * comg1;
1118 salp2 = cbet2 != cbet1 ? salp0 / cbet2 : salp1;
1123 calp2 = cbet2 != cbet1 || fabs(sbet2) != -sbet1 ?
1126 (cbet2 - cbet1) * (cbet1 + cbet2) :
1127 (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2 :
1131 ssig2 = sbet2; somg2 = salp0 * sbet2;
1132 csig2 = comg2 = calp2 * cbet2;
1134 cchi2 = _f1 * dn2 * comg2;
1140 sig12 = atan2(fmax(
real(0), csig1 * ssig2 - ssig1 * csig2),
1141 csig1 * csig2 + ssig1 * ssig2);
1144 somg12 = fmax(
real(0), comg1 * somg2 - somg1 * comg2);
1145 comg12 = comg1 * comg2 + somg1 * somg2;
1147 E.Reset(-k2, -_ep2, 1 + k2, 1 + _ep2);
1150 schi12 = fmax(
real(0), cchi1 * somg2 - somg1 * cchi2),
1151 cchi12 = cchi1 * cchi2 + somg1 * somg2;
1153 real eta = atan2(schi12 * clam120 - cchi12 * slam120,
1154 cchi12 * clam120 + schi12 * slam120);
1155 real deta12 = -_e2/_f1 * salp0 * E.H() / (
Math::pi() / 2) *
1156 (sig12 + (E.deltaH(ssig2, csig2, dn2) - E.deltaH(ssig1, csig1, dn1)));
1157 lam12 = eta + deta12;
1159 domg12 = deta12 + atan2(schi12 * comg12 - cchi12 * somg12,
1160 cchi12 * comg12 + schi12 * somg12);
1163 dlam12 = - 2 * _f1 * dn1 / sbet1;
1166 Lengths(E, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2,
1168 dummy, dlam12, dummy, dummy, dummy);
1169 dlam12 *= _f1 / (calp2 * cbet2);
1179 (x > 0 ? asinh(sqrt(x))/sqrt(x) :
1180 asin(sqrt(-x))/sqrt(-x));
1189 return x + (sqrt(1 + x) * asinhsqrt(x) - 1);
1193 return x == 0 ? 4/
real(3) :
1195 1 + (1 - asinhsqrt(x) / sqrt(1+x)) / (2*x);
1215 if (X == y)
return tdX;
1216 if (X * y <= 0)
return ( tX - t(y) ) / (X - y);
1218 sy = sqrt(fabs(y)), sy1 = sqrt(1 + y),
1219 z = (X - y) / (sX * sy1 + sy * sX1),
1221 d2 = 2 * (X * sy * sy1 + y * sXX1);
1223 ( 1 + (asinh(z)/z) / d1 - (asinhsX + asinh(sy)) / d2 ) :
1225 ( 1 - (asin (z)/z) / d1 - (asinhsX + asin (sy)) / d2 );
1227 GeodesicExact::I4Integrand::I4Integrand(
real ep2,
real k2)
1236 asinhsX = X > 0 ? asinh(sX) : asin(sX);
1238 Math::real GeodesicExact::I4Integrand::operator()(
real sig)
const {
1239 real ssig = sin(sig);
1240 return - DtX(_k2 *
Math::sq(ssig)) * ssig/2;
GeographicLib::Math::real real
Header for GeographicLib::GeodesicExact class.
Header for GeographicLib::GeodesicLineExact class.
void transform(std::function< real(real)> f, real F[]) const
static real integral(real sinx, real cosx, const real F[], int N)
Elliptic integrals and functions.
Math::real deltaE(real sn, real cn, real dn) const
Math::real deltaD(real sn, real cn, real dn) const
Exact geodesic calculations.
GeodesicLineExact InverseLine(real lat1, real lon1, real lat2, real lon2, unsigned caps=ALL) const
GeodesicLineExact GenDirectLine(real lat1, real lon1, real azi1, bool arcmode, real s12_a12, unsigned caps=ALL) const
GeodesicLineExact DirectLine(real lat1, real lon1, real azi1, real s12, unsigned caps=ALL) const
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
friend class GeodesicLineExact
GeodesicLineExact Line(real lat1, real lon1, real azi1, unsigned caps=ALL) const
static const GeodesicExact & WGS84()
GeodesicLineExact ArcDirectLine(real lat1, real lon1, real azi1, real a12, unsigned caps=ALL) const
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 T AngNormalize(T x)
static void sincosde(T x, T t, T &sinx, T &cosx)
static T AngDiff(T x, T y, T &e)
@ hd
degrees per half turn
@ qd
degrees per quarter turn
Namespace for GeographicLib.
void swap(GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &a, GeographicLib::NearestNeighbor< dist_t, pos_t, distfun_t > &b)