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
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
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