Esempio n. 1
0
    def _sigmaInv0(self, xi, eta):
        '''Starting point for C{sigmaInv}.

           @return: 3-Tuple C{(u, v, trip)}.

           @see: C{bool TMExact::sigmainv0(real xi, real eta,
                                           real &u, real &v)}.
        '''
        trip = False
        if eta > self._Ev_KE_5_4 or xi < min(-self._Eu_E_1_4,
                                             eta - self._Ev_KE):
            # sigma as a simple pole at
            #  w = w0 = Eu.K() + i * Ev.K()
            # and sigma is approximated by
            #  sigma = (Eu.E() + i * Ev.KE()) + 1/(w - w0)
            x = xi - self._Eu_E
            y = eta - self._Ev_KE
            d = x**2 + y**2
            u = self._Eu_K + x / d
            v = self._Ev_K - y / d

        elif eta > self._Ev_KE or (eta > self._Ev_KE_3_4
                                   and xi < self._Eu_E_1_4):
            # At w = w0 = i * Ev.K(), we have
            #  sigma  = sigma0  = i * Ev.KE()
            #  sigma' = sigma'' = 0
            #
            # including the next term in the Taylor series gives:
            #  sigma = sigma0 - _mv / 3 * (w - w0)^3
            #
            # When inverting this, we map arg(w - w0) = [-pi/2, -pi/6]
            # to arg(sigma - sigma0) = [-pi/2, pi/2]
            # mapping arg = [-pi/2, -pi/6] to [-pi/2, pi/2]

            d = eta - self._Ev_KE
            r = hypot(xi, d)
            # Error using this guess is about 0.068 * rad^(5/3)
            trip = r < _TAYTOL2
            # Map the range [-90, 180] in sigma space to [-90, 0] in
            # w space.  See discussion in zetainv0 on the cut for ang.
            r = cbrt(r * self._3_mv)
            a = atan2(d - xi, xi + d) / 3.0 - PI_4
            s, c = sincos2(a)
            u = r * c
            v = r * s + self._Ev_K

        else:  # use w = sigma * Eu.K/Eu.E (correct in the limit _e -> 0)
            r = self._Eu_K / self._Eu_E
            u = xi * r
            v = eta * r
        return u, v, trip
Esempio n. 2
0
    def toNvector(self, datum=Datums.WGS84):
        '''Convert this cartesian to an (ellipsoidal) n-vector.

           @keyword datum: Optional datum to use (L{Datum}).

           @return: The ellipsoidal n-vector (L{Nvector}).

           @raise ValueError: The I{Cartesian} at origin.

           @example:

           >>> from ellipsoidalNvector import LatLon
           >>> c = Cartesian(3980581, 97, 4966825)
           >>> n = c.toNvector()  # (0.62282, 0.000002, 0.78237, +0.24)
        '''
        if self._Nv is None or datum != self._Nv.datum:
            E = datum.ellipsoid
            x, y, z = self.to3xyz()

            # Kenneth Gade eqn 23
            p = (x**2 + y**2) * E.a2_
            q = (z**2 * E.e12) * E.a2_
            r = fsum_(p, q, -E.e4) / 6
            s = (p * q * E.e4) / (4 * r**3)
            t = cbrt(fsum_(1, s, sqrt(s * (2 + s))))

            u = r * fsum_(1, t, 1 / t)
            v = sqrt(u**2 + E.e4 * q)
            w = E.e2 * fsum_(u, v, -q) / (2 * v)

            k = sqrt(fsum_(u, v, w**2)) - w
            if abs(k) < EPS:
                raise ValueError('%s: %r' % ('origin', self))
            e = k / (k + E.e2)
            d = e * hypot(x, y)

            t = hypot(d, z)
            if t < EPS:
                raise ValueError('%s: %r' % ('origin', self))
            h = fsum_(k, E.e2, -1) / k * t

            s = e / t
            self._Nv = Nvector(x * s,
                               y * s,
                               z / t,
                               h=h,
                               datum=datum,
                               name=self.name)
        return self._Nv
Esempio n. 3
0
    def _zetaInv0(self, psi, lam):
        '''Starting point for C{zetaInv}.

           @return: 3-Tuple C{(u, v, trip)}.

           @see: C{bool TMExact::zetainv0(real psi, real lam,  # radians
                                          real &u, real &v)}.
        '''
        trip = False
        if (psi < -self._e_PI_4 and lam > self._1_e2_PI_2
                and psi < lam - self._1_e_PI_2):
            # N.B. this branch is normally not taken because psi < 0
            # is converted psi > 0 by Forward.
            #
            # There's a log singularity at w = w0 = Eu.K() + i * Ev.K(),
            # corresponding to the south pole, where we have, approximately
            #
            #  psi = _e + i * pi/2 - _e * atanh(cos(i * (w - w0)/(1 + _mu/2)))
            #
            # Inverting this gives:
            h = sinh(1 - psi / self._e)
            a = (PI_2 - lam) / self._e
            s, c = sincos2(a)
            u = self._Eu_K - asinh(s / hypot(c, h)) * self._mu_2_1
            v = self._Ev_K - atan2(c, h) * self._mu_2_1

        elif (psi < self._e_PI_2 and lam > self._1_e2_PI_2):
            # At w = w0 = i * Ev.K(), we have
            #
            #  zeta  = zeta0  = i * (1 - _e) * pi/2
            #  zeta' = zeta'' = 0
            #
            # including the next term in the Taylor series gives:
            #
            #  zeta = zeta0 - (_mv * _e) / 3 * (w - w0)^3
            #
            # When inverting this, we map arg(w - w0) = [-90, 0] to
            # arg(zeta - zeta0) = [-90, 180]

            d = lam - self._1_e_PI_2
            r = hypot(psi, d)
            # Error using this guess is about 0.21 * (rad/e)^(5/3)
            trip = r < self._e_taytol_
            # atan2(dlam-psi, psi+dlam) + 45d gives arg(zeta - zeta0)
            # in range [-135, 225).  Subtracting 180 (since multiplier
            # is negative) makes range [-315, 45).  Multiplying by 1/3
            # (for cube root) gives range [-105, 15).  In particular
            # the range [-90, 180] in zeta space maps to [-90, 0] in
            # w space as required.
            r = cbrt(r * self._3_mv_e)
            a = atan2(d - psi, psi + d) / 3.0 - PI_4
            s, c = sincos2(a)
            u = r * c
            v = r * s + self._Ev_K

        else:
            # Use spherical TM, Lee 12.6 -- writing C{atanh(sin(lam) /
            # cosh(psi)) = asinh(sin(lam) / hypot(cos(lam), sinh(psi)))}.
            # This takes care of the log singularity at C{zeta = Eu.K()},
            # corresponding to the north pole.
            s, c = sincos2(lam)
            h, r = sinh(psi), self._Eu_K / PI_2
            # But scale to put 90, 0 on the right place
            u = r * atan2(h, c)
            v = r * asinh(s / hypot(c, h))
        return u, v, trip