Exemple #1
0
    def latlon2(self, datum=None):
        '''Convert this WM coordinate to a lat- and longitude.

           @kwarg datum: Optional, ellipsoidal datum (L{Datum},
                         L{Ellipsoid}, L{Ellipsoid2} or
                         L{a_f2Tuple}) or C{None}.

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

           @raise TypeError: Invalid or 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:
            E = _ellipsoidal_datum(datum, name=self.name).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)
Exemple #2
0
def _streprs(prec, objs, fmt, ints, force, strepr):
    '''(INTERNAL) Helper for C{fstr}, C{pairs}, C{reprs} and C{strs}
    '''
    if fmt in _EeFfGg:
        fGg = fmt in _Gg
        fmt = '%.' + str(abs(prec)) + fmt
    elif fmt.startswith(_PERCENT_):
        fGg = False
        fmt = fmt.replace(_STAR_, str(abs(prec)))
    else:
        t = '[%s]%s' % ('%.*', '|'.join(_EeFfGg))
        raise _ValueError(fmt=fmt, txt='not %r' % (t,))

    for o in objs:
        if force or isinstance(o, float):
            t = fmt % (float(o),)
            if ints and (isint(o, both=True) or  # for ...
                         # corner case testLcc lon0=-96.0
                         t.rstrip(_0_).endswith(_DOT_)):
                t = t.split(_DOT_)[0]
            elif prec > 1:
                t = fstrzs(t, ap1z=fGg)
        elif strepr:
            t = strepr(o)
        else:
            raise _IsnotError(_scalar_, floats=o)
        yield t
Exemple #3
0
def fpowers(x, n, alts=0):
    '''Return a series of powers M{[x**i for i=1..n]}.

       @arg x: Value (C{scalar}).
       @arg n: Highest exponent (C{int}).
       @kwarg alts: Only alternating powers, starting with
                    this exponent (C{int}).

       @return: Powers of B{C{x}} (C{float}[]).

       @raise TypeError: Non-scalar B{C{x}} or B{C{n}} not C{int}.

       @raise ValueError: Non-finite B{C{x}} or non-positive B{C{n}}.
    '''
    if not isfinite(x):
        raise _ValueError(x=x, txt=_not_(_finite_))
    if not isint(n):
        raise _IsnotError(int.__name__, n=n)
    elif n < 1:
        raise _ValueError(n=n)

    xs = [x]
    for _ in range(1, n):
        xs.append(xs[-1] * x)

    if alts > 0:  # x**2, x**4, ...
        # XXX PyChecker chokes on xs[alts-1::2]
        xs = xs[slice(alts - 1, None, 2)]

    # XXX PyChecker claims result is None
    return xs
Exemple #4
0
    def datum(self, datum):
        '''Set this cartesian's C{datum} I{without conversion}.

           @arg datum: New datum (L{Datum}).

           @raise TypeError: The B{C{datum}} is not a L{Datum}.
        '''
        _xinstanceof(Datum, datum=datum)
        d = self.datum
        if d is not None:
            if d.isEllipsoidal and not datum.isEllipsoidal:
                raise _IsnotError(_ellipsoidal_, datum=datum)
            elif d.isSpherical and not datum.isSpherical:
                raise _IsnotError(_spherical_, datum=datum)
            self._update(datum != d)
        self._datum = datum
Exemple #5
0
def _streprs(prec, objs, fmt, ints, force, strepr):
    '''(INTERNAL) Helper for C{fstr}, C{pairs}, C{reprs} and C{strs}
    '''
    # <https://docs.Python.org/3/library/stdtypes.html#printf-style-string-formatting>
    if fmt in _FfEeGg:
        fGg = fmt in _Gg
        fmt = NN(_PERCENT_, _DOT_, abs(prec), fmt)

    elif fmt.startswith(_PERCENT_):
        fGg = False
        try:  # to make sure fmt is valid
            f = fmt.replace(_DOTSTAR_, Fmt.DOT(abs(prec)))
            _ = f % (0.0, )
        except (TypeError, ValueError):
            raise _ValueError(fmt=fmt, txt=_not_(repr(_DOTSTAR_)))
        fmt = f

    else:
        raise _ValueError(fmt=fmt, txt=_not_(repr(_Fspec_)))

    for o in objs:
        if force or isinstance(o, float):
            t = fmt % (float(o), )
            if ints and (isint(o, both=True) or  # for ...
                         # corner case testLcc lon0=-96.0
                         t.rstrip(_0_).endswith(_DOT_)):
                t = t.split(_DOT_)[0]
            elif prec > 1:
                t = fstrzs(t, ap1z=fGg)
        elif strepr:
            t = strepr(o)
        else:
            raise _IsnotError(_scalar_, floats=o)
        yield t
Exemple #6
0
def _xUnits(units, Base=_NamedUnit):  # in .frechet, .hausdorff
    '''(INTERNAL) Set property C{units} as C{Unit} or C{Str}.
    '''
    if not issubclassof(Base, _NamedUnit):
        raise _IsnotError(_NamedUnit.__name__, Base=Base)
    elif issubclassof(units, Base):
        return units
    elif isstr(units):
        return Str(
            units,
            name=_units_)  # XXX Str to _Pass and for backward compatibility
    else:
        raise _IsnotError(Base.__name__,
                          Str.__name__,
                          str.__name__,
                          units=units)
Exemple #7
0
def pairs(items, prec=6, fmt=_Fmt, ints=False, sep=_EQUAL_):
    '''Convert items to I{name=value} strings, with C{float}s handled like L{fstr}.

       @arg items: Name-value pairs (C{dict} or 2-{tuple}s of any C{type}s).
       @kwarg prec: The C{float} precision, number of decimal digits (0..9).
                    Trailing zero decimals are stripped if B{C{prec}} is
                    positive, but kept for negative B{C{prec}} values.
       @kwarg fmt: Optional, float format (C{str}).
       @kwarg ints: Optionally, remove the decimal dot (C{bool}).
       @kwarg sep: Separator joining I{names} and I{values} (C{str}).

       @return: A C{tuple(sep.join(t) for t in zip(names, reprs(values,...)))}
                of C{str}s.
    '''
    try:
        if isinstance(items, dict):
            items = sorted(items.items())
        elif not isinstance(items, (list, tuple)):
            items = tuple(items)
        # can't unzip empty items tuple, list, etc.
        n, v = zip(*items) if items else ((), ())
    except (TypeError, ValueError):
        raise _IsnotError(dict.__name__, '2-tuples', items=items)
    v = _streprs(prec, v, fmt, ints, False, repr)
    return tuple(sep.join(t) for t in zip(map(str, n), v))
Exemple #8
0
def _xUnit(units, Base):  # in .frechet,  .hausdorff
    '''(INTERNAL) Get C{Unit} from C{Unit} or C{name}, ortherwise C{Base}.
    '''
    if not issubclassof(Base, _NamedUnit):
        raise _IsnotError(_NamedUnit.__name__, Base=Base)
    U = globals().get(units.capitalize(), Base) if isstr(units) else (
        units if issubclassof(units, Base) else Base)
    return U if issubclassof(U, Base) else Base
Exemple #9
0
def hausdorff_(model,
               target,
               both=False,
               early=True,
               seed=None,
               units=NN,
               distance=None,
               point=_point):
    '''Compute the C{directed} or C{symmetric} U{Hausdorff distance<https://
       WikiPedia.org/wiki/Hausdorff_distance>} between 2 sets of points with or
       without U{early breaking<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}
       and U{random sampling<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}.

       @arg model: First set of points (C{LatLon}[], C{Numpy2LatLon}[],
                   C{Tuple2LatLon}[] or C{other}[]).
       @arg target: Second set of points (C{LatLon}[], C{Numpy2LatLon}[],
                    C{Tuple2LatLon}[] or C{other}[]).
       @kwarg both: Return the C{directed} (forward only) or the C{symmetric}
                    (combined forward and reverse) C{Hausdorff} distance (C{bool}).
       @kwarg early: Enable or disable U{early breaking<https://Publik.TUWien.ac.AT/
                     files/PubDat_247739.pdf>} (C{bool}).
       @kwarg seed: Random sampling seed (C{any}) or C{None}, C{0} or C{False} for no
                    U{random sampling<https://Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}.
       @kwarg units: Optional, the distance units (C{Unit} or C{str}).
       @kwarg distance: Callable returning the distance between a B{C{model}}
                        and B{C{target}} point (signature C{(point1, point2)}).
       @kwarg point: Callable returning the B{C{model}} or B{C{target}} point
                     suitable for B{C{distance}} (signature C{(point)}).

       @return: A L{Hausdorff6Tuple}C{(hd, i, j, mn, md, units)}.

       @raise HausdorffError: Insufficient number of B{C{model}} or B{C{target}} points.

       @raise TypeError: If B{C{distance}} or B{C{point}} is not callable.
    '''
    if not callable(distance):
        raise _IsnotError(callable.__name__, distance=distance)
    if not callable(point):
        raise _IsnotError(callable.__name__, point=point)

    _, ps1 = points2(model, closed=False,
                     Error=HausdorffError)  # PYCHOK non-sequence
    _, ps2 = points2(target, closed=False,
                     Error=HausdorffError)  # PYCHOK non-sequence
    return _hausdorff_(ps1, ps2, both, early, seed, units, distance, point)
Exemple #10
0
def _Equidistant2(equidistant, datum):
    # (INTERNAL) Get an C{Equidistant} or C{EquidistantKarney} instance
    import pygeodesy.azimuthal as _az

    if equidistant is None or not callable(equidistant):
        equidistant = _az.equidistant
    elif not (issubclassof(equidistant, _az.Equidistant)
              or issubclassof(equidistant, _az.EquidistantKarney)):
        raise _IsnotError(_az.Equidistant.__name__,
                          _az.EquidistantKarney.__name__,
                          equidistant=equidistant)
    return equidistant(0, 0, datum)
Exemple #11
0
    def times(self, factor):
        '''Multiply this vector by a scalar.

           @arg factor: Scale factor (C{scalar}).

           @return: New, scaled vector (L{Vector3d}).

           @raise TypeError: Non-scalar B{C{factor}}.
        '''
        if not isscalar(factor):
            raise _IsnotError(_scalar_, factor=factor)
        return self.classof(self.x * factor, self.y * factor, self.z * factor)
Exemple #12
0
    def isfinite(obj):
        '''Check for C{Inf} and C{NaN} values.

           @arg obj: Value (C{scalar}).

           @return: C{False} if B{C{obj}} is C{INF} or C{NAN},
                    C{True} otherwise.

           @raise TypeError: Non-scalar B{C{obj}}.
        '''
        if not isscalar(obj):
            raise _IsnotError(isscalar.__name__, obj=obj)
        return not (isinf(obj) or isnan(obj))
Exemple #13
0
    def _xrenamed(self, inst):
        '''(INTERNAL) Rename the instance' C{.name = self.name}.

           @arg inst: The instance (C{_Named}).

           @return: The B{C{inst}}, named if not named before.
        '''
        if not isinstance(inst, _Named):
            raise _IsnotError(_valid_, inst=inst)

        if inst.name != self.name:
            inst.name = self.name
        return inst
Exemple #14
0
    def datum(self, datum):
        '''Set this point's datum I{without conversion}.

           @arg datum: New datum (L{Datum}).

           @raise TypeError: If B{C{datum}} is not a L{Datum}
                             or not spherical.
        '''
        _xinstanceof(Datum, datum=datum)
        if not datum.isSpherical:
            raise _IsnotError(_spherical_, datum=datum)
        self._update(datum != self._datum)
        self._datum = datum
Exemple #15
0
    def toDatum(self, datum):
        '''Convert this conic to the given datum.

           @arg datum: Ellipsoidal datum to use (L{Datum}, L{Ellipsoid},
                       L{Ellipsoid2} or L{a_f2Tuple}).

           @return: Converted conic, unregistered (L{Conic}).

           @raise TypeError: Non-ellipsoidal B{C{datum}}.
        '''
        d = _ellipsoidal_datum(datum, name=self.name)
        E = d.ellipsoid
        if not E.isEllipsoidal:
            raise _IsnotError(_ellipsoidal_, datum=datum)

        c = self
        if c._e != E.e or c._datum != d:

            c = Conic(None, 0, name=self._name)
            self._dup2(c)
            c._datum = d
            c._e = E.e

            if abs(c._par1 - c._par2) < EPS:
                m1 = c._mdef(c._phi0)
                t1 = c._tdef(c._phi0)
                t0 = t1
                k = 1  # _1_0
                n = sin(c._phi0)
                sp = 1
            else:
                m1 = c._mdef(c._par1)
                m2 = c._mdef(c._par2)
                t1 = c._tdef(c._par1)
                t2 = c._tdef(c._par2)
                t0 = c._tdef(c._phi0)
                k = c._k0
                n  = (log(m1) - log(m2)) \
                   / (log(t1) - log(t2))
                sp = 2

            F = m1 / (n * pow(t1, n))

            c._aF = k * E.a * F
            c._n = n
            c._n_ = _1_0 / n
            c._r0 = c._rdef(t0)
            c._SP = sp

        return c
Exemple #16
0
def frange(start, number, step=1):
    '''Generate a range of C{float}s.

       @arg start: First value (C{float}).
       @arg number: The number of C{float}s to generate (C{int}).
       @kwarg step: Increment value (C{float}).

       @return: A generator (C{float}s).

       @see: U{NumPy.prod<https://docs.SciPy.org/doc/
             numpy/reference/generated/numpy.arange.html>}.
    '''
    if not isint(number):
        raise _IsnotError(int.__name__, number=number)
    for i in range(number):
        yield start + i * step
Exemple #17
0
    def dividedBy(self, factor):
        '''Divide this vector by a scalar.

           @arg factor: The divisor (C{scalar}).

           @return: New, scaled vector (L{Vector3d}).

           @raise TypeError: Non-scalar B{C{factor}}.

           @raise VectorError: Invalid or zero B{C{factor}}.
        '''
        if not isscalar(factor):
            raise _IsnotError(_scalar_, factor=factor)
        try:
            return self.times(_1_0 / factor)
        except (ValueError, ZeroDivisionError) as x:
            raise VectorError(factor=factor, txt=str(x))
Exemple #18
0
def _spherical_datum(radius, name=NN, raiser=False):
    '''(INTERNAL) Create a L{Datum} from an L{Ellipsoid}, L{Ellipsoid2} or scalar earth C{radius}.
    '''
    try:
        d = _ellipsoidal_datum(radius, name=name)
    except TypeError:
        d = None
    if d is None:
        if not isscalar(radius):
            _xinstanceof(Datum,
                         Ellipsoid,
                         Ellipsoid2,
                         a_f2Tuple,
                         Scalar,
                         datum=radius)
        n = _UNDERSCORE_ + name
        r = Radius_(radius, Error=TypeError)
        E = Ellipsoid(r, r, name=n)
        d = Datum(E, transform=Transforms.Identity, name=n)
    elif raiser and not d.isSpherical:  # raiser if no spherical
        raise _IsnotError(_spherical_, datum=radius)
    return d
Exemple #19
0
def frechet_(points1, points2, distance=None, units=NN):
    '''Compute the I{discrete} U{Fréchet<https://WikiPedia.org/wiki/Frechet_distance>}
       distance between two paths given as sets of points.

       @arg points1: First set of points (C{LatLon}[], L{Numpy2LatLon}[],
                     L{Tuple2LatLon}[] or C{other}[]).
       @arg points2: Second set of points (C{LatLon}[], L{Numpy2LatLon}[],
                     L{Tuple2LatLon}[] or C{other}[]).
       @kwarg distance: Callable returning the distance between a B{C{points1}}
                        and a B{C{points2}} point (signature C{(point1, point2)}).
       @kwarg units: Optional, name of the distance units (C{str}).

       @return: A L{Frechet6Tuple}C{(fd, fi1, fi2, r, n, units)} where C{fi1}
                and C{fi2} are type C{int} indices into B{C{points1}} respectively
                B{C{points2}}.

       @raise FrechetError: Insufficient number of B{C{points1}} or B{C{points2}}.

       @raise RecursionError: Recursion depth exceeded, see U{sys.getrecursionlimit()
                              <https://docs.Python.org/3/library/sys.html#sys.getrecursionlimit>}.

       @raise TypeError: If B{C{distance}} is not a callable.

       @note: Function L{frechet_} does not support I{fractional} indices for
              intermediate B{C{points1}} and B{C{points2}}.
    '''
    if not callable(distance):
        raise _IsnotError(callable.__name__, distance=distance)

    n1, ps1 = _points2(points1, closed=False, Error=FrechetError)
    n2, ps2 = _points2(points2, closed=False, Error=FrechetError)

    def dF(i1, i2):
        return distance(ps1[i1], ps2[i2])

    return _frechet_(n1, 1, n2, 1, dF, units)
Exemple #20
0
def utmupsValidate(coord, falsed=False, MGRS=False, Error=UTMUPSError):
    '''Check a UTM or UPS coordinate.

       @arg coord: The UTM or UPS coordinate (L{Utm}, L{Ups} or C{5+Tuple}).
       @kwarg falsed: C{5+Tuple} easting and northing are falsed (C{bool}).
       @kwarg MGRS: Increase easting and northing ranges (C{bool}).
       @kwarg Error: Optional error to raise, overriding the default
                     (L{UTMUPSError}).

       @return: C{None} if validation passed.

       @raise Error: Validation failed.

       @see: Function L{utmupsValidateOK}.
    '''
    def _en(en, lo, hi, ename):  # U, Error
        try:
            if lo <= float(en) <= hi:
                return
        except (TypeError, ValueError):
            pass
        t = _SPACE_.join(
            (_outside_, U, _range_, '[%.0F' % (lo, ), '%.0F]' % (hi, )))
        raise Error(ename, en, txt=t)

    if isinstance(coord, (Ups, Utm)):
        hemi = coord.hemisphere
        enMM = coord.falsed
    elif isinstance(coord, (UtmUps5Tuple, UtmUps8Tuple)):
        hemi = coord.hemipole
        enMM = falsed
    else:
        raise _IsnotError(Error=Error,
                          coord=coord,
                          *map1(modulename, Utm, Ups, UtmUps5Tuple,
                                UtmUps8Tuple))
    band = coord.band
    zone = coord.zone

    z, B, h = _to3zBhp(zone, band, hemipole=hemi)

    if z == _UPS_ZONE:  # UPS
        import pygeodesy.ups as u  # PYCHOK expected
        U, M = _UPS_, _UpsMinMax
    else:  # UTM
        import pygeodesy.utm as u  # PYCHOK expected
        U, M = _UTM_, _UtmMinMax

    if MGRS:
        U, s = _MGRS_, _MGRS_TILE
    else:
        s = 0

    i = _NS_.find(h)
    if i < 0 or z < _UTMUPS_ZONE_MIN \
             or z > _UTMUPS_ZONE_MAX \
             or B not in u._Bands:
        t = '%s(%s%s %s)' % (U, z, B, h)
        raise Error(coord=t, zone=zone, band=band, hemisphere=hemi)

    if enMM:
        _en(coord.easting, M.eMin[i] - s, M.eMax[i] + s,
            _easting_)  # PYCHOK .eMax .eMin
        _en(coord.northing, M.nMin[i] - s, M.nMax[i] + s,
            _northing_)  # PYCHOK .nMax .nMin
Exemple #21
0
def _xStrError(*Refs, **name_value_Error):
    '''(INTERNAL) Create a C{TypeError} for C{Garef}, C{Geohash}, C{Wgrs}.
    '''
    r = tuple(r.__name__
              for r in Refs) + (Str.__name__, _LatLon_, 'LatLon*Tuple')
    return _IsnotError(*r, **name_value_Error)