def reverse(self, x, y, name=NN, LatLon=None, **LatLon_kwds): '''Convert an azimuthal equidistant location to (ellipsoidal) geodetic lat- and longitude. @arg x: Easting of the location (C{meter}). @arg y: Northing of the location (C{meter}). @kwarg name: Optional name for the location (C{str}). @kwarg LatLon: Class to use (C{LatLon}) or C{None}. @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword arguments, ignored if C{B{LatLon}=None}. @return: The geodetic (C{LatLon}) or if B{C{LatLon}} is C{None} an L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}. @note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon} in the range C{[-180..180] degrees}. The scale of the projection is C{1} in I{radial} direction, C{azimuth} clockwise from true North and is C{1 / reciprocal} in the direction perpendicular to this. ''' x = Meter(x=x) y = Meter(y=y) z = atan2d(x, y) # (x, y) for azimuth from true North s = hypot(x, y) r = self.geodesic.Direct(self.lat0, self.lon0, z, s, self._mask) t = self._7Tuple(x, y, r) if LatLon is None else \ self._toLatLon(r.lat2, r.lon2, LatLon, LatLon_kwds) return self._xnamed(t, name=name)
def _reverse(self, x, y, name, LatLon, LatLon_kwds, _c_t, lea): '''(INTERNAL) Azimuthal (spherical) reverse C{x, y} to C{lat, lon}. ''' x = Scalar(x, name=_x_) y = Scalar(y, name=_y_) r = hypot(x, y) c, t = _c_t(r / self.radius) if t: s0, c0 = self._sc0 sc, cc = sincos2(c) k = c / sc z = atan2d(x, y) # (x, y) for azimuth from true North lat = degrees(asin1(s0 * cc + c0 * sc * (y / r))) if lea or abs(c0) > EPS: lon = atan2(x * sc, c0 * cc * r - s0 * sc * y) else: lon = atan2(x, (y if s0 < 0 else -y)) lon = _norm180(self.lon0 + degrees(lon)) else: k, z = 1, 0 lat, lon = self.latlon0 t = self._toLatLon(lat, lon, LatLon, LatLon_kwds) if LatLon else \ Azimuthal7Tuple(x, y, lat, lon, z, k, self.datum) return _xnamed(t, name or self.name)
def reverse(self, x, y, name=NN, LatLon=None, **LatLon_kwds): '''Convert an azimuthal gnomonic location to (ellipsoidal) geodetic lat- and longitude. @arg x: Easting of the location (C{meter}). @arg y: Northing of the location (C{meter}). @kwarg name: Optional name for the location (C{str}). @kwarg LatLon: Class to use (C{LatLon}) or C{None}. @kwarg LatLon_kwds: Optional, additional B{C{LatLon}} keyword arguments, ignored if C{B{LatLon}=None}. @return: The geodetic (C{LatLon}) or if B{C{LatLon}} is C{None} an L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)}. @raise AzimuthalError: No convergence. @note: The C{lat} will be in the range C{[-90..90] degrees} and C{lon} in the range C{[-180..180] degrees}. The C{azimuth} is clockwise from true North. The scale is C{1 / reciprocal**2} in C{radial} direction and C{1 / reciprocal} in the direction perpendicular to this. ''' x = Scalar(x=x) y = Scalar(y=y) z = atan2d(x, y) # (x, y) for azimuth from true North q = hypot(x, y) d = e = self.equatoradius s = e * atan(q / e) if q > e: def _d(r, q): return (r.M12 - q * r.m12) * r.m12 # negated q = 1 / q else: # little == True def _d(r, q): # PYCHOK _d return (q * r.M12 - r.m12) * r.M12 # negated e *= _Karney_eps S = Fsum(s) g = self.geodesic.Line(self.lat0, self.lon0, z, self._mask) for self._iteration in range(1, _TRIPS): r = g.Position(s, self._mask) if abs(d) < e: break s, d = S.fsum2_(_d(r, q)) else: raise AzimuthalError(x=x, y=y, txt=_no_(Fmt.convergence(e))) t = self._7Tuple(x, y, r, r.M12) if LatLon is None else \ self._toLatLon(r.lat2, r.lon2, LatLon, LatLon_kwds) t._iteration = self._iteration return self._xnamed(t, name=name)
def _forward(self, lat, lon, name, _k_t): '''(INTERNAL) Azimuthal (spherical) forward C{lat, lon} to C{x, y}. ''' sa, ca, sb, cb = sincos2d(Lat_(lat), Lon_(lon) - self.lon0) s0, c0 = self._sc0 k, t = _k_t(s0 * sa + c0 * ca * cb) if t: r = k * self.radius x = r * ca * sb y = r * (c0 * sa - s0 * ca * cb) z = atan2d(x, y) # (x, y) for azimuth from true North else: # 0 or 180 x = y = z = 0 t = Azimuthal7Tuple(x, y, lat, lon, z, k, self.datum) return _xnamed(t, name or self.name)
def _scaled(self, tau, d2, snu, cnu, dnu, snv, cnv, dnv): '''(INTERNAL) C{scaled}. @note: Argument B{C{d2}} is C{_mu * cnu**2 + _mv * cnv**2} from C{._sigma3} or C{._zeta3}. @return: 2-Tuple C{(convergence, scale)}. @see: C{void TMExact::Scale(real tau, real /*lam*/, real snu, real cnu, real dnu, real snv, real cnv, real dnv, real &gamma, real &k)}. ''' mu, mv = self._mu, self._mv cnudnv = cnu * dnv # Lee 55.12 -- negated for our sign convention. g gives # the bearing (clockwise from true north) of grid north g = atan2d(mv * cnv * snv * snu, cnudnv * dnu) # Lee 55.13 with nu given by Lee 9.1 -- in sqrt change # the numerator from # # (1 - snu^2 * dnv^2) to (_mv * snv^2 + cnu^2 * dnv^2) # # to maintain accuracy near phi = 90 and change the # denomintor from # (dnu^2 + dnv^2 - 1) to (_mu * cnu^2 + _mv * cnv^2) # # to maintain accuracy near phi = 0, lam = 90 * (1 - e). # Similarly rewrite sqrt term in 9.1 as # # _mv + _mu * c^2 instead of 1 - _mu * sin(phi)^2 q2 = (mv * snv**2 + cnudnv**2) / d2 # originally: sec2 = 1 + tau**2 # sec(phi)^2 # k = sqrt(mv + mu / sec2) * sqrt(sec2) * sqrt(q2) # = sqrt(mv + mv * tau**2 + mu) * sqrt(q2) k = sqrt(fsum_(mu, mv, mv * tau**2)) * sqrt(q2) return g, k * self._k0
def _Lat_s_c3(name, s, c): L = Lat_(atan2d(s, c), name=name, Error=AlbersError) r = _1_0 / Float_(hypot(s, c), name=name, Error=AlbersError) return L, s * r, c * r
def _Lat_s_c3(s, c, name): L = _Lat_(atan2d(s, c), name=name) r = 1.0 / Float_(hypot(s, c), Error=AlbersError, name=name) return L, s * r, c * r