Esempio n. 1
0
def _to3zBll(lat, lon, cmoff=True):
    '''(INTERNAL) Return zone, Band and lat- and (central) longitude in degrees.

       @arg lat: Latitude (C{degrees}).
       @arg lon: Longitude (C{degrees}).
       @kwarg cmoff: Offset B{C{lon}} from zone's central meridian.

       @return: 4-Tuple (zone, Band, lat, lon).
    '''
    z, lat, lon = _to3zll(lat, lon)  # in .utmupsBase

    if _UTM_LAT_MIN > lat or lat >= _UTM_LAT_MAX:  # [-80, 84) like Veness
        r = _range_(_UTM_LAT_MIN, _UTM_LAT_MAX, ropen=True)
        t = _SPACE_(_outside_, _UTM_, _range_, r)
        raise RangeError(lat=degDMS(lat), txt=t)
    B = _Bands[int(lat + 80) >> 3]

    x = lon - _cmlon(z)  # z before Norway/Svaldbard
    if abs(x) > _UTM_ZONE_OFF_MAX:
        t = _SPACE_(_outside_, _UTM_, _zone_, str(z), _by_, degDMS(x, prec=6))
        raise RangeError(lon=degDMS(lon), txt=t)

    if B == _X_:  # and 0 <= int(lon) < 42: z = int(lon + 183) // 6 + 1
        x = {32: 9, 34: 21, 36: 33}.get(z, None)
        if x:  # Svalbard
            z += 1 if lon >= x else -1
    elif B == _V_ and z == 31 and lon >= 3:
        z += 1  # SouthWestern Norway

    if cmoff:  # lon off central meridian
        lon -= _cmlon(z)  # z after Norway/Svaldbard
    return Zone(z), Band(B), Lat(lat), Lon(lon)
Esempio n. 2
0
    def __imul__(self, other):
        '''Multiply this instance by a scalar or an other instance.

           @arg other: L{Fsum} instance or C{scalar}.

           @return: This instance, updated (L{Fsum}).

           @raise TypeError: Invalid B{C{other}} type.

           @see: Method L{Fsum.fmul}.
        '''
        if isscalar(other):
            self.fmul(other)
        elif isinstance(other, Fsum):
            ps = list(other._ps)  # copy
            if ps:
                s = self.fcopy()
                self.fmul(ps.pop())
                while ps:  # self += s * ps.pop()
                    p = s.fcopy()
                    p.fmul(ps.pop())
                    self.fadd(p._ps)
            else:
                self._ps = []  # zero
                self._fsum2_ = None
        else:
            raise _TypeError(_SPACE_(self, '*=', repr(other)))
        return self
Esempio n. 3
0
def _reframeTransforms(rf2, rf, epoch):
    '''(INTERNAL) Get 0, 1 or 2 Helmert C{Transforms} to convert
       reference frame C{rf} observed at C{epoch} into C{rf2}.
    '''
    n2 = rf2.name  # .upper()
    n1 = rf.name  # .upper()
    if n1 == n2 or (n1.startswith(_S.ITRF) and n2.startswith(_S.WGS84)) \
                or (n2.startswith(_S.ITRF) and n1.startswith(_S.WGS84)):
        return ()  # PYCHOK returns

    if (n1, n2) in _trfXs:
        return (_2Transform((n1, n2), epoch, _Forward), )  # PYCHOK returns

    if (n2, n1) in _trfXs:
        return (_2Transform((n2, n1), epoch, _Reverse), )  # PYCHOK returns

    n = _intermediate(n1, n2)
    if n:
        return (
            _2Transform((n1, n), epoch, _Forward),  # PYCHOK returns
            _2Transform((n, n2), epoch, _Forward))

    n = _intermediate(n2, n1)
    if n:
        return (
            _2Transform((n, n1), epoch, _Reverse),  # PYCHOK returns
            _2Transform((n2, n), epoch, _Reverse))

    t = _SPACE_(RefFrame.__name__, repr(n1), _to_, repr(n2))
    raise TRFError(_no_(_conversion_), txt=t)
Esempio n. 4
0
def upsZoneBand5(lat, lon, strict=True):
    '''Return the UTM/UPS zone number, (polar) Band letter, pole and
       clipped lat- and longitude for a given location.

       @arg lat: Latitude in degrees (C{scalar} or C{str}).
       @arg lon: Longitude in degrees (C{scalar} or C{str}).
       @kwarg strict: Restrict B{C{lat}} to UPS ranges (C{bool}).

       @return: A L{UtmUpsLatLon5Tuple}C{(zone, band, hemipole,
                lat, lon)} where C{hemipole} is the C{'N'|'S'} pole,
                the UPS projection top/center.

       @raise RangeError: If B{C{strict}} and B{C{lat}} in the UTM
                          and not the UPS range or if B{C{lat}} or
                          B{C{lon}} outside the valid range and
                          L{rangerrors} set to C{True}.

       @raise ValueError: Invalid B{C{lat}} or B{C{lon}}.
    '''
    z, lat, lon = _to3zll(*parseDMS2(lat, lon))
    if lat < _UPS_LAT_MIN:  # includes 30' overlap
        z, B, p = _UPS_ZONE, _Band(lat, lon), _S_

    elif lat > _UPS_LAT_MAX:  # includes 30' overlap
        z, B, p = _UPS_ZONE, _Band(lat, lon), _N_

    elif strict:
        r = _range_(_UPS_LAT_MIN, _UPS_LAT_MAX)
        t = _SPACE_(_inside_, _UTM_, _range_, r)
        raise RangeError(lat=degDMS(lat), txt=t)

    else:
        B, p = NN, _hemi(lat)
    return UtmUpsLatLon5Tuple(z, B, p, lat, lon, Error=UPSError)
Esempio n. 5
0
def _xkwds_Error(_xkwds_func, kwds, name_txt, txt='default'):
    # Helper for _xkwds_get and _xkwds_pop below
    from pygeodesy.streprs import Fmt, pairs
    f = _COMMASPACE_.join(pairs(kwds) + pairs(name_txt))
    f = Fmt.PAREN(_xkwds_func.__name__, f)
    t = _multiple_ if name_txt else _no_
    t = _SPACE_(t, _EQUAL_(_name_, txt), 'kwargs')
    return _AssertionError(f, txt=t)
Esempio n. 6
0
 def _en(en, lo, hi, ename):  # U, Error
     try:
         if lo <= float(en) <= hi:
             return
     except (TypeError, ValueError):
         pass
     t = _SPACE_(_outside_, U, _range_, _range_(lo, hi))
     raise Error(ename, en, txt=t)
Esempio n. 7
0
 def _immutable(inst, value):
     '''Throws an C{AttributeError}, always.
     '''
     from pygeodesy.named import classname
     s = _DOT_(repr(inst), self.name)
     s = _EQUALSPACED_(s, repr(value))
     t = _SPACE_(_immutable_, classname(self))
     raise _AttributeError(s, txt=t)
Esempio n. 8
0
def _callname(name, class_name, self_name, up=1):  # imported by .points
    '''(INTERNAL) Assemble the name for an invokation.
    '''
    n, c = class_name, callername(up=up + 1)
    if c:
        n = _DOT_(n, Fmt.PAREN(c, name))
    if self_name:
        n = _SPACE_(n, repr(self_name))
    return n
Esempio n. 9
0
 def _xtend(self, xTuple, *items):
     '''(INTERNAL) Extend this C{Named-Tuple} with C{items} to an other B{C{xTuple}}.
     '''
     if not (issubclassof(xTuple, _NamedTuple) and
             (len(self._Names_) + len(items)) == len(xTuple._Names_)
             and self._Names_ == xTuple._Names_[:len(self)]):
         c = NN(self.classname, repr(self._Names_))
         x = NN(xTuple.__name__, repr(xTuple._Names_))
         raise TypeError(_SPACE_(c, _vs_, x))
     return self._xnamed(xTuple(*(self + items)))
Esempio n. 10
0
def _datum_datum(datum1, datum2, Error=None):
    '''(INTERNAL) Check for datum or ellipsoid match.
    '''
    if Error:
        E1, E2 = datum1.ellipsoid, datum2.ellipsoid
        if E1 != E2:
            raise Error(E2.named2, txt=_incompatible(E1.named2))
    elif datum1 != datum2:
        t = _SPACE_(_datum_, repr(datum1.name), _not_, repr(datum2.name))
        raise _AssertionError(t)
Esempio n. 11
0
 def _txt(c1, r1, c2, r2):
     # check for concentric or too distant spheres
     d = c1.minus(c2).length
     if d < abs(r1 - r2):
         t = _near_concentric_
     elif d > (r1 + r2):
         t = _too_(Fmt.distant(d))
     else:
         return NN
     return _SPACE_(c1.name, 'and', c2.name, t)
Esempio n. 12
0
def _or(*words):
    '''(INTERNAL) Join C{words} with C{", "} and C{" or "}.
    '''
    t, w = NN, list(words)
    if w:
        t = w.pop()
        if w:
            w = _COMMASPACE_.join(w)
            t = _SPACE_(w, _or_, t)
    return t
Esempio n. 13
0
def _boolkwds(inst, **name_value_pairs):  # in .frechet, .hausdorff, .heights
    '''(INTERNAL) Set applicable C{bool} properties/attributes.
    '''
    for n, v in name_value_pairs.items():
        b = getattr(inst, n, None)
        if b is None:  # invalid bool attr
            t = _SPACE_(_EQUAL_(n, repr(v)), 'for',
                        inst.__class__.__name__)  # XXX .classname
            raise _AttributeError(t, txt=_not_('applicable'))
        if v in (False, True) and v != b:
            setattr(inst, NN(_UNDER_, n), v)
Esempio n. 14
0
def _xversion(package, where, *required):  # in .karney
    '''(INTERNAL) Check the C{package} version vs B{C{required}}.
    '''
    t = map2(int, package.__version__.split(_DOT_)[:2])
    if t < required:
        from pygeodesy.named import modulename as mn
        t = _SPACE_(package.__name__, _version_, _DOT_.join(map2(str, t)),
                    'below', _DOT_.join(map2(str, required)), 'required', _by_,
                    mn(where, True))
        raise ImportError(t)
    return package
Esempio n. 15
0
    def trilaterate5(
            self,
            distance1,
            point2,
            distance2,
            point3,
            distance3,  # PYCHOK signature
            area=False,
            eps=EPS1,
            radius=R_M,
            wrap=False):
        '''B{Not implemented} for C{B{area}=True} or C{B{wrap}=True}
           and falls back to method C{trilaterate} otherwise.

           @return: A L{Trilaterate5Tuple}C{(min, minPoint, max, maxPoint, n)}
                    with a single trilaterated intersection C{minPoint I{is}
                    maxPoint}, C{min I{is} max} the nearest intersection
                    margin and count C{n = 1}.

           @raise IntersectionError: No intersection, trilateration failed.

           @raise NotImplementedError: Keyword argument C{B{area}=True} or
                                       B{C{wrap}=True} not (yet) supported.

           @raise TypeError: Invalid B{C{point2}} or B{C{point3}}.

           @raise ValueError: Some B{C{points}} coincide or invalid B{C{distance1}},
                              B{C{distance2}}, B{C{distance3}} or B{C{radius}}.
        '''
        if area or wrap:
            from pygeodesy.named import notImplemented
            notImplemented(self, self.trilaterate5, area=area, wrap=wrap)

        t = _trilaterate(self,
                         distance1,
                         self.others(point2=point2),
                         distance2,
                         self.others(point3=point3),
                         distance3,
                         radius=radius,
                         height=None,
                         useZ=True,
                         LatLon=self.classof)
        # ... and handle B{C{eps}} and C{IntersectionError} as
        # method C{.latlonBase.LatLonBase.trilaterate2}
        d = self.distanceTo(t, radius=radius, wrap=wrap)  # PYCHOK distanceTo
        d = abs(distance1 - d), abs(distance2 - d), abs(distance3 - d)
        d = float(min(d))
        if d < eps:  # min is max, minPoint is maxPoint
            return Trilaterate5Tuple(d, t, d, t, 1)  # n = 1
        t = _SPACE_(_no_(_intersection_),
                    Fmt.PAREN(min.__name__, Fmt.f(d, prec=3)))
        raise IntersectionError(area=area, eps=eps, wrap=wrap, txt=t)
Esempio n. 16
0
def _error_init(Error,
                inst,
                name_value,
                fmt_name_value='%s (%r)',
                txt=_invalid_,
                **name_values):  # by .lazily
    '''(INTERNAL) Format an error text and initialize an C{Error} instance.

       @arg Error: The error super-class (C{Exception}).
       @arg inst: Sub-class instance to be initialized (C{_Exception}).
       @arg name_value: Either just a value or several name, value, ...
                        positional arguments (C{str}, any C{type}), in
                        particular for name conflicts with keyword
                        arguments of C{error_init} or which can't be
                        used as C{name=value} keyword arguments.
       @kwarg name_value_fmt: Format for (name, value) (C{str}).
       @kwarg txt: Optional explanation of the error (C{str}).
       @kwarg name_values: One or more B{C{name=value}} pairs overriding
                           any B{C{name_value}} positional arguments.
    '''
    if name_values:
        t = _or(*sorted(fmt_name_value % t for t in name_values.items()))
    elif len(name_value) > 1:
        t = _or(*sorted(fmt_name_value % t
                        for t in zip(name_value[0::2], name_value[1::2])))
    elif name_value:
        t = str(name_value[0])
    else:
        t = _SPACE_(_name_value_, str(MISSING))

    if txt is None:
        x = NN
    else:
        x = str(txt) or _invalid_
        c = _COMMA_ if _COLON_ in t else _COLON_
        t = _SPACE_(t + c, x)
    Error.__init__(inst, t)
    #   inst.__x_txt__ = x  # hold explanation
    _error_chain(inst)  # no Python 3+ exception chaining
    _error_under(inst)
Esempio n. 17
0
    def __init__(self, *name_n_corners, **txt):
        '''New L{ClipError}.

           @arg name_n_corners: Either just a name (C{str}) or
                                name, number, corners (C{str},
                                C{int}, C{tuple}).
           @kwarg txt: Optional explanation of the error (C{str}).
        '''
        if len(name_n_corners) == 3:
            t, n, v = name_n_corners
            n = _SPACE_(t, 'clip', 'box' if n == 2 else 'region')
            name_n_corners = n, v
        _ValueError.__init__(self, *name_n_corners, **txt)
Esempio n. 18
0
    def unregister(self):
        '''Remove this instance from its C{_NamedEnum} registry.

           @raise AssertionError: Mismatch of this and registered item.

           @raise NameError: This item is unregistered.
        '''
        enum = self._enum
        if enum and self.name and self.name in enum:
            item = enum.unregister(self.name)
            if item is not self:
                t = _SPACE_(repr(item), _vs_, repr(self))
                raise _AssertionError(t)
Esempio n. 19
0
    def __init__(self, where, **lens_txt):  # txt=None
        '''New L{LenError}.

           @arg where: Object with C{.__name__} attribute
                       (C{class}, C{method}, or C{function}).
           @kwarg lens_txt: Two or more C{name=len(name)} pairs
                            (C{keyword arguments}).
        '''
        from pygeodesy.streprs import Fmt as _Fmt
        x = _xkwds_pop(lens_txt, txt=_invalid_)
        ns, vs = zip(*sorted(lens_txt.items()))
        ns = _COMMASPACE_.join(ns)
        vs = ' vs '.join(map(str, vs))
        t = _SPACE_(_Fmt.PAREN(where.__name__, ns), _len_, vs)
        _ValueError.__init__(self, t, txt=x)
Esempio n. 20
0
    def toUps(self, pole=NN, **unused):
        '''Duplicate this UPS coordinate.

           @kwarg pole: Optional top/center of the UPS projection,
                        (C{str}, 'N[orth]'|'S[outh]').

           @return: A copt of this UPS coordinate (L{Ups}).

           @raise UPSError: Invalid B{C{pole}} or attempt to transfer
                            the projection top/center.
        '''
        if self.pole == pole or not pole:
            return self.copy()
        t = _SPACE_(_pole_, repr(self.pole), _to_, repr(pole))
        raise UPSError('no transfer', txt=t)
Esempio n. 21
0
    def __iadd__(self, other):
        '''Add a scalar or an other instance to this instance.

           @arg other: L{Fsum} instance or C{scalar}.

           @return: This instance, updated (L{Fsum}).

           @raise TypeError: Invalid B{C{other}} type.

           @see: Method L{Fsum.fadd}.
        '''
        if isscalar(other):
            self.fadd_(other)
        elif other is self:
            self.fmul(2)
        elif isinstance(other, Fsum):
            self.fadd(other._ps)
        else:
            raise _TypeError(_SPACE_(self, '+=', repr(other)))
        return self
Esempio n. 22
0
    def __isub__(self, other):
        '''Subtract a scalar or an other instance from this instance.

           @arg other: L{Fsum} instance or C{scalar}.

           @return: This instance, updated (L{Fsum}).

           @raise TypeError: Invalid B{C{other}} type.

           @see: Method L{Fsum.fadd}.
        '''
        if isscalar(other):
            self.fadd_(-other)
        elif other is self:
            self._ps = []  # zero
            self._fsum2_ = None
        elif isinstance(other, Fsum):
            self.fadd(-p for p in other._ps)
        else:
            raise _TypeError(_SPACE_(self, '-=', repr(other)))
        return self
Esempio n. 23
0
    def convertRefFrame(self, reframe2):
        '''Convert this point to an other reference frame.

           @arg reframe2: Reference frame to convert I{to} (L{RefFrame}).

           @return: The converted point (ellipsoidal C{LatLon}) or
                    this point if conversion is C{nil}.

           @raise TRFError: No B{C{.reframe}} or no conversion
                            available from B{C{.reframe}} to
                            B{C{reframe2}}.

           @raise TypeError: The B{C{reframe2}} is not a L{RefFrame}.

           @example:

           >>> p = LatLon(51.4778, -0.0016, reframe=RefFrames.ETRF2000)  # default Datums.WGS84
           >>> p.convertRefFrame(RefFrames.ITRF2014)  # 51.477803°N, 000.001597°W, +0.01m
        '''
        from pygeodesy.trf import RefFrame, _reframeTransforms
        _xinstanceof(RefFrame, reframe2=reframe2)

        if not self.reframe:
            t = _SPACE_(_DOT_(repr(self), 'reframe'), MISSING)
            raise TRFError(_no_(_conversion_), txt=t)

        ts = _reframeTransforms(reframe2, self.reframe, self.epoch)
        if ts:
            c = self.toCartesian()
            for t in ts:
                c = c._applyHelmert(t, False)
            ll = c.toLatLon(datum=self.datum,
                            LatLon=self.classof,
                            epoch=self.epoch,
                            reframe=reframe2)
            # ll.reframe, ll.epoch = reframe2, self.epoch
        else:
            ll = self
        return ll
Esempio n. 24
0
def _IsnotError(*nouns, **name_value_Error):  # name=value [, Error=TypeeError]
    '''Create a C{TypeError} for an invalid C{name=value} type.

       @arg nouns: One or more expected class or type names,
                   usually nouns (C{str}).
       @kwarg name_value_Error: One B{C{name=value}} pair and
                                optionally, an B{C{Error=...}}
                                keyword argument to override
                                the default B{C{Error=TypeError}}.

       @return: A C{TypeError} or an B{C{Error}} instance.
    '''
    from pygeodesy.streprs import Fmt as _Fmt
    Error = _xkwds_pop(name_value_Error, Error=TypeError)
    n, v = _xkwds_popitem(name_value_Error) if name_value_Error else (
        _name_value_, MISSING)  # XXX else tuple(...)
    t = _or(*nouns) or _specified_
    if len(nouns) > 1:
        t = _an(t)
    e = Error(_SPACE_(n, _Fmt.PAREN(repr(v)), _not_, t))
    _error_chain(e)
    _error_under(e)
    return e
Esempio n. 25
0
 def _error(arg):
     n = _DOT_(Fstr.__name__, self.name or self)
     return _SPACE_(n, _PERCENT_, repr(arg))
Esempio n. 26
0
def _an(noun):
    '''(INTERNAL) Prepend an article to a noun based
       on the pronounciation of the first letter.
    '''
    return _SPACE_((_an_ if noun[:1].lower() in 'aeinoux' else _a_), noun)
Esempio n. 27
0
 def _split2(g, name, _2m):
     i = max(g.find(name[0]), g.rfind(name[0]))
     if i > _BaseLen:
         return g[:i], _2m(int(g[i + 1:]), _SPACE_(georef, name))
     else:
         return g, None
Esempio n. 28
0
def _invokationError(name, *args):  # PYCHOK no cover
    '''(INTERNAL) Return an L{EllipticError}.
    '''
    return EllipticError(_SPACE_('invokation', NN(name, repr(args))))  # unstr
Esempio n. 29
0
def _convergenceError(where, *args):  # PYCHOK no cover
    '''(INTERNAL) Return an L{EllipticError}.
    '''
    t = _SPACE_(where.__name__, repr(args))
    return EllipticError(_no_(_convergence_), txt=t)  # unstr
Esempio n. 30
0
    def _inverse(self, other, azis, wrap):
        '''(INTERNAL) Inverse Vincenty method.

           @raise TypeError: The B{C{other}} point is not L{LatLon}.

           @raise ValueError: If this and the B{C{other}} point's L{Datum}
                              ellipsoids are not compatible.

           @raise VincentyError: Vincenty fails to converge for the current
                                 L{LatLon.epsilon} and L{LatLon.iterations}
                                 limit and/or if this and the B{C{other}}
                                 point are coincident or near-antipodal.
        '''
        E = self.ellipsoids(other)

        c1, s1, _ = _r3(self.lat, E.f)
        c2, s2, _ = _r3(other.lat, E.f)

        c1c2, s1c2 = c1 * c2, s1 * c2
        c1s2, s1s2 = c1 * s2, s1 * s2

        dl, _ = unroll180(self.lon, other.lon, wrap=wrap)
        ll = dl = radians(dl)
        for self._iteration in range(1, self._iterations + 1):
            ll_ = ll
            sll, cll = sincos2(ll)

            ss = hypot(c2 * sll, c1s2 - s1c2 * cll)
            if ss < EPS:  # coincident or antipodal, ...
                if self.isantipodeTo(other, eps=self._epsilon):
                    t = '%r %sto %r' % (self, _antipodal_, other)
                    raise VincentyError(_ambiguous_, txt=t)
                # return zeros like Karney, but unlike Veness
                return Distance3Tuple(0.0, 0, 0)

            cs = s1s2 + c1c2 * cll
            s = atan2(ss, cs)

            sa = c1c2 * sll / ss
            c2a = 1 - sa**2
            if abs(c2a) < EPS:
                c2a = 0  # equatorial line
                ll = dl + E.f * sa * s
            else:
                c2sm = cs - 2 * s1s2 / c2a
                ll = dl + _dl(E.f, c2a, sa, s, cs, ss, c2sm)

            if abs(ll - ll_) < self._epsilon:
                break


#           # omitted and applied only after failure to converge below, see footnote
#           # under Inverse at <https://WikiPedia.org/wiki/Vincenty's_formulae>
#           # <https://GitHub.com/ChrisVeness/geodesy/blob/master/latlon-vincenty.js>
#           elif abs(ll) > PI and self.isantipodeTo(other, eps=self._epsilon):
#              raise VincentyError('%s, %r %sto %r' % ('ambiguous', self,
#                                  _antipodal_, other))
        else:
            t = _antipodal_ if self.isantipodeTo(other,
                                                 eps=self._epsilon) else NN
            t = _SPACE_(repr(self), NN(t, _to_), repr(other))
            raise VincentyError(_no_(_convergence_), txt=t)

        if c2a:  # e22 == (a / b)**2 - 1
            A, B = _p2(c2a * E.e22)
            s = A * (s - _ds(B, cs, ss, c2sm))

        b = E.b
        #       if self.height or other.height:
        #           b += self._havg(other)
        d = b * s

        if azis:  # forward and reverse azimuth
            sll, cll = sincos2(ll)
            f = atan2b(c2 * sll, c1s2 - s1c2 * cll)
            r = atan2b(c1 * sll, -s1c2 + c1s2 * cll)
        else:
            f = r = 0
        return Distance3Tuple(d, f, r)