Пример #1
0
    def __init__(self, geod, lat1, lon1, azi1, caps=GeodesicCapability.ALL):
        from geographiclib.geodesic import Geodesic
        self._a = geod._a
        self._f = geod._f
        self._b = geod._b
        self._c2 = geod._c2
        self._f1 = geod._f1
        self._caps = caps | Geodesic.LATITUDE | Geodesic.AZIMUTH

        # Guard against underflow in salp0
        azi1 = Geodesic.AngRound(Math.AngNormalize(azi1))
        lon1 = Math.AngNormalize(lon1)
        self._lat1 = lat1
        self._lon1 = lon1
        self._azi1 = azi1
        # alp1 is in [0, pi]
        alp1 = azi1 * Math.degree
        # Enforce sin(pi) == 0 and cos(pi/2) == 0.  Better to face the ensuing
        # problems directly than to skirt them.
        self._salp1 = 0 if azi1 == -180 else math.sin(alp1)
        self._calp1 = 0 if abs(azi1) == 90 else math.cos(alp1)
        # real cbet1, sbet1, phi
        phi = lat1 * Math.degree
        # Ensure cbet1 = +epsilon at poles
        sbet1 = self._f1 * math.sin(phi)
        cbet1 = Geodesic.tiny_ if abs(lat1) == 90 else math.cos(phi)
        sbet1, cbet1 = Geodesic.SinCosNorm(sbet1, cbet1)
        self._dn1 = math.sqrt(1 + geod._ep2 * Math.sq(sbet1))

        # Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
        self._salp0 = self._salp1 * cbet1  # alp0 in [0, pi/2 - |bet1|]
        # Alt: calp0 = hypot(sbet1, calp1 * cbet1).  The following
        # is slightly better (consider the case salp1 = 0).
        self._calp0 = math.hypot(self._calp1, self._salp1 * sbet1)
        # Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
        # sig = 0 is nearest northward crossing of equator.
        # With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
        # With bet1 =  pi/2, alp1 = -pi, sig1 =  pi/2
        # With bet1 = -pi/2, alp1 =  0 , sig1 = -pi/2
        # Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
        # With alp0 in (0, pi/2], quadrants for sig and omg coincide.
        # No atan2(0,0) ambiguity at poles since cbet1 = +epsilon.
        # With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi.
        self._ssig1 = sbet1
        self._somg1 = self._salp0 * sbet1
        self._csig1 = self._comg1 = (cbet1 * self._calp1
                                     if sbet1 != 0 or self._calp1 != 0 else 1)
        # sig1 in (-pi, pi]
        self._ssig1, self._csig1 = Geodesic.SinCosNorm(self._ssig1,
                                                       self._csig1)
        # No need to normalize
        # self._somg1, self._comg1 = Geodesic.SinCosNorm(self._somg1, self._comg1)

        self._k2 = Math.sq(self._calp0) * geod._ep2
        eps = self._k2 / (2 * (1 + math.sqrt(1 + self._k2)) + self._k2)

        if self._caps & Geodesic.CAP_C1:
            self._A1m1 = Geodesic.A1m1f(eps)
            self._C1a = range(Geodesic.nC1_ + 1)
            Geodesic.C1f(eps, self._C1a)
            self._B11 = Geodesic.SinCosSeries(True, self._ssig1, self._csig1,
                                              self._C1a, Geodesic.nC1_)
            s = math.sin(self._B11)
            c = math.cos(self._B11)
            # tau1 = sig1 + B11
            self._stau1 = self._ssig1 * c + self._csig1 * s
            self._ctau1 = self._csig1 * c - self._ssig1 * s
            # Not necessary because C1pa reverts C1a
            #    _B11 = -SinCosSeries(true, _stau1, _ctau1, _C1pa, nC1p_)

        if self._caps & Geodesic.CAP_C1p:
            self._C1pa = range(Geodesic.nC1p_ + 1)
            Geodesic.C1pf(eps, self._C1pa)

        if self._caps & Geodesic.CAP_C2:
            self._A2m1 = Geodesic.A2m1f(eps)
            self._C2a = range(Geodesic.nC2_ + 1)
            Geodesic.C2f(eps, self._C2a)
            self._B21 = Geodesic.SinCosSeries(True, self._ssig1, self._csig1,
                                              self._C2a, Geodesic.nC2_)

        if self._caps & Geodesic.CAP_C3:
            self._C3a = range(Geodesic.nC3_)
            geod.C3f(eps, self._C3a)
            self._A3c = -self._f * self._salp0 * geod.A3f(eps)
            self._B31 = Geodesic.SinCosSeries(True, self._ssig1, self._csig1,
                                              self._C3a, Geodesic.nC3_ - 1)

        if self._caps & Geodesic.CAP_C4:
            self._C4a = range(Geodesic.nC4_)
            geod.C4f(eps, self._C4a)
            # Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0)
            self._A4 = Math.sq(self._a) * self._calp0 * self._salp0 * geod._e2
            self._B41 = Geodesic.SinCosSeries(False, self._ssig1, self._csig1,
                                              self._C4a, Geodesic.nC4_)
Пример #2
0
  def __init__(self, geod, lat1, lon1, azi1, caps = GeodesicCapability.ALL):
    """Construct a GeodesicLine object describing a geodesic line
    starting at (lat1, lon1) with azimuth azi1.  geod is a Geodesic
    object (which embodies the ellipsoid parameters).  caps is caps is
    an or'ed combination of bit the following values indicating the
    capabilities of the returned object

      Geodesic.LATITUDE
      Geodesic.LONGITUDE
      Geodesic.AZIMUTH
      Geodesic.DISTANCE
      Geodesic.REDUCEDLENGTH
      Geodesic.GEODESICSCALE
      Geodesic.AREA
      Geodesic.DISTANCE_IN
      Geodesic.ALL (all of the above)

    The default value of caps is ALL.

    """

    from geographiclib.geodesic import Geodesic
    self._a = geod._a
    self._f = geod._f
    self._b = geod._b
    self._c2 = geod._c2
    self._f1 = geod._f1
    self._caps = (caps | Geodesic.LATITUDE | Geodesic.AZIMUTH |
                  Geodesic.LONG_UNROLL)

    # Guard against underflow in salp0
    self._lat1 = Math.LatFix(lat1)
    self._lon1 = lon1
    self._azi1 = Math.AngNormalize(azi1)
    self._salp1, self._calp1 = Math.sincosd(Math.AngRound(azi1))

    # real cbet1, sbet1
    sbet1, cbet1 = Math.sincosd(Math.AngRound(lat1)); sbet1 *= self._f1
    # Ensure cbet1 = +epsilon at poles
    sbet1, cbet1 = Math.norm(sbet1, cbet1); cbet1 = max(Geodesic.tiny_, cbet1)
    self._dn1 = math.sqrt(1 + geod._ep2 * Math.sq(sbet1))

    # Evaluate alp0 from sin(alp1) * cos(bet1) = sin(alp0),
    self._salp0 = self._salp1 * cbet1 # alp0 in [0, pi/2 - |bet1|]
    # Alt: calp0 = hypot(sbet1, calp1 * cbet1).  The following
    # is slightly better (consider the case salp1 = 0).
    self._calp0 = math.hypot(self._calp1, self._salp1 * sbet1)
    # Evaluate sig with tan(bet1) = tan(sig1) * cos(alp1).
    # sig = 0 is nearest northward crossing of equator.
    # With bet1 = 0, alp1 = pi/2, we have sig1 = 0 (equatorial line).
    # With bet1 =  pi/2, alp1 = -pi, sig1 =  pi/2
    # With bet1 = -pi/2, alp1 =  0 , sig1 = -pi/2
    # Evaluate omg1 with tan(omg1) = sin(alp0) * tan(sig1).
    # With alp0 in (0, pi/2], quadrants for sig and omg coincide.
    # No atan2(0,0) ambiguity at poles since cbet1 = +epsilon.
    # With alp0 = 0, omg1 = 0 for alp1 = 0, omg1 = pi for alp1 = pi.
    self._ssig1 = sbet1; self._somg1 = self._salp0 * sbet1
    self._csig1 = self._comg1 = (cbet1 * self._calp1
                                 if sbet1 != 0 or self._calp1 != 0 else 1)
    # sig1 in (-pi, pi]
    self._ssig1, self._csig1 = Math.norm(self._ssig1, self._csig1)
    # No need to normalize
    # self._somg1, self._comg1 = Math.norm(self._somg1, self._comg1)

    self._k2 = Math.sq(self._calp0) * geod._ep2
    eps = self._k2 / (2 * (1 + math.sqrt(1 + self._k2)) + self._k2)

    if self._caps & Geodesic.CAP_C1:
      self._A1m1 = Geodesic.A1m1f(eps)
      self._C1a = list(range(Geodesic.nC1_ + 1))
      Geodesic.C1f(eps, self._C1a)
      self._B11 = Geodesic.SinCosSeries(
        True, self._ssig1, self._csig1, self._C1a)
      s = math.sin(self._B11); c = math.cos(self._B11)
      # tau1 = sig1 + B11
      self._stau1 = self._ssig1 * c + self._csig1 * s
      self._ctau1 = self._csig1 * c - self._ssig1 * s
      # Not necessary because C1pa reverts C1a
      #    _B11 = -SinCosSeries(true, _stau1, _ctau1, _C1pa)

    if self._caps & Geodesic.CAP_C1p:
      self._C1pa = list(range(Geodesic.nC1p_ + 1))
      Geodesic.C1pf(eps, self._C1pa)

    if self._caps & Geodesic.CAP_C2:
      self._A2m1 = Geodesic.A2m1f(eps)
      self._C2a = list(range(Geodesic.nC2_ + 1))
      Geodesic.C2f(eps, self._C2a)
      self._B21 = Geodesic.SinCosSeries(
        True, self._ssig1, self._csig1, self._C2a)

    if self._caps & Geodesic.CAP_C3:
      self._C3a = list(range(Geodesic.nC3_))
      geod.C3f(eps, self._C3a)
      self._A3c = -self._f * self._salp0 * geod.A3f(eps)
      self._B31 = Geodesic.SinCosSeries(
        True, self._ssig1, self._csig1, self._C3a)

    if self._caps & Geodesic.CAP_C4:
      self._C4a = list(range(Geodesic.nC4_))
      geod.C4f(eps, self._C4a)
      # Multiplier = a^2 * e^2 * cos(alpha0) * sin(alpha0)
      self._A4 = Math.sq(self._a) * self._calp0 * self._salp0 * geod._e2
      self._B41 = Geodesic.SinCosSeries(
        False, self._ssig1, self._csig1, self._C4a)