Ejemplo n.º 1
0
    def toStr(self, prec=0, sep=' ', B=False, cs=False):  # PYCHOK expected
        '''Return a string representation of this UTM coordinate.

           To distinguish from MGRS grid zone designators, a
           space is left between the zone and the hemisphere.

           Note that UTM coordinates are rounded, not truncated
           (unlike MGRS grid references).

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword B: Optionally, include latitudinal band (C{bool}).
           @keyword cs: Optionally, include meridian convergence and
                        grid scale factor (C{bool}).

           @return: This UTM as a string with I{zone[band], hemisphere,
                    easting, northing, [convergence, scale]} in
                    C{"00 N|S meter meter"} plus C{" degrees float"} if
                    I{cs} is C{True} (C{str}).

           @example:

           >>> u = Utm(3, 'N', 448251, 5411932.0001)
           >>> u.toStr(4)  # 03 N 448251.0 5411932.0001
           >>> u.toStr(sep=', ')  # 03 N, 448251, 5411932
        '''
        z = '%02d%s' % (self.zone, self.band if B else '')
        t = (z, self.hemisphere, fStr(self.easting,
                                      prec=prec), fStr(self.northing,
                                                       prec=prec))
        if cs:
            t += ('n/a' if self.convergence is None else degDMS(
                self.convergence, prec=8, pos='+'),
                  'n/a' if self.scale is None else fStr(self.scale, prec=8))
        return sep.join(t)
Ejemplo n.º 2
0
def decode(geohash):
    '''Decode a geohash to lat-/longitude of the (approximate
       centre of) geohash cell, to reasonable precision.

       @param geohash: To be decoded (L{Geohash}).

       @return: 2-Tuple (latStr, lonStr) in (C{str}).

       @raise TypeError: The I{geohash} is not a L{Geohash}, C{LatLon}
                         or C{str}.

       @raise ValueError: Invalid or null I{geohash}.

       @example:

       >>> geohash.decode('u120fxw')  # '52.205', '0.1188'
       >>> geohash.decode('sunny')  # '23.708', '42.473'  Saudi Arabia
       >>> geohash.decode('fur')  # '69.6', '-45.7'  Greenland
       >>> geohash.decode('reef')  # '-24.87', '162.95'  Coral Sea
       >>> geohash.decode('geek')  # '65.48', '-17.75'  Iceland
    '''
    s, w, n, e = bounds(geohash)

    # round to near centre without excessive precision
    # ⌊2-log10(Δ°)⌋ decimal places, strip trailing zeros
    lat = fStr(favg(n, s), prec=int(2 - log10(n - s)))
    lon = fStr(favg(e, w), prec=int(2 - log10(e - w)))

    return lat, lon  # strings
Ejemplo n.º 3
0
    def toStr(self, prec=0, sep=' ', B=False, cs=False):  # PYCHOK expected
        '''Return a string representation of this UPS coordinate.

           Note that UPS coordinates are rounded, not truncated
           (unlike MGRS grid references).

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword B: Optionally, include and polar band letter (C{bool}).
           @keyword cs: Optionally, include gamma meridian convergence
                        and point scale factor (C{bool}).

           @return: This UPS as a string with I{00[Band] pole, easting,
                    northing, [convergence, scale]} as C{"00[B] N|S
                    meter meter"} plus C{" DMS float"} if I{cs} is C{True},
                    where C{[Band]} is present and C{'A'|'B'|'Y'|'Z'} only
                    if I{B} is C{True} and convergence C{DMS} is in
                    I{either} degrees, minutes I{or} seconds (C{str}).

           @note: Zone zero (C{"00"}) for UPS follows Karney's U{zone UPS
                  <http://GeographicLib.SourceForge.io/html/classGeographicLib_1_1UTMUPS.html>}.
        '''
        z = _UPS_ZONE_STR + (self.band if B else '')
        t = (z, self.pole, fStr(self.easting,  prec=prec),
                           fStr(self.northing, prec=prec))
        if cs:
            t += ('n/a' if self.convergence is None else
                    degDMS(self.convergence, prec=8, pos='+'),
                  'n/a' if self.scale is None else
                      fStr(self.scale, prec=8))
        return sep.join(t)
Ejemplo n.º 4
0
    def toStr(self, prec=0, sep=' ', B=False, cs=False):  # PYCHOK expected
        '''Return a string representation of this UTM coordinate.

           To distinguish from MGRS grid zone designators, a
           space is left between the zone and the hemisphere.

           Note that UTM coordinates are rounded, not truncated
           (unlike MGRS grid references).

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword B: Optionally, include latitudinal band (C{bool}).
           @keyword cs: Optionally, include meridian convergence and
                        grid scale factor (C{bool}).

           @return: This UTM as string "00 N|S meter meter" (C{str})
                    plus " degrees float" if I{cs} is C{True}.

           @example:

           >>> u = Utm(3, 'N', 448251, 5411932.0001)
           >>> u.toStr(4)  # 03 N 448251.0 5411932.0001
           >>> u.toStr(sep=', ')  # 03 N, 448251, 5411932
        '''
        b = self._band if B else ''
        t = ['%02d%s %s' % (self._zone, b, self._hemi),
             fStr(self._easting, prec=prec),
             fStr(self._northing, prec=prec)]
        if cs:
            t += ['n/a' if self._convergence is None else
                      fStr(self._convergence, prec=8, fmt='%+013.*f') + S_DEG,
                  'n/a' if self._scale is None else
                      fStr(self._scale, prec=8)]
        return sep.join(t)
Ejemplo n.º 5
0
def equirectangular_(lat1,
                     lon1,
                     lat2,
                     lon2,
                     adjust=True,
                     limit=45,
                     wrap=False):
    '''Compute the distance between two points using
       the U{Equirectangular Approximation / Projection
       <http://www.Movable-Type.co.UK/scripts/latlong.html>}.

       This approximation is valid for short distance of several
       hundred Km or Miles, see the I{limit} keyword argument and
       the L{LimitError}.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword adjust: Adjust the wrapped, unrolled longitudinal
                        delta by the cosine of the mean latitude (C{bool}).
       @keyword limit: Optional limit for lat- and longitudinal deltas
                       (C{degrees}) or C{None} or C{0} for unlimited.
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: 4-Tuple (distance2, delta_lat, delta_lon, unroll_lon2)
                with the distance in C{degrees squared}, the latitudinal
                delta I{lat2}-I{lat1}, the wrapped, unrolled, and
                adjusted longitudinal delta I{lon2}-I{lon1} and the
                unrollment for I{lon2}.  Use Function L{degrees2m} to
                convert C{degrees squared} to distance in C{meter} as
                M{degrees2m(sqrt(distance2), ...)} or
                M{degrees2m(hypot(delta_lat, delta_lon), ...)}.

       @raise LimitError: If the lat- and/or longitudinal delta exceeds
                          the I{-limit..+limit} range and L{limiterrors}
                          set to C{True}.

       @see: U{Local, flat earth approximation
             <http://www.EdWilliams.org/avform.htm#flat>}, functions
             L{equirectangular} and L{haversine}, L{Ellipsoid} method
             C{distance2} and C{LatLon} methods C{distanceTo*}
             for more accurate and/or larger distances.
    '''
    d_lat = lat2 - lat1
    d_lon, ulon2 = unroll180(lon1, lon2, wrap=wrap)

    if limit and _limiterrors \
             and max(abs(d_lat), abs(d_lon)) > limit > 0:
        t = fStr((lat1, lon1, lat2, lon2), prec=4)
        raise LimitError('%s(%s, limit=%s) delta exceeds limit' %
                         ('equirectangular_', t, fStr(limit, prec=2)))

    if adjust:  # scale delta lon
        d_lon *= cos(radians(lat1 + lat2) * 0.5)

    d2 = d_lat**2 + d_lon**2  # degrees squared!
    return d2, d_lat, d_lon, ulon2 - lon2
Ejemplo n.º 6
0
def equirectangular_(lat1,
                     lon1,
                     lat2,
                     lon2,
                     adjust=True,
                     limit=45,
                     wrap=False):
    '''Compute the distance between two points using
       the U{Equirectangular Approximation / Projection
       <http://www.movable-type.co.uk/scripts/latlong.html>}.

       This approximation is valid for smaller distance of several
       hundred Km or Miles, see the I{limit} keyword argument and
       the L{LimitError}.

       @param lat1: Start latitude (degrees).
       @param lon1: Start longitude (degrees).
       @param lat2: End latitude (degrees).
       @param lon2: End longitude (degrees).
       @keyword adjust: Adjust the wrapped, unrolled longitudinal
                        delta by the cosine of the mean latitude (bool).
       @keyword limit: Optional limit for the lat- and longitudinal
                       deltas (degrees) or None or 0 for unlimited.
       @keyword wrap: Wrap and L{unroll180} longitudes and longitudinal
                      delta (bool).

       @return: 4-Tuple (distance2, delta_lat, delta_lon, lon2_unroll)
                with the distance in degrees squared, the latitudinal
                delta I{lat2}-I{lat1}, the wrapped, unrolled, and
                adjusted longitudinal delta I{lon2}-I{lon1} and the
                unrollment for I{lon2}.  To convert I{distance2} to
                meter, use M{radians(sqrt(distance2)) * radius} where
                I{radius} is the mean earth radius in the desired units,
                for example L{R_M} meter.

       @raise LimitError: If the lat- and/or longitudinal delta exceeds
                          the I{-limit..+limit} range and I{limiterrors}
                          set to True.

       @see: U{Local, Flat Earth<http://www.edwilliams.org/avform.htm#flat>},
             method L{Ellipsoid.distance2}, function L{equirectangular}
             for distance only and function L{haversine} for accurate
             and/or larger distances.
    '''
    d_lat = lat2 - lat1
    d_lon, ulon2 = unroll180(lon1, lon2, wrap=wrap)

    if limit and _limiterrors \
             and max(abs(d_lat), abs(d_lon)) > limit > 0:
        t = fStr((lat1, lon1, lat2, lon2), prec=4)
        raise LimitError('%s(%s, limit=%s) delta exceeds limit' %
                         ('equirectangular_', t, fStr(limit, prec=2)))

    if adjust:  # scale delta lon
        d_lon *= cos(radians(lat1 + lat2) * 0.5)

    d2 = d_lat**2 + d_lon**2  # degrees squared!
    return d2, d_lat, d_lon, ulon2 - lon2
Ejemplo n.º 7
0
 def _toStr4_6(self, hemipole, B, cs, prec, sep):
     '''(INTERNAL) Return a string representation of this UTM/UPS coordinate.
     '''
     z = '%02d%s' % (self.zone, (self.band if B else ''))  # PYCHOK band
     t = (z, hemipole, fStr(self.easting,
                            prec=prec), fStr(self.northing, prec=prec))
     if cs:
         t += ('n/a' if self.convergence is None else degDMS(
             self.convergence, prec=8, pos='+'),
               'n/a' if self.scale is None else fStr(self.scale, prec=8))
     return sep.join(t)
Ejemplo n.º 8
0
def equirectangular_(lat1,
                     lon1,
                     lat2,
                     lon2,
                     adjust=True,
                     limit=45,
                     wrap=False):
    '''Compute the distance between two points using
       the U{Equirectangular Approximation / Projection
       <https://www.Movable-Type.co.UK/scripts/latlong.html>}.

       This approximation is valid for short distance of several
       hundred Km or Miles, see the B{C{limit}} keyword argument and
       the L{LimitError}.

       @param lat1: Start latitude (C{degrees}).
       @param lon1: Start longitude (C{degrees}).
       @param lat2: End latitude (C{degrees}).
       @param lon2: End longitude (C{degrees}).
       @keyword adjust: Adjust the wrapped, unrolled longitudinal
                        delta by the cosine of the mean latitude (C{bool}).
       @keyword limit: Optional limit for lat- and longitudinal deltas
                       (C{degrees}) or C{None} or C{0} for unlimited.
       @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).

       @return: A L{Distance4Tuple}C{(distance2, delta_lat, delta_lon,
                unroll_lon2)}.

       @raise LimitError: If the lat- and/or longitudinal delta exceeds
                          the B{C{-limit..+limit}} range and L{limiterrors}
                          set to C{True}.

       @see: U{Local, flat earth approximation
             <https://www.EdWilliams.org/avform.htm#flat>}, functions
             L{equirectangular}, L{euclidean}, L{haversine} and
             L{vincentys} and methods L{Ellipsoid.distance2},
             C{LatLon.distanceTo*} and C{LatLon.equirectangularTo}.
    '''
    d_lat = lat2 - lat1
    d_lon, ulon2 = unroll180(lon1, lon2, wrap=wrap)

    if limit and _limiterrors \
             and max(abs(d_lat), abs(d_lon)) > limit > 0:
        t = fStr((lat1, lon1, lat2, lon2), prec=4)
        raise LimitError('%s(%s, limit=%s) delta exceeds limit' %
                         ('equirectangular_', t, fStr(limit, prec=2)))

    if adjust:  # scale delta lon
        d_lon *= _scaled(lat1, lat2)

    d2 = d_lat**2 + d_lon**2  # degrees squared!
    return Distance4Tuple(d2, d_lat, d_lon, ulon2 - lon2)
Ejemplo n.º 9
0
    def toStr(self, prec=6, sep=' ', m='m'):  # PYCHOK expected
        '''Return a string representation of this L{Css} position.

           @keyword prec: Optional number of decimal, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword m: Optional height units, default C{meter} (C{str}).

           @return: This Css as "easting nothing" C{str} in C{meter} plus
                    " height" and 'm' if heigth is non-zero (C{str}).
        '''
        t = [fStr(self.easting, prec=prec), fStr(self.northing, prec=prec)]
        if self.height:
            t += ['%+.2f%s' % (self.height, m)]
        return sep.join(t)
Ejemplo n.º 10
0
    def toStr(self, prec=3, sep=' ', radius=False):  # PYCHOK expected
        '''Return a string representation of this WM coordinate.

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword radius: Optionally, include radius (C{bool} or C{scalar}).

           @return: This WM as "meter meter" (C{str}) plus " radius"
                    if I{radius} is C{True} or C{scalar}.

           @raise ValueError: Invalid I{radius}.

           @example:

           >>> w = Wm(448251, 5411932.0001)
           >>> w.toStr(4)  # 448251.0 5411932.0001
           >>> w.toStr(sep=', ')  # 448251, 5411932
        '''
        fs = self._x, self._y
        if radius in (False, None):
            pass
        elif radius is True:
            fs += (self._radius, )
        elif isscalar(radius):
            fs += (radius, )
        else:
            raise ValueError('% invalid: %r' % ('radius', radius))
        return fStr(fs, prec=prec, sep=sep)
Ejemplo n.º 11
0
def clipDMS(deg, limit):
    '''Clip a lat- or longitude to the given range.

       @param deg: Unclipped lat- or longitude (C{degrees}).
       @param limit: Valid I{-limit..+limit} range (C{degrees}).

       @return: Clipped value (C{degrees}).

       @raise RangeError: If I{deg} beyond I{limit} and L{rangerrors}
                          set to C{True}.
    '''
    if limit > 0:
        c = min(limit, max(-limit, deg))
        if _rangerrors and deg != c:
            raise RangeError('%s beyond %s degrees' % (fStr(
                deg, prec=6), fStr(copysign(limit, deg), prec=3, ints=True)))
        deg = c
    return deg
Ejemplo n.º 12
0
    def toStr(self, prec=6, sep=' '):  # PYCHOK expected
        '''Return a string representation of this projection.

           @keyword prec: Optional number of decimal, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).

           @return: This projection as C{"lat0 lon0"} (C{str}).
        '''
        return fStr(self.latlon0, prec=prec, sep=sep)
Ejemplo n.º 13
0
    def toStr(self, prec=5, fmt='(%s)', sep=', '):  # PYCHOK expected
        '''Return a string representation of this vector.

           @keyword prec: Optional number of decimal places (C{int}).
           @keyword fmt: Optional, enclosing format to use (C{str}).
           @keyword sep: Optional separator between components (C{str}).

           @return: Vector as "(x, y, z)" (C{str}).
        '''
        return fmt % (fStr(self.to3xyz(), prec=prec, sep=sep), )
Ejemplo n.º 14
0
    def toStr(self, prec=3, fmt='[%s]', sep=', '):  # PYCHOK expected
        '''Return a string representation of this NED vector.

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword fmt: Optional enclosing backets format (C{str}).
           @keyword sep: Optional separator between NEDs (C{str}).

           @return: This Ned as "[N:f, E:f, D:f]" (C{str}).
        '''
        t3 = fStr(self.to3ned(), prec=prec, sep=' ').split()
        return fmt % (sep.join('%s:%s' % t for t in zip('NED', t3)), )
Ejemplo n.º 15
0
 def _fStr(self, prec, *attrs, **others):
     '''(INTERNAL) Format.
     '''
     t = fStr([getattr(self, a) for a in attrs],
              prec=prec,
              sep=' ',
              ints=True)
     t = ['%s=%s' % (a, v) for a, v in zip(attrs, t.split())]
     if others:
         t += ['%s=%s' % (a, v) for a, v in sorted(others.items())]
     return ', '.join(['name=%r' % (self.name, )] + t)
Ejemplo n.º 16
0
    def toStr(self, **kwds):
        '''This L{LatLon_} as a string "<degrees>, <degrees>".

           @keyword kwds: Optional, keyword arguments.

           @return: Instance (string).
        '''
        t = [fStr(getattr(self, _)) for _ in self.__slots__]
        if kwds:
            t += ['%s=%s' % _ for _ in sorted(kwds.items())]
        return ', '.join(t)
Ejemplo n.º 17
0
    def toStr(self, prec=0, sep=' ', m='m'):  # PYCHOK expected
        '''Return a string representation of this L{Lcc} position.

           @keyword prec: Optional number of decimal, unstripped (C{int}).
           @keyword sep: Optional separator to join (C{str}).
           @keyword m: Optional height units, default C{meter} (C{str}).

           @return: This Lcc as "easting nothing" C{str} in C{meter} plus
                    " height" and 'm' if heigth is non-zero (C{str}).

           @example:

           >>> lb = Lcc(448251, 5411932.0001)
           >>> lb.toStr(4)  # 448251.0 5411932.0001
           >>> lb.toStr(sep=', ')  # 448251, 5411932
        '''
        t = [fStr(self._easting, prec=prec), fStr(self._northing, prec=prec)]
        if self._height:
            t += ['%+.2f%s' % (self._height, m)]
        return sep.join(t)
Ejemplo n.º 18
0
    def toStr2(self, prec=None, fmt='[%s]', sep=', '):  # PYCHOK expected
        '''Return a string representation of this NED vector as
           length, bearing and elevation.

           @keyword prec: Optional number of decimals, unstripped (C{int}).
           @keyword fmt: Optional enclosing backets format (C{str}).
           @keyword sep: Optional separator between NEDs (C{str}).

           @return: This Ned as "[L:f, B:degrees360, E:degrees90]" (C{str}).
        '''
        t3 = (fStr(self.length, prec=3 if prec is None else prec),
              toDMS(self.bearing, form=F_D, prec=prec,
                    ddd=0), toDMS(self.elevation, form=F_D, prec=prec, ddd=0))
        return fmt % (sep.join('%s:%s' % t for t in zip('LBE', t3)), )
Ejemplo n.º 19
0
def _error(fun, lat, lon, e):
    '''(INTERNAL) Format an error
    '''
    return '%s(%s): %s' % (fun.__name__, fStr((lat, lon)), e)