Ejemplo n.º 1
0
    def __new__(cls, cll, precision=3, name=NN):
        '''New L{Georef} from an other L{Georef} instance or georef
           C{str} or from a C{LatLon} instance or lat-/longitude C{str}.

           @arg cll: Cell or location (L{Georef} or C{str}, C{LatLon}
                     or C{str}).
           @kwarg precision: Optional, the desired georef resolution
                             and length (C{int} 0..11), see function
                             L{wgrs.encode} for more details.
           @kwarg 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 WGRSError: INValid or non-alphanumeric B{C{cll}}.
        '''
        h = None

        if isinstance(cll, Georef):
            g, p = _2geostr2(str(cll))
            self = Str.__new__(cls, g)
            self._latlon = LatLon2Tuple(*cll._latlon)
            self._precision = p  # cll._precision
            if cll._name:
                self._name = cll._name

        elif isstr(cll):
            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)
            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 _xStrError(Georef, cll=cll)  # Error=WGRSError
            g = encode(lat, lon, precision=precision, height=h)  # PYCHOK false
            self = Str.__new__(cls, g)
            self._latlon = LatLon2Tuple(lat, lon)

        if h not in (None, _Missing):
            self._height = Height(h)
        if self._precision is None:
            self._precision = _2Precision(precision)

        if name:
            self.name = name
        return self
Ejemplo n.º 2
0
    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 WGRSError: 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 _IsNotError('valid', **{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
Ejemplo n.º 3
0
    def __new__(cls, cll, precision=1, name=NN):
        '''New L{Garef} from an other L{Garef} instance or garef
           C{str} or from a C{LatLon} instance or lat-/longitude C{str}.

           @arg cll: Cell or location (L{Garef} or C{str}, C{LatLon}
                     or C{str}).
           @kwarg precision: Optional, the desired garef resolution
                             and length (C{int} 0..2), see function
                             L{gars.encode} for more details.
           @kwarg name: Optional name (C{str}).

           @return: New L{Garef}.

           @raise RangeError: Invalid B{C{cll}} lat- or longitude.

           @raise TypeError: Invalid B{C{cll}}.

           @raise GARSError: INValid or non-alphanumeric B{C{cll}}.
        '''
        if isinstance(cll, Garef):
            g, p = _2garstr2(str(cll))
            self = Str.__new__(cls, g)
            self._latlon = LatLon2Tuple(*cll._latlon)
            self._name = cll._name
            self._precision = p  # cll._precision

        elif isstr(cll):
            if ',' in cll:
                lat, lon = _2fll(*parse3llh(cll))
                cll = encode(lat, lon, precision=precision)  # PYCHOK false
                self = Str.__new__(cls, cll)
                self._latlon = LatLon2Tuple(lat, lon)
            else:
                self = Str.__new__(cls, cll.upper())
                self._decode()

        else:  # assume LatLon
            try:
                lat, lon = _2fll(cll.lat, cll.lon)
            except AttributeError:
                raise _xStrError(Garef, cll=cll)  # Error=GARSError
            cll = encode(lat, lon, precision=precision)  # PYCHOK false
            self = Str.__new__(cls, cll)
            self._latlon = LatLon2Tuple(lat, lon)

        if self._precision is None:
            self._precision = _2Precision(precision)

        if name:
            self.name = name
        return self
Ejemplo n.º 4
0
    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)))
Ejemplo n.º 5
0
    def reverse(self, easting, northing, LatLon=None, **LatLon_kwds):
        '''Convert a Cassini-Soldner location to (ellipsoidal) geodetic
           lat- and longitude.

           @arg easting: Easting of the location (C{meter}).
           @arg northing: Northing of the location (C{meter}).
           @kwarg LatLon: Optional, ellipsoidal class to return the
                          geodetic location as (C{LatLon}) or C{None}.
           @kwarg LatLon_kwds: Optional (C{LatLon}) keyword arguments,
                               ignored if B{C{LatLon=None}}.

           @return: Geodetic location B{C{LatLon}} or if B{C{LatLon}}
                    is C{None}, a L{LatLon2Tuple}C{(lat, lon)}.

           @raise CSSError: Ellipsoidal mismatch of B{C{LatLon}} and this projection.

           @raise TypeError: Invalid B{C{LatLon}} or B{C{LatLon_kwds}}.

           @see: Method L{CassiniSoldner.reverse4}, L{CassiniSoldner.forward}
                 and L{CassiniSoldner.forward4}.
        '''
        r = self.reverse4(easting, northing)
        if LatLon is None:
            r = LatLon2Tuple(r.lat, r.lon)  # PYCHOK expected
        else:
            _xsubclassof(_LLEB, LatLon=LatLon)
            kwds = _xkwds(LatLon_kwds, datum=self.datum)
            r = LatLon(r.lat, r.lon, **kwds)  # PYCHOK expected
            self._datumatch(r)
        return self._xnamed(r)
Ejemplo n.º 6
0
    def latlon2(self, datum=None):
        '''Convert this WM coordinate to a lat- and longitude.

           @kwarg datum: Optional ellipsoidal datum (C{Datum}).

           @return: A L{LatLon2Tuple}C{(lat, lon)}.

           @raise TypeError: Non-ellipsoidal B{C{datum}}.

           @see: Method C{toLatLon}.
        '''
        r = self.radius
        x = self._x / r
        y = 2 * atan(exp(self._y / r)) - PI_2
        if datum is not None:
            _xinstanceof(Datum, datum=datum)
            E = datum.ellipsoid
            if not E.isEllipsoidal:
                raise _IsnotError(_ellipsoidal_, datum=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))  # == E.es_atanh(tanh(y))
            y *= E.a
            x *= E.a / r

        r = LatLon2Tuple(Lat(degrees90(y)), Lon(degrees180(x)))
        return self._xnamed(r)
Ejemplo n.º 7
0
 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
Ejemplo n.º 8
0
    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)
Ejemplo n.º 9
0
    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)
Ejemplo n.º 10
0
def antipode(lat, lon):
    '''Return the antipode, the point diametrically opposite
       to a given point in C{degrees}.

       @arg lat: Latitude (C{degrees}).
       @arg 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))
Ejemplo n.º 11
0
    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, name=_lat0_, Error=AzimuthalError),
            Lon_(lon0, name=_lon0_, Error=AzimuthalError))
        self._sc0 = tuple(sincos2d(self.lat0))
        self._radius = None
Ejemplo n.º 12
0
def nearestOn2(point, points, **closed_radius_LatLon_options):  # PYCHOK no cover
    '''DEPRECATED, use function L{sphericalTrigonometry.nearestOn3}.

       @return: ... 2-tuple C{(closest, distance)} of the C{closest}
                point (L{LatLon}) on the polygon and the C{distance}
                between the C{closest} and the given B{C{point}}.  The
                C{closest} is a B{C{LatLon}} or a L{LatLon2Tuple}C{(lat,
                lon)} if B{C{LatLon}} is C{None} ...
    '''
    ll, d, _ = nearestOn3(point, points, **closed_radius_LatLon_options)
    if _xkwds_get(closed_radius_LatLon_options, LatLon=LatLon) is None:
        ll = LatLon2Tuple(ll.lat, ll.lon)
    return ll, d
Ejemplo n.º 13
0
    def to2ll(self):
        '''Convert this vector to (geodetic) lat- and longitude in C{degrees}.

           @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)
Ejemplo n.º 14
0
def _fractional(points, fi):
    '''(INTERANL) Compute point as fractional index.
    '''
    i = int(fi)
    p = points[i]
    f = fi - float(i)
    if f > EPS:
        if f < EPS1:
            q = points[i + 1]
            p = LatLon2Tuple(favg(p.lat, q.lat, f=f), favg(p.lon, q.lon, f=f))
        else:
            p = points[i + 1]
    return p
Ejemplo n.º 15
0
    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}).
        '''
        g, M = self.datum.ellipsoid._geodesic_Math2

        self._meridian = m = g.Line(Lat(lat0, name=_lat0_),
                                    Lon(lon0, name=_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)
Ejemplo n.º 16
0
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 CSSError: Mismatch of this and the B{C{latlon}} ellipsoid.

       @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 _IsNotError(_LLEB.__name__, latlon=latlon)

    cs = _CassiniSoldner(cs0)

    C, E = cs.datum.ellipsoid, latlon.datum.ellipsoid
    if C != E:
        raise CSSError('%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))
Ejemplo n.º 17
0
    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.
        '''
        r = LatLon2Tuple(*self.reverse4(easting, northing)[:2])
        if issubclassof(LatLon, _LLEB):
            r = LatLon(r.lat, r.lon, datum=self.datum)  # PYCHOK expected
        elif LatLon is not None:
            raise _IsNotError(_LLEB.__name__, LatLon=LatLon)
        return self._xnamed(r)
Ejemplo n.º 18
0
def parseDMS2(strLat, strLon, sep=S_SEP, clipLat=90, clipLon=180):
    '''Parse lat- and longitude representions in degrees.

       @arg strLat: Latitude in any of several forms (C{str} or C{degrees}).
       @arg strLon: Longitude in any of several forms (C{str} or C{degrees}).
       @kwarg sep: Optional separator between deg°, min′ and sec″ ('').
       @kwarg clipLat: Keep latitude in B{C{-clipLat..+clipLat}} range (C{degrees}).
       @kwarg clipLon: Keep longitude in B{C{-clipLon..+clipLon}} range (C{degrees}).

       @return: A L{LatLon2Tuple}C{(lat, lon)} in C{degrees}.

       @raise ParseError: Invalid B{C{strLat}} or B{C{strLon}}.

       @raise RangeError: Value of B{C{strLat}} or B{C{strLon}} outside the
                          valid range and L{rangerrors} set to C{True}.

       @note: See the B{Notes} at function L{parseDMS}.

       @see: Functions L{parseDDDMMSS}, L{parseDMS} and L{parse3llh}.
    '''
    return LatLon2Tuple(parseDMS(strLat, suffix=_NS_, sep=sep, clip=clipLat),
                        parseDMS(strLon, suffix=_EW_, sep=sep, clip=clipLon))
Ejemplo n.º 19
0
def toCss(latlon, cs0=_CassiniSoldner0, height=None, Css=Css, name=NN):
    '''Convert an (ellipsoidal) geodetic point to a Cassini-Soldner
       location.

       @arg latlon: Ellipsoidal point (C{LatLon} or L{LatLon4Tuple}).
       @kwarg cs0: Optional, the Cassini-Soldner projection to use
                   (L{CassiniSoldner}).
       @kwarg height: Optional height for the point, overriding the
                      default height (C{meter}).
       @kwarg Css: Optional class to return the location (L{Css}) or C{None}.
       @kwarg 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 CSSError: Ellipsoidal mismatch of B{C{latlon}} and B{C{cs0}}.

       @raise ImportError: Package U{GeographicLib<https://PyPI.org/
                           project/geographiclib>} missing.

       @raise TypeError: If B{C{latlon}} is not ellipsoidal.
    '''
    _xinstanceof(_LLEB, LatLon4Tuple, latlon=latlon)

    cs = _CassiniSoldner(cs0)
    cs._datumatch(latlon)

    c = cs.forward4(latlon.lat, latlon.lon)
    h = latlon.height if height is None else Height(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))
Ejemplo n.º 20
0
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 GeohashError: 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)