def forward(self, lat, lon, name=NN): '''Convert an (ellipsoidal) geodetic location to azimuthal equidistant east- and northing. @arg lat: Latitude of the location (C{degrees90}). @arg lon: Longitude of the location (C{degrees180}). @kwarg name: Optional name for the location (C{str}). @return: An L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)} with C{x} and C{y} in C{meter} and C{lat} and C{lon} in C{degrees}. The C{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. @see: Method L{EquidistantKarney.reverse}. A call to C{.forward} followed by a call to C{.reverse} will return the original C{lat, lon} to within roundoff. @raise AzimuthalError: Invalid B{C{lat}} or B{C{lon}}. ''' r = self.geodesic.Inverse(self.lat0, self.lon0, Lat_(lat), Lon_(lon), self._mask) x, y = sincos2d(r.azi1) t = Azimuthal7Tuple(x * r.s12, y * r.s12, r.lat2, r.lon2, r.azi2, self._1_rk(r), self.datum) return _xnamed(t, name or self.name)
def __new__(cls, x, y, lat, lon, azi, s, datum): return _NamedTuple.__new__( cls, Scalar(x, name=_x_, Error=AzimuthalError), Scalar(y, name=_y_, Error=AzimuthalError), # PYCHOK indent Lat_(lat, Error=AzimuthalError), Lon_(lon, Error=AzimuthalError), Bearing(azi, name=_azimuth_, Error=AzimuthalError), Scalar(s, name=_scale_, Error=AzimuthalError), datum)
def reset(self, lat0, lon0): '''Set or reset the center point of this azimuthal projection. @arg lat0: Center point latitude (C{degrees90}). @arg lon0: Center point longitude (C{degrees180}). @raise AzimuthalError: Invalid B{C{lat0}} or B{C{lon0}}. ''' self._latlon0 = LatLon2Tuple(Lat_(lat0=lat0, Error=AzimuthalError), Lon_(lon0=lon0, Error=AzimuthalError)) self._sc0 = tuple(sincos2d(self.lat0)) self._radius = None
def reset(self, lat0, lon0): '''Set or reset the center point of this Cassini-Soldner projection. @arg lat0: Center point latitude (C{degrees90}). @arg lon0: Center point longitude (C{degrees180}). @raise CSSError: Invalid B{C{lat0}} or B{C{lon0}}. ''' g, M = self.datum.ellipsoid._geodesic_Math2 self._meridian = m = g.Line(Lat_(lat0, name=_lat0_, Error=CSSError), Lon_(lon0, name=_lon0_, Error=CSSError), 0.0, g.STANDARD | g.DISTANCE_IN) self._latlon0 = LatLon2Tuple(m.lat1, m.lon1) s, c = M.sincosd(m.lat1) # == self.lat0 == self.LatitudeOrigin() self._sb0, self._cb0 = M.norm(s * (1.0 - g.f), c)
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 = atan2b(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 self._xnamed(t, name=name)
def forward4(self, lat, lon): '''Convert an (ellipsoidal) geodetic location to Cassini-Soldner easting and northing. @arg lat: Latitude of the location (C{degrees90}). @arg lon: Longitude of the location (C{degrees180}). @return: An L{EasNorAziRk4Tuple}C{(easting, northing, azimuth, reciprocal)}. @see: Method L{CassiniSoldner.forward}, L{CassiniSoldner.reverse} and L{CassiniSoldner.reverse4}. @raise CSSError: Invalid B{C{lat}} or B{C{lon}}. ''' g, M = self.datum.ellipsoid._geodesic_Math2 lat = Lat_(lat, Error=CSSError) d = M.AngDiff(self.lon0, Lon_(lon, Error=CSSError))[0] # _2sum r = g.Inverse(lat, -abs(d), lat, abs(d)) z1, a = r.azi1, (r.a12 * 0.5) z2, s = r.azi2, (r.s12 * 0.5) if s == 0: z = M.AngDiff(z1, z2)[0] * 0.5 # _2sum c = -90 if abs(d) > 90 else 90 z1, z2 = c - z, c + z if d < 0: a, s, z2 = -a, -s, z1 # z: azimuth of easting direction e, z = s, M.AngNormalize(z2) p = g.Line(lat, d, z, g.DISTANCE | g.GEODESICSCALE) # rk: reciprocal of azimuthal northing scale rk = p.ArcPosition(-a, g.GEODESICSCALE).M21 # rk = p._GenPosition(True, -a, g.DISTANCE)[7] # s, c = M.sincosd(p.EquatorialAzimuth()) s, c = M.sincosd(M.atan2d(p._salp0, p._calp0)) sb1 = -c if lat < 0 else c cb1 = -abs(s) if abs(d) > 90 else abs(s) # copysign(s, 90 - abs(d)) d = M.atan2d(sb1 * self._cb0 - cb1 * self._sb0, cb1 * self._cb0 + sb1 * self._sb0) n = self._meridian.ArcPosition(d, g.DISTANCE).s12 # n = self._meridian._GenPosition(True, d, g.DISTANCE)[4] r = EasNorAziRk4Tuple(e, n, z, rk) return self._xnamed(r)
def forward(self, lat, lon, name=NN, raiser=True): '''Convert an (ellipsoidal) geodetic location to azimuthal gnomonic east- and northing. @arg lat: Latitude of the location (C{degrees90}). @arg lon: Longitude of the location (C{degrees180}). @kwarg name: Optional name for the location (C{str}). @kwarg raiser: Do or don't throw an error (C{bool}) if the location lies over the horizon. @return: An L{Azimuthal7Tuple}C{(x, y, lat, lon, azimuth, scale, datum)} with C{x} and C{y} in C{meter} and C{lat} and C{lon} in C{degrees} and C{azimuth} clockwise from true North. The C{scale} of the projection is C{1 / reciprocal**2} in I{radial} direction and C{1 / reciprocal} in the direction perpendicular to this. Both C{x} and C{y} will be C{NAN} if the geodetic location lies over the horizon and B{C{raiser}} is C{False}. @raise AzimuthalError: Invalid B{C{lat}}, B{C{lon}} or the geodetic location lies over the horizon and B{C{raiser}} is C{True}. ''' self._iteration = 0 r = self.geodesic.Inverse(self.lat0, self.lon0, Lat_(lat), Lon_(lon), self._mask) if r.M21 < EPS: if raiser: raise AzimuthalError(lat=lat, lon=lon, txt=_over_horizon_) x = y = NAN else: q = r.m12 / r.M21 # .M12 x, y = sincos2d(r.azi1) x *= q y *= q t = self._7Tuple(x, y, r, r.M21) t._iteraton = self._iteration # = 0 return self._xnamed(t, name=name)
def _Lat(**name_lat): '''(INTERNAL) Latitude C{-90 <= B{lat} <= 90}. ''' return Lat_(Error=AlbersError, **name_lat)
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_(lat, name=_lat_): '''(INTERNAL) Latitude C{-90 <= B{lat} <= 90}. ''' return Lat_(lat, name=name, Error=AlbersError)
def __new__(cls, lat, lon, azi, rk): return _NamedTuple.__new__(cls, Lat_(lat, Error=CSSError), Lon_(lon, Error=CSSError), Bearing(azi, Error=CSSError), Scalar(rk, Error=CSSError))