1 """Define the :class:`~geographiclib.geodesic.Geodesic` class 
    3 The ellipsoid parameters are defined by the constructor.  The direct and 
    4 inverse geodesic problems are solved by 
    6   * :meth:`~geographiclib.geodesic.Geodesic.Inverse` Solve the inverse 
    8   * :meth:`~geographiclib.geodesic.Geodesic.Direct` Solve the direct 
   10   * :meth:`~geographiclib.geodesic.Geodesic.ArcDirect` Solve the direct 
   11     geodesic problem in terms of spherical arc length 
   13 :class:`~geographiclib.geodesicline.GeodesicLine` objects can be created 
   16   * :meth:`~geographiclib.geodesic.Geodesic.Line` 
   17   * :meth:`~geographiclib.geodesic.Geodesic.DirectLine` 
   18   * :meth:`~geographiclib.geodesic.Geodesic.ArcDirectLine` 
   19   * :meth:`~geographiclib.geodesic.Geodesic.InverseLine` 
   21 :class:`~geographiclib.polygonarea.PolygonArea` objects can be created 
   24   * :meth:`~geographiclib.geodesic.Geodesic.Polygon` 
   26 The public attributes for this class are 
   28   * :attr:`~geographiclib.geodesic.Geodesic.a` 
   29     :attr:`~geographiclib.geodesic.Geodesic.f` 
   31 *outmask* and *caps* bit masks are 
   33   * :const:`~geographiclib.geodesic.Geodesic.EMPTY` 
   34   * :const:`~geographiclib.geodesic.Geodesic.LATITUDE` 
   35   * :const:`~geographiclib.geodesic.Geodesic.LONGITUDE` 
   36   * :const:`~geographiclib.geodesic.Geodesic.AZIMUTH` 
   37   * :const:`~geographiclib.geodesic.Geodesic.DISTANCE` 
   38   * :const:`~geographiclib.geodesic.Geodesic.STANDARD` 
   39   * :const:`~geographiclib.geodesic.Geodesic.DISTANCE_IN` 
   40   * :const:`~geographiclib.geodesic.Geodesic.REDUCEDLENGTH` 
   41   * :const:`~geographiclib.geodesic.Geodesic.GEODESICSCALE` 
   42   * :const:`~geographiclib.geodesic.Geodesic.AREA` 
   43   * :const:`~geographiclib.geodesic.Geodesic.ALL` 
   44   * :const:`~geographiclib.geodesic.Geodesic.LONG_UNROLL` 
   48     >>> from geographiclib.geodesic import Geodesic 
   49     >>> # The geodesic inverse problem 
   50     ... Geodesic.WGS84.Inverse(-41.32, 174.81, 40.96, -5.50) 
   52      'a12': 179.6197069334283, 
   53      's12': 19959679.26735382, 
   55      'azi2': 18.825195123248392, 
   56      'azi1': 161.06766998615882, 
   86   """Solve geodesic problems""" 
   88   GEOGRAPHICLIB_GEODESIC_ORDER = 6
 
   89   nA1_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   90   nC1_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   91   nC1p_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   92   nA2_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   93   nC2_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   94   nA3_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   96   nC3_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   97   nC3x_ = (nC3_ * (nC3_ - 1)) // 2
 
   98   nC4_ = GEOGRAPHICLIB_GEODESIC_ORDER
 
   99   nC4x_ = (nC4_ * (nC4_ + 1)) // 2
 
  101   maxit2_ = maxit1_ + Math.digits + 10
 
  103   tiny_ = math.sqrt(Math.minval)
 
  106   tol2_ = math.sqrt(tol0_)
 
  107   tolb_ = tol0_ * tol2_
 
  108   xthresh_ = 1000 * tol2_
 
  110   CAP_NONE = GeodesicCapability.CAP_NONE
 
  111   CAP_C1   = GeodesicCapability.CAP_C1
 
  112   CAP_C1p  = GeodesicCapability.CAP_C1p
 
  113   CAP_C2   = GeodesicCapability.CAP_C2
 
  114   CAP_C3   = GeodesicCapability.CAP_C3
 
  115   CAP_C4   = GeodesicCapability.CAP_C4
 
  116   CAP_ALL  = GeodesicCapability.CAP_ALL
 
  117   CAP_MASK = GeodesicCapability.CAP_MASK
 
  118   OUT_ALL  = GeodesicCapability.OUT_ALL
 
  119   OUT_MASK = GeodesicCapability.OUT_MASK
 
  122     """Private: Evaluate a trig series using Clenshaw summation.""" 
  130     ar = 2 * (cosx - sinx) * (cosx + sinx) 
 
  141       k -= 1; y1 = ar * y0 - y1 + c[k]
 
  142       k -= 1; y0 = ar * y1 - y0 + c[k]
 
  143     return ( 2 * sinx * cosx * y0 
if sinp 
 
  144              else cosx * (y0 - y1) )      
 
  148     """Private: solve astroid equation.""" 
  154     if not(q == 0 
and r <= 0):
 
  162       disc = S * (S + 2 * r3)
 
  169         T3 += -math.sqrt(disc) 
if T3 < 0 
else math.sqrt(disc) 
 
  173         u += T + (r2 / T 
if T != 0 
else 0)
 
  176         ang = math.atan2(math.sqrt(-disc), -(S + r3))
 
  179         u += 2 * r * math.cos(ang / 3)
 
  180       v = math.sqrt(Math.sq(u) + q) 
 
  182       uv = q / (v - u) 
if u < 0 
else u + v 
 
  183       w = (uv - q) / (2 * v)               
 
  186       k = uv / (math.sqrt(uv + Math.sq(w)) + w) 
 
  195     """Private: return A1-1.""" 
  200     t = Math.polyval(m, coeff, 0, Math.sq(eps)) / coeff[m + 1]
 
  201     return (t + eps) / (1 - eps)
 
  205     """Private: return C1.""" 
  217     for l 
in range(1, Geodesic.nC1_ + 1): 
 
  218       m = (Geodesic.nC1_ - l) // 2        
 
  219       c[l] = d * Math.polyval(m, coeff, o, eps2) / coeff[o + m + 1]
 
  225     """Private: return C1'""" 
  227       205, -432, 768, 1536,
 
  228       4005, -4736, 3840, 12288,
 
  237     for l 
in range(1, Geodesic.nC1p_ + 1): 
 
  238       m = (Geodesic.nC1p_ - l) // 2 
 
  239       c[l] = d * Math.polyval(m, coeff, o, eps2) / coeff[o + m + 1]
 
  245     """Private: return A2-1""" 
  247       -11, -28, -192, 0, 256,
 
  250     t = Math.polyval(m, coeff, 0, Math.sq(eps)) / coeff[m + 1]
 
  251     return (t - eps) / (1 + eps)
 
  255     """Private: return C2""" 
  267     for l 
in range(1, Geodesic.nC2_ + 1): 
 
  268       m = (Geodesic.nC2_ - l) // 2        
 
  269       c[l] = d * Math.polyval(m, coeff, o, eps2) / coeff[o + m + 1]
 
  275     """Construct a Geodesic object 
  277     :param a: the equatorial radius of the ellipsoid in meters 
  278     :param f: the flattening of the ellipsoid 
  280     An exception is thrown if *a* or the polar semi-axis *b* = *a* (1 - 
  281     *f*) is not a finite positive quantity. 
  286     """The equatorial radius in meters (readonly)""" 
  288     """The flattening (readonly)""" 
  292     self.
_n = self.
f / ( 2 - self.
f)
 
  295     self.
_c2 = (Math.sq(self.
a) + Math.sq(self.
_b) *
 
  296                 (1 
if self.
_e2 == 0 
else 
  297                  (Math.atanh(math.sqrt(self.
_e2)) 
if self.
_e2 > 0 
else 
  298                   math.atan(math.sqrt(-self.
_e2))) /
 
  299                  math.sqrt(
abs(self.
_e2))))/2
 
  310                                                     min(1.0, 1-self.
f/2) / 2 )
 
  311     if not(Math.isfinite(self.
a) 
and self.
a > 0):
 
  312       raise ValueError(
"Equatorial radius is not positive")
 
  313     if not(Math.isfinite(self.
_b) 
and self.
_b > 0):
 
  314       raise ValueError(
"Polar semi-axis is not positive")
 
  323     """Private: return coefficients for A3""" 
  333     for j 
in range(Geodesic.nA3_ - 1, -1, -1): 
 
  334       m = 
min(Geodesic.nA3_ - j - 1, j) 
 
  335       self.
_A3x[k] = Math.polyval(m, coeff, o, self.
_n) / coeff[o + m + 1]
 
  340     """Private: return coefficients for C3""" 
  359     for l 
in range(1, Geodesic.nC3_): 
 
  360       for j 
in range(Geodesic.nC3_ - 1, l - 1, -1): 
 
  361         m = 
min(Geodesic.nC3_ - j - 1, j) 
 
  362         self.
_C3x[k] = Math.polyval(m, coeff, o, self.
_n) / coeff[o + m + 1]
 
  367     """Private: return coefficients for C4""" 
  371       -224, -4784, 1573, 45045,
 
  372       -10656, 14144, -4576, -858, 45045,
 
  373       64, 624, -4576, 6864, -3003, 15015,
 
  374       100, 208, 572, 3432, -12012, 30030, 45045,
 
  377       5792, 1040, -1287, 135135,
 
  378       5952, -11648, 9152, -2574, 135135,
 
  379       -64, -624, 4576, -6864, 3003, 135135,
 
  382       -8448, 4992, -1144, 225225,
 
  383       -1440, 4160, -4576, 1716, 225225,
 
  386       3584, -3328, 1144, 315315,
 
  392     for l 
in range(Geodesic.nC4_): 
 
  393       for j 
in range(Geodesic.nC4_ - 1, l - 1, -1): 
 
  394         m = Geodesic.nC4_ - j - 1 
 
  395         self.
_C4x[k] = Math.polyval(m, coeff, o, self.
_n) / coeff[o + m + 1]
 
  400     """Private: return A3""" 
  402     return Math.polyval(Geodesic.nA3_ - 1, self.
_A3x, 0, eps)
 
  405     """Private: return C3""" 
  410     for l 
in range(1, Geodesic.nC3_): 
 
  411       m = Geodesic.nC3_ - l - 1       
 
  413       c[l] = mult * Math.polyval(m, self.
_C3x, o, eps)
 
  417     """Private: return C4""" 
  422     for l 
in range(Geodesic.nC4_): 
 
  423       m = Geodesic.nC4_ - l - 1    
 
  424       c[l] = mult * Math.polyval(m, self.
_C4x, o, eps)
 
  430                ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2, outmask,
 
  433     """Private: return a bunch of lengths""" 
  437     outmask &= Geodesic.OUT_MASK
 
  442     s12b = m12b = m0 = M12 = M21 = Math.nan
 
  443     if outmask & (Geodesic.DISTANCE | Geodesic.REDUCEDLENGTH |
 
  444                   Geodesic.GEODESICSCALE):
 
  445       A1 = Geodesic._A1m1f(eps)
 
  446       Geodesic._C1f(eps, C1a)
 
  447       if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
 
  448         A2 = Geodesic._A2m1f(eps)
 
  449         Geodesic._C2f(eps, C2a)
 
  453     if outmask & Geodesic.DISTANCE:
 
  454       B1 = (Geodesic._SinCosSeries(
True, ssig2, csig2, C1a) -
 
  455             Geodesic._SinCosSeries(
True, ssig1, csig1, C1a))
 
  457       s12b = A1 * (sig12 + B1)
 
  458       if outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
 
  459         B2 = (Geodesic._SinCosSeries(
True, ssig2, csig2, C2a) -
 
  460               Geodesic._SinCosSeries(
True, ssig1, csig1, C2a))
 
  461         J12 = m0x * sig12 + (A1 * B1 - A2 * B2)
 
  462     elif outmask & (Geodesic.REDUCEDLENGTH | Geodesic.GEODESICSCALE):
 
  464       for l 
in range(1, Geodesic.nC2_):
 
  465         C2a[l] = A1 * C1a[l] - A2 * C2a[l]
 
  466       J12 = m0x * sig12 + (Geodesic._SinCosSeries(
True, ssig2, csig2, C2a) -
 
  467                            Geodesic._SinCosSeries(
True, ssig1, csig1, C2a))
 
  468     if outmask & Geodesic.REDUCEDLENGTH:
 
  473       m12b = (dn2 * (csig1 * ssig2) - dn1 * (ssig1 * csig2) -
 
  475     if outmask & Geodesic.GEODESICSCALE:
 
  476       csig12 = csig1 * csig2 + ssig1 * ssig2
 
  477       t = self.
_ep2 * (cbet1 - cbet2) * (cbet1 + cbet2) / (dn1 + dn2)
 
  478       M12 = csig12 + (t * ssig2 - csig2 * J12) * ssig1 / dn1
 
  479       M21 = csig12 - (t * ssig1 - csig1 * J12) * ssig2 / dn2
 
  480     return s12b, m12b, m0, M12, M21
 
  484                     lam12, slam12, clam12,
 
  487     """Private: Find a starting value for Newton's method.""" 
  491     sig12 = -1; salp2 = calp2 = dnm = Math.nan 
 
  493     sbet12 = sbet2 * cbet1 - cbet2 * sbet1
 
  494     cbet12 = cbet2 * cbet1 + sbet2 * sbet1
 
  500     sbet12a = sbet2 * cbet1
 
  501     sbet12a += cbet2 * sbet1
 
  503     shortline = cbet12 >= 0 
and sbet12 < 0.5 
and cbet2 * lam12 < 0.5
 
  505       sbetm2 = Math.sq(sbet1 + sbet2)
 
  508       sbetm2 /= sbetm2 + Math.sq(cbet1 + cbet2)
 
  509       dnm = math.sqrt(1 + self.
_ep2 * sbetm2)
 
  510       omg12 = lam12 / (self.
_f1 * dnm)
 
  511       somg12 = math.sin(omg12); comg12 = math.cos(omg12)
 
  513       somg12 = slam12; comg12 = clam12
 
  515     salp1 = cbet2 * somg12
 
  517       sbet12 + cbet2 * sbet1 * Math.sq(somg12) / (1 + comg12) 
if comg12 >= 0
 
  518       else sbet12a - cbet2 * sbet1 * Math.sq(somg12) / (1 - comg12))
 
  520     ssig12 = math.hypot(salp1, calp1)
 
  521     csig12 = sbet1 * sbet2 + cbet1 * cbet2 * comg12
 
  523     if shortline 
and ssig12 < self.
_etol2:
 
  525       salp2 = cbet1 * somg12
 
  526       calp2 = sbet12 - cbet1 * sbet2 * (Math.sq(somg12) / (1 + comg12)
 
  527                                         if comg12 >= 0 
else 1 - comg12)
 
  528       salp2, calp2 = Math.norm(salp2, calp2)
 
  530       sig12 = math.atan2(ssig12, csig12)
 
  531     elif (
abs(self.
_n) >= 0.1 
or  
  533           ssig12 >= 6 * 
abs(self.
_n) * math.pi * Math.sq(cbet1)):
 
  544       lam12x = math.atan2(-slam12, -clam12)
 
  547         k2 = Math.sq(sbet1) * self.
_ep2 
  548         eps = k2 / (2 * (1 + math.sqrt(1 + k2)) + k2)
 
  549         lamscale = self.
f * cbet1 * self.
_A3f(eps) * math.pi
 
  550         betscale = lamscale * cbet1
 
  551         x = lam12x / lamscale
 
  552         y = sbet12a / betscale
 
  555         cbet12a = cbet2 * cbet1 - sbet2 * sbet1
 
  556         bet12a = math.atan2(sbet12a, cbet12a)
 
  560         dummy, m12b, m0, dummy, dummy = self.
_Lengths(
 
  561           self.
_n, math.pi + bet12a, sbet1, -cbet1, dn1, sbet2, cbet2, dn2,
 
  562           cbet1, cbet2, Geodesic.REDUCEDLENGTH, C1a, C2a)
 
  563         x = -1 + m12b / (cbet1 * cbet2 * m0 * math.pi)
 
  564         betscale = (sbet12a / x 
if x < -0.01
 
  565                     else -self.
f * Math.sq(cbet1) * math.pi)
 
  566         lamscale = betscale / cbet1
 
  567         y = lam12x / lamscale
 
  569       if y > -Geodesic.tol1_ 
and x > -1 - Geodesic.xthresh_:
 
  572           salp1 = 
min(1.0, -x); calp1 = - math.sqrt(1 - Math.sq(salp1))
 
  574           calp1 = 
max((0.0 
if x > -Geodesic.tol1_ 
else -1.0), x)
 
  575           salp1 = math.sqrt(1 - Math.sq(calp1))
 
  611         k = Geodesic._Astroid(x, y)
 
  612         omg12a = lamscale * ( -x * k/(1 + k) 
if self.
f >= 0
 
  613                               else -y * (1 + k)/k )
 
  614         somg12 = math.sin(omg12a); comg12 = -math.cos(omg12a)
 
  616         salp1 = cbet2 * somg12
 
  617         calp1 = sbet12a - cbet2 * sbet1 * Math.sq(somg12) / (1 - comg12)
 
  620       salp1, calp1 = Math.norm(salp1, calp1)
 
  623     return sig12, salp1, calp1, salp2, calp2, dnm
 
  627   def _Lambda12(self, sbet1, cbet1, dn1, sbet2, cbet2, dn2, salp1, calp1,
 
  628                 slam120, clam120, diffp,
 
  631     """Private: Solve hybrid problem""" 
  632     if sbet1 == 0 
and calp1 == 0:
 
  635       calp1 = -Geodesic.tiny_
 
  638     salp0 = salp1 * cbet1
 
  639     calp0 = math.hypot(calp1, salp1 * sbet1) 
 
  644     ssig1 = sbet1; somg1 = salp0 * sbet1
 
  645     csig1 = comg1 = calp1 * cbet1
 
  646     ssig1, csig1 = Math.norm(ssig1, csig1)
 
  653     salp2 = salp0 / cbet2 
if cbet2 != cbet1 
else salp1
 
  658     calp2 = (math.sqrt(Math.sq(calp1 * cbet1) +
 
  659                        ((cbet2 - cbet1) * (cbet1 + cbet2) 
if cbet1 < -sbet1
 
  660                         else (sbet1 - sbet2) * (sbet1 + sbet2))) / cbet2
 
  661              if cbet2 != cbet1 
or abs(sbet2) != -sbet1 
else abs(calp1))
 
  664     ssig2 = sbet2; somg2 = salp0 * sbet2
 
  665     csig2 = comg2 = calp2 * cbet2
 
  666     ssig2, csig2 = Math.norm(ssig2, csig2)
 
  670     sig12 = math.atan2(
max(0.0, csig1 * ssig2 - ssig1 * csig2),
 
  671                                 csig1 * csig2 + ssig1 * ssig2)
 
  674     somg12 = 
max(0.0, comg1 * somg2 - somg1 * comg2)
 
  675     comg12 =          comg1 * comg2 + somg1 * somg2
 
  677     eta = math.atan2(somg12 * clam120 - comg12 * slam120,
 
  678                      comg12 * clam120 + somg12 * slam120)
 
  681     k2 = Math.sq(calp0) * self.
_ep2 
  682     eps = k2 / (2 * (1 + math.sqrt(1 + k2)) + k2)
 
  684     B312 = (Geodesic._SinCosSeries(
True, ssig2, csig2, C3a) -
 
  685             Geodesic._SinCosSeries(
True, ssig1, csig1, C3a))
 
  686     domg12 =  -self.
f * self.
_A3f(eps) * salp0 * (sig12 + B312)
 
  691         dlam12 = - 2 * self.
_f1 * dn1 / sbet1
 
  693         dummy, dlam12, dummy, dummy, dummy = self.
_Lengths(
 
  694           eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
 
  695           Geodesic.REDUCEDLENGTH, C1a, C2a)
 
  696         dlam12 *= self.
_f1 / (calp2 * cbet2)
 
  700     return (lam12, salp2, calp2, sig12, ssig1, csig1, ssig2, csig2, eps,
 
  705     """Private: General version of the inverse problem""" 
  706     a12 = s12 = m12 = M12 = M21 = S12 = Math.nan 
 
  708     outmask &= Geodesic.OUT_MASK
 
  712     lon12, lon12s = Math.AngDiff(lon1, lon2)
 
  714     lonsign = 1 
if lon12 >= 0 
else -1
 
  716     lon12 = lonsign * Math.AngRound(lon12)
 
  717     lon12s = Math.AngRound((180 - lon12) - lonsign * lon12s)
 
  718     lam12 = math.radians(lon12)
 
  720       slam12, clam12 = Math.sincosd(lon12s); clam12 = -clam12
 
  722       slam12, clam12 = Math.sincosd(lon12)
 
  725     lat1 = Math.AngRound(Math.LatFix(lat1))
 
  726     lat2 = Math.AngRound(Math.LatFix(lat2))
 
  729     swapp = -1 
if abs(lat1) < 
abs(lat2) 
else 1
 
  732       lat2, lat1 = lat1, lat2
 
  734     latsign = 1 
if lat1 < 0 
else -1
 
  751     sbet1, cbet1 = Math.sincosd(lat1); sbet1 *= self.
_f1 
  753     sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 = 
max(Geodesic.tiny_, cbet1)
 
  755     sbet2, cbet2 = Math.sincosd(lat2); sbet2 *= self.
_f1 
  757     sbet2, cbet2 = Math.norm(sbet2, cbet2); cbet2 = 
max(Geodesic.tiny_, cbet2)
 
  769         sbet2 = sbet1 
if sbet2 < 0 
else -sbet1
 
  771       if abs(sbet2) == -sbet1:
 
  774     dn1 = math.sqrt(1 + self.
_ep2 * Math.sq(sbet1))
 
  775     dn2 = math.sqrt(1 + self.
_ep2 * Math.sq(sbet2))
 
  783     meridian = lat1 == -90 
or slam12 == 0
 
  790       calp1 = clam12; salp1 = slam12 
 
  791       calp2 = 1.0; salp2 = 0.0       
 
  794       ssig1 = sbet1; csig1 = calp1 * cbet1
 
  795       ssig2 = sbet2; csig2 = calp2 * cbet2
 
  798       sig12 = math.atan2(
max(0.0, csig1 * ssig2 - ssig1 * csig2),
 
  799                                   csig1 * csig2 + ssig1 * ssig2)
 
  801       s12x, m12x, dummy, M12, M21 = self.
_Lengths(
 
  802         self.
_n, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
 
  803         outmask | Geodesic.DISTANCE | Geodesic.REDUCEDLENGTH, C1a, C2a)
 
  812       if sig12 < 1 
or m12x >= 0:
 
  813         if sig12 < 3 * Geodesic.tiny_:
 
  814           sig12 = m12x = s12x = 0.0
 
  817         a12 = math.degrees(sig12)
 
  824     somg12 = 2.0; comg12 = 0.0; omg12 = 0.0
 
  828         (self.
f <= 0 
or lon12s >= self.
f * 180)):
 
  831       calp1 = calp2 = 0.0; salp1 = salp2 = 1.0
 
  832       s12x = self.
a * lam12
 
  833       sig12 = omg12 = lam12 / self.
_f1 
  834       m12x = self.
_b * math.sin(sig12)
 
  835       if outmask & Geodesic.GEODESICSCALE:
 
  836         M12 = M21 = math.cos(sig12)
 
  837       a12 = lon12 / self.
_f1 
  846         sbet1, cbet1, dn1, sbet2, cbet2, dn2, lam12, slam12, clam12, C1a, C2a)
 
  850         s12x = sig12 * self.
_b * dnm
 
  851         m12x = (Math.sq(dnm) * self.
_b * math.sin(sig12 / dnm))
 
  852         if outmask & Geodesic.GEODESICSCALE:
 
  853           M12 = M21 = math.cos(sig12 / dnm)
 
  854         a12 = math.degrees(sig12)
 
  855         omg12 = lam12 / (self.
_f1 * dnm)
 
  871         tripn = tripb = 
False 
  873         salp1a = Geodesic.tiny_; calp1a = 1.0
 
  874         salp1b = Geodesic.tiny_; calp1b = -1.0
 
  876         while numit < Geodesic.maxit2_:
 
  879           (v, salp2, calp2, sig12, ssig1, csig1, ssig2, csig2,
 
  881              sbet1, cbet1, dn1, sbet2, cbet2, dn2,
 
  882              salp1, calp1, slam12, clam12, numit < Geodesic.maxit1_,
 
  886           if tripb 
or not (
abs(v) >= (8 
if tripn 
else 1) * Geodesic.tol0_):
 
  889           if v > 0 
and (numit > Geodesic.maxit1_ 
or 
  890                         calp1/salp1 > calp1b/salp1b):
 
  891             salp1b = salp1; calp1b = calp1
 
  892           elif v < 0 
and (numit > Geodesic.maxit1_ 
or 
  893                           calp1/salp1 < calp1a/salp1a):
 
  894             salp1a = salp1; calp1a = calp1
 
  897           if numit < Geodesic.maxit1_ 
and dv > 0:
 
  899             sdalp1 = math.sin(dalp1); cdalp1 = math.cos(dalp1)
 
  900             nsalp1 = salp1 * cdalp1 + calp1 * sdalp1
 
  901             if nsalp1 > 0 
and abs(dalp1) < math.pi:
 
  902               calp1 = calp1 * cdalp1 - salp1 * sdalp1
 
  904               salp1, calp1 = Math.norm(salp1, calp1)
 
  908               tripn = 
abs(v) <= 16 * Geodesic.tol0_
 
  918           salp1 = (salp1a + salp1b)/2
 
  919           calp1 = (calp1a + calp1b)/2
 
  920           salp1, calp1 = Math.norm(salp1, calp1)
 
  922           tripb = (
abs(salp1a - salp1) + (calp1a - calp1) < Geodesic.tolb_ 
or 
  923                    abs(salp1 - salp1b) + (calp1 - calp1b) < Geodesic.tolb_)
 
  925         lengthmask = (outmask |
 
  927                        if (outmask & (Geodesic.REDUCEDLENGTH |
 
  928                                       Geodesic.GEODESICSCALE))
 
  929                        else Geodesic.EMPTY))
 
  930         s12x, m12x, dummy, M12, M21 = self.
_Lengths(
 
  931           eps, sig12, ssig1, csig1, dn1, ssig2, csig2, dn2, cbet1, cbet2,
 
  932           lengthmask, C1a, C2a)
 
  936         a12 = math.degrees(sig12)
 
  937         if outmask & Geodesic.AREA:
 
  939           sdomg12 = math.sin(domg12); cdomg12 = math.cos(domg12)
 
  940           somg12 = slam12 * cdomg12 - clam12 * sdomg12
 
  941           comg12 = clam12 * cdomg12 + slam12 * sdomg12
 
  945     if outmask & Geodesic.DISTANCE:
 
  948     if outmask & Geodesic.REDUCEDLENGTH:
 
  951     if outmask & Geodesic.AREA:
 
  953       salp0 = salp1 * cbet1
 
  954       calp0 = math.hypot(calp1, salp1 * sbet1) 
 
  956       if calp0 != 0 
and salp0 != 0:
 
  958         ssig1 = sbet1; csig1 = calp1 * cbet1
 
  959         ssig2 = sbet2; csig2 = calp2 * cbet2
 
  960         k2 = Math.sq(calp0) * self.
_ep2 
  961         eps = k2 / (2 * (1 + math.sqrt(1 + k2)) + k2)
 
  963         A4 = Math.sq(self.
a) * calp0 * salp0 * self.
_e2 
  964         ssig1, csig1 = Math.norm(ssig1, csig1)
 
  965         ssig2, csig2 = Math.norm(ssig2, csig2)
 
  968         B41 = Geodesic._SinCosSeries(
False, ssig1, csig1, C4a)
 
  969         B42 = Geodesic._SinCosSeries(
False, ssig2, csig2, C4a)
 
  970         S12 = A4 * (B42 - B41)
 
  975       if not meridian 
and somg12 > 1:
 
  976         somg12 = math.sin(omg12); comg12 = math.cos(omg12)
 
  981           sbet2 - sbet1 < 1.75): 
 
  985         domg12 = 1 + comg12; dbet1 = 1 + cbet1; dbet2 = 1 + cbet2
 
  986         alp12 = 2 * math.atan2( somg12 * ( sbet1 * dbet2 + sbet2 * dbet1 ),
 
  987                                 domg12 * ( sbet1 * sbet2 + dbet1 * dbet2 ) )
 
  990         salp12 = salp2 * calp1 - calp2 * salp1
 
  991         calp12 = calp2 * calp1 + salp2 * salp1
 
  996         if salp12 == 0 
and calp12 < 0:
 
  997           salp12 = Geodesic.tiny_ * calp1
 
  999         alp12 = math.atan2(salp12, calp12)
 
 1000       S12 += self.
_c2 * alp12
 
 1001       S12 *= swapp * lonsign * latsign
 
 1007       salp2, salp1 = salp1, salp2
 
 1008       calp2, calp1 = calp1, calp2
 
 1009       if outmask & Geodesic.GEODESICSCALE:
 
 1012     salp1 *= swapp * lonsign; calp1 *= swapp * latsign
 
 1013     salp2 *= swapp * lonsign; calp2 *= swapp * latsign
 
 1015     return a12, s12, salp1, calp1, salp2, calp2, m12, M12, M21, S12
 
 1018               outmask = GeodesicCapability.STANDARD):
 
 1019     """Solve the inverse geodesic problem 
 1021     :param lat1: latitude of the first point in degrees 
 1022     :param lon1: longitude of the first point in degrees 
 1023     :param lat2: latitude of the second point in degrees 
 1024     :param lon2: longitude of the second point in degrees 
 1025     :param outmask: the :ref:`output mask <outmask>` 
 1026     :return: a :ref:`dict` 
 1028     Compute geodesic between (*lat1*, *lon1*) and (*lat2*, *lon2*). 
 1029     The default value of *outmask* is STANDARD, i.e., the *lat1*, 
 1030     *lon1*, *azi1*, *lat2*, *lon2*, *azi2*, *s12*, *a12* entries are 
 1035     a12, s12, salp1,calp1, salp2,calp2, m12, M12, M21, S12 = self.
_GenInverse(
 
 1036       lat1, lon1, lat2, lon2, outmask)
 
 1037     outmask &= Geodesic.OUT_MASK
 
 1038     if outmask & Geodesic.LONG_UNROLL:
 
 1039       lon12, e = Math.AngDiff(lon1, lon2)
 
 1040       lon2 = (lon1 + lon12) + e
 
 1042       lon2 = Math.AngNormalize(lon2)
 
 1043     result = {
'lat1': Math.LatFix(lat1),
 
 1044               'lon1': lon1 
if outmask & Geodesic.LONG_UNROLL 
else 
 1045               Math.AngNormalize(lon1),
 
 1046               'lat2': Math.LatFix(lat2),
 
 1049     if outmask & Geodesic.DISTANCE: result[
's12'] = s12
 
 1050     if outmask & Geodesic.AZIMUTH:
 
 1051       result[
'azi1'] = Math.atan2d(salp1, calp1)
 
 1052       result[
'azi2'] = Math.atan2d(salp2, calp2)
 
 1053     if outmask & Geodesic.REDUCEDLENGTH: result[
'm12'] = m12
 
 1054     if outmask & Geodesic.GEODESICSCALE:
 
 1055       result[
'M12'] = M12; result[
'M21'] = M21
 
 1056     if outmask & Geodesic.AREA: result[
'S12'] = S12
 
 1060   def _GenDirect(self, lat1, lon1, azi1, arcmode, s12_a12, outmask):
 
 1061     """Private: General version of direct problem""" 
 1064     if not arcmode: outmask |= Geodesic.DISTANCE_IN
 
 1065     line = GeodesicLine(self, lat1, lon1, azi1, outmask)
 
 1066     return line._GenPosition(arcmode, s12_a12, outmask)
 
 1069              outmask = GeodesicCapability.STANDARD):
 
 1070     """Solve the direct geodesic problem 
 1072     :param lat1: latitude of the first point in degrees 
 1073     :param lon1: longitude of the first point in degrees 
 1074     :param azi1: azimuth at the first point in degrees 
 1075     :param s12: the distance from the first point to the second in 
 1077     :param outmask: the :ref:`output mask <outmask>` 
 1078     :return: a :ref:`dict` 
 1080     Compute geodesic starting at (*lat1*, *lon1*) with azimuth *azi1* 
 1081     and length *s12*.  The default value of *outmask* is STANDARD, i.e., 
 1082     the *lat1*, *lon1*, *azi1*, *lat2*, *lon2*, *azi2*, *s12*, *a12* 
 1083     entries are returned. 
 1087     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.
_GenDirect(
 
 1088       lat1, lon1, azi1, 
False, s12, outmask)
 
 1089     outmask &= Geodesic.OUT_MASK
 
 1090     result = {
'lat1': Math.LatFix(lat1),
 
 1091               'lon1': lon1 
if outmask & Geodesic.LONG_UNROLL 
else 
 1092               Math.AngNormalize(lon1),
 
 1093               'azi1': Math.AngNormalize(azi1),
 
 1096     if outmask & Geodesic.LATITUDE: result[
'lat2'] = lat2
 
 1097     if outmask & Geodesic.LONGITUDE: result[
'lon2'] = lon2
 
 1098     if outmask & Geodesic.AZIMUTH: result[
'azi2'] = azi2
 
 1099     if outmask & Geodesic.REDUCEDLENGTH: result[
'm12'] = m12
 
 1100     if outmask & Geodesic.GEODESICSCALE:
 
 1101       result[
'M12'] = M12; result[
'M21'] = M21
 
 1102     if outmask & Geodesic.AREA: result[
'S12'] = S12
 
 1106                 outmask = GeodesicCapability.STANDARD):
 
 1107     """Solve the direct geodesic problem in terms of spherical arc length 
 1109     :param lat1: latitude of the first point in degrees 
 1110     :param lon1: longitude of the first point in degrees 
 1111     :param azi1: azimuth at the first point in degrees 
 1112     :param a12: spherical arc length from the first point to the second 
 1114     :param outmask: the :ref:`output mask <outmask>` 
 1115     :return: a :ref:`dict` 
 1117     Compute geodesic starting at (*lat1*, *lon1*) with azimuth *azi1* 
 1118     and arc length *a12*.  The default value of *outmask* is STANDARD, 
 1119     i.e., the *lat1*, *lon1*, *azi1*, *lat2*, *lon2*, *azi2*, *s12*, 
 1120     *a12* entries are returned. 
 1124     a12, lat2, lon2, azi2, s12, m12, M12, M21, S12 = self.
_GenDirect(
 
 1125       lat1, lon1, azi1, 
True, a12, outmask)
 
 1126     outmask &= Geodesic.OUT_MASK
 
 1127     result = {
'lat1': Math.LatFix(lat1),
 
 1128               'lon1': lon1 
if outmask & Geodesic.LONG_UNROLL 
else 
 1129               Math.AngNormalize(lon1),
 
 1130               'azi1': Math.AngNormalize(azi1),
 
 1132     if outmask & Geodesic.DISTANCE: result[
's12'] = s12
 
 1133     if outmask & Geodesic.LATITUDE: result[
'lat2'] = lat2
 
 1134     if outmask & Geodesic.LONGITUDE: result[
'lon2'] = lon2
 
 1135     if outmask & Geodesic.AZIMUTH: result[
'azi2'] = azi2
 
 1136     if outmask & Geodesic.REDUCEDLENGTH: result[
'm12'] = m12
 
 1137     if outmask & Geodesic.GEODESICSCALE:
 
 1138       result[
'M12'] = M12; result[
'M21'] = M21
 
 1139     if outmask & Geodesic.AREA: result[
'S12'] = S12
 
 1143            caps = GeodesicCapability.STANDARD |
 
 1144            GeodesicCapability.DISTANCE_IN):
 
 1145     """Return a GeodesicLine object 
 1147     :param lat1: latitude of the first point in degrees 
 1148     :param lon1: longitude of the first point in degrees 
 1149     :param azi1: azimuth at the first point in degrees 
 1150     :param caps: the :ref:`capabilities <outmask>` 
 1151     :return: a :class:`~geographiclib.geodesicline.GeodesicLine` 
 1153     This allows points along a geodesic starting at (*lat1*, *lon1*), 
 1154     with azimuth *azi1* to be found.  The default value of *caps* is 
 1155     STANDARD | DISTANCE_IN, allowing direct geodesic problem to be 
 1161     return GeodesicLine(self, lat1, lon1, azi1, caps)
 
 1164                      caps = GeodesicCapability.STANDARD |
 
 1165                      GeodesicCapability.DISTANCE_IN):
 
 1166     """Private: general form of DirectLine""" 
 1169     if not arcmode: caps |= Geodesic.DISTANCE_IN
 
 1170     line = GeodesicLine(self, lat1, lon1, azi1, caps)
 
 1172       line.SetArc(s12_a12)
 
 1174       line.SetDistance(s12_a12)
 
 1178                  caps = GeodesicCapability.STANDARD |
 
 1179                  GeodesicCapability.DISTANCE_IN):
 
 1180     """Define a GeodesicLine object in terms of the direct geodesic 
 1181     problem specified in terms of spherical arc length 
 1183     :param lat1: latitude of the first point in degrees 
 1184     :param lon1: longitude of the first point in degrees 
 1185     :param azi1: azimuth at the first point in degrees 
 1186     :param s12: the distance from the first point to the second in 
 1188     :param caps: the :ref:`capabilities <outmask>` 
 1189     :return: a :class:`~geographiclib.geodesicline.GeodesicLine` 
 1191     This function sets point 3 of the GeodesicLine to correspond to 
 1192     point 2 of the direct geodesic problem.  The default value of *caps* 
 1193     is STANDARD | DISTANCE_IN, allowing direct geodesic problem to be 
 1201                  caps = GeodesicCapability.STANDARD |
 
 1202                  GeodesicCapability.DISTANCE_IN):
 
 1203     """Define a GeodesicLine object in terms of the direct geodesic 
 1204     problem specified in terms of spherical arc length 
 1206     :param lat1: latitude of the first point in degrees 
 1207     :param lon1: longitude of the first point in degrees 
 1208     :param azi1: azimuth at the first point in degrees 
 1209     :param a12: spherical arc length from the first point to the second 
 1211     :param caps: the :ref:`capabilities <outmask>` 
 1212     :return: a :class:`~geographiclib.geodesicline.GeodesicLine` 
 1214     This function sets point 3 of the GeodesicLine to correspond to 
 1215     point 2 of the direct geodesic problem.  The default value of *caps* 
 1216     is STANDARD | DISTANCE_IN, allowing direct geodesic problem to be 
 1224                   caps = GeodesicCapability.STANDARD |
 
 1225                   GeodesicCapability.DISTANCE_IN):
 
 1226     """Define a GeodesicLine object in terms of the invese geodesic problem 
 1228     :param lat1: latitude of the first point in degrees 
 1229     :param lon1: longitude of the first point in degrees 
 1230     :param lat2: latitude of the second point in degrees 
 1231     :param lon2: longitude of the second point in degrees 
 1232     :param caps: the :ref:`capabilities <outmask>` 
 1233     :return: a :class:`~geographiclib.geodesicline.GeodesicLine` 
 1235     This function sets point 3 of the GeodesicLine to correspond to 
 1236     point 2 of the inverse geodesic problem.  The default value of *caps* 
 1237     is STANDARD | DISTANCE_IN, allowing direct geodesic problem to be 
 1243     a12, _, salp1, calp1, _, _, _, _, _, _ = self.
_GenInverse(
 
 1244       lat1, lon1, lat2, lon2, 0)
 
 1245     azi1 = Math.atan2d(salp1, calp1)
 
 1246     if caps & (Geodesic.OUT_MASK & Geodesic.DISTANCE_IN):
 
 1247       caps |= Geodesic.DISTANCE
 
 1248     line = GeodesicLine(self, lat1, lon1, azi1, caps, salp1, calp1)
 
 1253     """Return a PolygonArea object 
 1255     :param polyline: if True then the object describes a polyline 
 1256       instead of a polygon 
 1257     :return: a :class:`~geographiclib.polygonarea.PolygonArea` 
 1262     return PolygonArea(self, polyline)
 
 1264   EMPTY         = GeodesicCapability.EMPTY
 
 1265   """No capabilities, no output.""" 
 1266   LATITUDE      = GeodesicCapability.LATITUDE
 
 1267   """Calculate latitude *lat2*.""" 
 1268   LONGITUDE     = GeodesicCapability.LONGITUDE
 
 1269   """Calculate longitude *lon2*.""" 
 1270   AZIMUTH       = GeodesicCapability.AZIMUTH
 
 1271   """Calculate azimuths *azi1* and *azi2*.""" 
 1272   DISTANCE      = GeodesicCapability.DISTANCE
 
 1273   """Calculate distance *s12*.""" 
 1274   STANDARD      = GeodesicCapability.STANDARD
 
 1275   """All of the above.""" 
 1276   DISTANCE_IN   = GeodesicCapability.DISTANCE_IN
 
 1277   """Allow distance *s12* to be used as input in the direct geodesic 
 1279   REDUCEDLENGTH = GeodesicCapability.REDUCEDLENGTH
 
 1280   """Calculate reduced length *m12*.""" 
 1281   GEODESICSCALE = GeodesicCapability.GEODESICSCALE
 
 1282   """Calculate geodesic scales *M12* and *M21*.""" 
 1283   AREA          = GeodesicCapability.AREA
 
 1284   """Calculate area *S12*.""" 
 1285   ALL           = GeodesicCapability.ALL
 
 1286   """All of the above.""" 
 1287   LONG_UNROLL   = GeodesicCapability.LONG_UNROLL
 
 1288   """Unroll longitudes, rather than reducing them to the range 
 1293 Geodesic.WGS84 = 
Geodesic(Constants.WGS84_a, Constants.WGS84_f)
 
 1294 """Instantiation for the WGS84 ellipsoid"""