def __new__(cls, cll, precision=3, name=''): '''New L{Georef} from an other L{Georef} instance or georef C{str} or from a C{LatLon} instance or lat-/longitude C{str}. @param cll: Cell or location (L{Georef} or C{str}, C{LatLon} or C{str}). @keyword precision: Optional, the desired georef resolution and length (C{int} 0..11), see function L{wgrs.encode} for more details. @keyword name: Optional name (C{str}). @return: New L{Georef}. @raise RangeError: Invalid B{C{cll}} lat- or longitude. @raise TypeError: Invalid B{C{cll}}. @raise ValueError: INValid or non-alphanumeric B{C{cll}}. ''' if isinstance(cll, Georef): g, p = _2geostr2(str(cll)) self = str.__new__(cls, g) self._latlon = LatLon2Tuple(*cll._latlon) self._name = cll._name self._precision = p # cll._precision elif isinstance(cll, _Strs): if ',' in cll: lat, lon, h = _2fllh(*parse3llh(cll, height=None)) g = encode(lat, lon, precision=precision, height=h) # PYCHOK false self = str.__new__(cls, g) self._latlon = LatLon2Tuple(lat, lon) self._precision = precision if h not in (None, _MISSING): self._height = h else: self = str.__new__(cls, cll.upper()) self._decode() else: # assume LatLon try: lat, lon, h = _2fllh(cll.lat, cll.lon) h = getattr(cll, 'height', h) except AttributeError: raise TypeError('%s: %r' % (Georef.__name__, cll)) g = encode(lat, lon, precision=precision, height=h) # PYCHOK false self = str.__new__(cls, g) self._latlon = LatLon2Tuple(lat, lon) self._precision = precision if h not in (None, _MISSING): self._height = h if name: self.name = name return self
def _decode(self): # cache all decoded attrs lat, lon, p = decode3(self) if self._latlon is None: self._latlon = LatLon2Tuple(lat, lon) if self._precision is None: self._precision = p
def sizes(self): '''Get the lat- and longitudinal size of this cell as a L{LatLon2Tuple}C{(lat, lon)} with the latitudinal height and longitudinal width in (C{meter}). ''' n = min(len(_Sizes) - 1, self.precision or 1) return LatLon2Tuple(*map2(float, _Sizes[n][:2]))
def _reverse4(self): '''(INTERNAL) Convert to geodetic location. ''' r = self.cs0.reverse4(self.easting, self.northing) self._latlon = LatLon2Tuple(r.lat, r.lon) self._azi, self._rk = r.azimuth, r.reciprocal return r # LatLonAziRk4Tuple
def _decode(self): # cache all decoded attrs lat, lon, p, h, r = decode5(self) # PYCHOK LatLonPrec5Tuple if self._latlon is None: self._latlon = LatLon2Tuple(lat, lon) if self._precision is None: self._precision = p if self._height is _MISSING: self._height = h if self._radius is _MISSING: self._radius = r
def antipode(lat, lon): '''Return the antipode, the point diametrically opposite to a given point. @param lat: Latitude (C{degrees}). @param lon: Longitude (C{degrees}). @return: A L{LatLon2Tuple}C{(lat, lon)}. @see: U{Geosphere<https://CRAN.R-Project.org/web/packages/geosphere/geosphere.pdf>}. ''' return LatLon2Tuple(-wrap90(lat), wrap180(lon + 180))
def to2ll(self): '''Convert this vector to (geodetic) lat- and longitude. @return: A L{LatLon2Tuple}C{(lat, lon)}. @example: >>> v = Vector3d(0.500, 0.500, 0.707) >>> a, b = v.to2ll() # 44.99567, 45.0 ''' a, b = self.to2ab() r = LatLon2Tuple(degrees90(a), degrees180(b)) return self._xnamed(r)
def latlon2(self, ndigits=0): '''Return this point's lat- and longitude, rounded. @keyword ndigits: Number of decimal digits (C{int}). @return: A L{LatLon2Tuple}C{(lat, lon)}, both rounded away from zero. @see: Built-in function C{round}. ''' r = LatLon2Tuple(round(self.lat, ndigits), round(self.lon, ndigits)) return self._xnamed(r)
def reset(self, lat0, lon0): '''Set the center point of this projection. @param lat0: Latitude of center point (C{degrees90}). @param lon0: Longitude of center point (C{degrees180}). ''' g, M = self.datum.ellipsoid._geodesic2 self._meridian = m = g.Line(lat0, lon0, 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 toCss(latlon, cs0=_CassiniSoldner0, height=None, Css=Css, name=''): '''Convert an (ellipsoidal) geodetic point to a Cassini-Soldner location. @param latlon: Ellipsoidal point (C{LatLon}). @keyword cs0: Optional, the Cassini-Soldner projection to use (L{CassiniSoldner}). @keyword height: Optional height for the point, overriding the default height (C{meter}). @keyword Css: Optional (sub-)class to return the location (L{Css}) or C{None}. @keyword name: Optional B{C{Css}} name (C{str}). @return: The Cassini-Soldner location (B{C{Css}}) or an L{EasNor3Tuple}C{(easting, northing, height)} if B{C{Css}} is C{None}. @raise ImportError: Package U{GeographicLib<https://PyPI.org/ project/geographiclib>} missing. @raise TypeError: If B{C{latlon}} is not ellipsoidal. ''' if not isinstance(latlon, _LLEB): raise TypeError('%s not %s: %r' % ('latlon', 'ellipsoidal', latlon)) cs = _CassiniSoldner(cs0) C, E = cs.datum.ellipsoid, latlon.datum.ellipsoid if C != E: raise ValueError('%s mistmatch: %r vs %r' % ('ellipsoidal', C, E)) c = cs.forward4(latlon.lat, latlon.lon) h = latlon.height if height is None else height if Css is None: r = EasNor3Tuple(c.easting, c.northing, h) else: r = Css(c.easting, c.northing, h=h, cs0=cs) r._latlon = LatLon2Tuple(latlon.lat, latlon.lon) r._azi, r._rk = c.azimuth, c.reciprocal return _xnamed(r, name or nameof(latlon))
def parseDMS2(strLat, strLon, sep=S_SEP, clipLat=90, clipLon=180): '''Parse lat- and longitude representions. @param strLat: Latitude in any of several forms (C{str} or C{degrees}). @param strLon: Longitude in any of several forms (C{str} or C{degrees}). @keyword sep: Optional separator between deg°, min′ and sec″ (''). @keyword clipLat: Keep latitude in B{C{-clipLat..+clipLat}} range (C{degrees}). @keyword clipLon: Keep longitude in B{C{-clipLon..+clipLon}} range (C{degrees}). @return: A L{LatLon2Tuple}C{(lat, lon)} in C{degrees}. @raise RangeError: Value of B{C{strLat}} or B{C{strLon}} outside the valid range and L{rangerrors} set to C{True}. @raise ValueError: Invalid B{C{strLat}} or B{C{strLon}}. @see: Function L{parse3llh} to parse a string with lat-, longitude and height values and function L{parseDMS} to parse individual lat- or longitudes. ''' return LatLon2Tuple(parseDMS(strLat, suffix='NS', sep=sep, clip=clipLat), parseDMS(strLon, suffix='EW', sep=sep, clip=clipLon))
def decode_error(geohash): '''Return the relative lat-/longitude decoding errors for this geohash. @param geohash: To be decoded (L{Geohash}). @return: A L{LatLon2Tuple}C{(lat, lon)} with the lat- and longitudinal errors in (C{degrees}). @raise TypeError: The B{C{geohash}} is not a L{Geohash}, C{LatLon} or C{str}. @raise ValueError: Invalid or null B{C{geohash}}. @example: >>> geohash.decode_error('u120fxw') # 0.00068665, 0.00068665 >>> geohash.decode_error('fur') # 0.703125, 0.703125 >>> geohash.decode_error('fu') # 2.8125, 5.625 >>> geohash.decode_error('f') # 22.5, 22.5 ''' s, w, n, e = bounds(geohash) return LatLon2Tuple((n - s) * 0.5, (e - w) * 0.5)
def reverse(self, easting, northing, LatLon=None): '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic lat- and longitude. @param easting: Easting of the location (C{meter}). @param northing: Northing of the location (C{meter}). @keyword LatLon: Optional, ellipsoidal (sub-)class to return the location as (C{LatLon}) or C{None}. @return: Geodetic location B{C{LatLon}} or a L{LatLon2Tuple}C{(lat, lon)} if B{C{LatLon}} is C{None}. @raise TypeError: If B{C{LatLon}} is not ellipsoidal. ''' a, b = self.reverse4(easting, northing)[:2] if LatLon is None: r = LatLon2Tuple(a, b) elif issubclassof(LatLon, _LLEB): r = LatLon(a, b, datum=self.datum) else: raise TypeError('%s not ellipsoidal: %r' % ('LatLon', LatLon)) return self._xnamed(r)
def to2ll(self, datum=None): '''Convert this WM coordinate to a geodetic lat- and longitude. @keyword datum: Optional datum (C{Datum}). @return: A L{LatLon2Tuple}C{(lat, lon)}. @raise TypeError: Non-ellipsoidal B{C{datum}}. ''' r = self.radius x = self._x / r y = 2 * atan(exp(self._y / r)) - PI_2 if datum: E = datum.ellipsoid if not E.isEllipsoidal: raise TypeError('%s not %s: %r' % ('datum', 'ellipsoidal', datum)) # <https://Earth-Info.NGA.mil/GandG/wgs84/web_mercator/ # %28U%29%20NGA_SIG_0011_1.0.0_WEBMERC.pdf> y = y / r if E.e: y -= E.e * atanh(E.e * tanh(y)) y *= E.a x *= E.a / r return self._xnamed(LatLon2Tuple(degrees90(y), degrees180(x)))
def latlon(self): '''Get the lat- and longitude (L{LatLon2Tuple}). ''' if self._latlon is None: self._latlon = LatLon2Tuple(self._lat, self._lon) return self._xrenamed(self._latlon)