def _sigmaInv(self, xi, eta): '''(INTERNAL) Invert C{sigma} using Newton's method. @return: 2-Tuple C{(u, v)}. @see: C{void TMExact::sigmainv(real xi, real eta, real &u, real &v)}. @raise EllipticError: No convergence. ''' u, v, trip = self._sigmaInv0(xi, eta) if trip: self._iteration = 0 else: U, V = Fsum(u), Fsum(v) # min iterations = 2, max = 7, mean = 3.9 for self._iteration in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC sncndn6 = self._sncndn6(u, v) X, E, _ = self._sigma3(v, *sncndn6) dw, dv = self._sigmaDwd( *sncndn6) X = xi - X E -= eta u, du = U.fsum2_(X * dw, E * dv) v, dv = V.fsum2_(X * dv, -E * dw) if trip: break trip = hypot2(du, dv) < _TOL_10 else: t = unstr(self._sigmaInv.__name__, xi, eta) raise EllipticError(_no_convergence_, txt=t) return u, v
def _zetaInv(self, taup, lam): '''(INTERNAL) Invert C{zeta} using Newton's method. @return: 2-Tuple C{(u, v)}. @see: C{void TMExact::zetainv(real taup, real lam, real &u, real &v)}. @raise EllipticError: No convergence. ''' psi = asinh(taup) sca = 1.0 / hypot1(taup) u, v, trip = self._zetaInv0(psi, lam) if trip: self._iteration = 0 else: stol2 = _TOL_10 / max(psi**2, 1.0) U, V = Fsum(u), Fsum(v) # min iterations = 2, max = 6, mean = 4.0 for self._iteration in range(1, _TRIPS): # GEOGRAPHICLIB_PANIC sncndn6 = self._sncndn6(u, v) T, L, _ = self._zeta3( *sncndn6) dw, dv = self._zetaDwd(*sncndn6) T = (taup - T) * sca L -= lam u, du = U.fsum2_(T * dw, L * dv) v, dv = V.fsum2_(T * dv, -L * dw) if trip: break trip = hypot2(du, dv) < stol2 else: t = unstr(self._zetaInv.__name__, taup, lam) raise EllipticError(_no_convergence_, txt=t) return u, v
def __init__(self, a_ellipsoid, f, name): '''(INTERNAL) New C{Ecef...}. ''' try: E = a_ellipsoid if f is None: if isinstance(E, Datum): self._datum = E E = E.ellipsoid elif not isinstance(E, Ellipsoid): raise TypeError if not name: name = E.name elif isscalar(E) and isscalar(f): a = float(E) f_ = (1.0 / f) if f else 0 # sphere b = None if f_ else a E = Ellipsoid(a, b, f_, name='_' + name) else: raise ValueError if not (E.a > 0 and E.f < 1): raise ValueError except (TypeError, ValueError): t = unstr(self.classname, a=E, f=f) raise EcefError('%s invalid: %s' % ('ellipsoid', t)) self._E = E if name: self.name = name
def _notError(inst, name, args, kwds): # PYCHOK no cover '''(INTERNAL) Format an error message. ''' n = _DOT_(classname(inst, prefixed=True), _dunder_name(name, name)) m = _COMMASPACE_.join( modulename(c, prefixed=True) for c in inst.__class__.__mro__[1:-1]) return _COMMASPACE_(unstr(n, *args, **kwds), Fmt.PAREN(_MRO_, m))
def _notError(inst, name, args, kwds): # PYCHOK no cover '''(INTERNAL) Format an error message. ''' n = _dot_(classname(inst, prefixed=True), _dunder_name(name, name)) m = _COMMA_SPACE_.join( modulename(c, prefixed=True) for c in inst.__class__.__mro__[1:-1]) t = '%s, MRO(%s)' % (unstr(n, *args, **kwds), m) return t
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#equirectangular>}. This approximation is valid for short distance of several hundred Km or Miles, see the B{C{limit}} keyword argument and the L{LimitError}. @arg lat1: Start latitude (C{degrees}). @arg lon1: Start longitude (C{degrees}). @arg lat2: End latitude (C{degrees}). @arg lon2: End longitude (C{degrees}). @kwarg adjust: Adjust the wrapped, unrolled longitudinal delta by the cosine of the mean latitude (C{bool}). @kwarg limit: Optional limit for lat- and longitudinal deltas (C{degrees}) or C{None} or C{0} for unlimited. @kwarg 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{cosineAndoyerLambert}, L{cosineForsytheAndoyerLambert}, L{cosineLaw}, L{euclidean}, L{flatLocal}/L{hubeny}, L{flatPolar}, L{haversine}, L{thomas} 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 = unstr(equirectangular_.__name__, lat1, lon1, lat2, lon2, limit=limit) raise LimitError('delta exceeds limit', txt=t) if adjust: # scale delta lon d_lon *= _scale_deg(lat1, lat2) d2 = hypot2(d_lat, d_lon) # degrees squared! return Distance4Tuple(d2, d_lat, d_lon, ulon2 - lon2)
def _2sum(a, b): # by .testFmath '''(INTERNAL) Precision C{2sum} of M{a + b}. ''' s = a + b if not isfinite(s): raise _OverflowError(unstr(_2sum.__name__, a, b), txt=str(s)) if abs(a) < abs(b): a, b = b, a return s, b - (s - a)
def __init__(self, *args, **kwds): if args: # args override kwds if len(args) != 1: t = unstr(self.classname, *args, **kwds) raise _ValueError(args=len(args), txt=t) kwds = _xkwds(dict(args[0]), **kwds) if _name_ in kwds: _Named.name.fset(self, kwds.pop(_name_)) # see _Named.name dict.__init__(self, kwds)
def __init__(self, *args, **kwds): if args: # args override kwds if len(args) != 1: t = unstr(self.classname, *args, **kwds) raise ValueError('invalid: ' + t) kwds.update(dict(args[0])) if _NAME_ in kwds: _Named.name.fset(self, kwds.pop(_NAME_)) # see _Named.name dict.__init__(self, kwds)
def __new__(cls, *args): '''New L{_NamedTuple} initialized with B{C{positional}} arguments. ''' self = tuple.__new__(cls, args) ns = self._Names_ if not (isinstance(ns, tuple) and len(ns) > 1): # XXX > 0 raise _TypeError(_dot_(self.classname, _Names_), ns) if len(ns) != len(args) or not ns: raise LenError(cls, args=len(args), ns=len(ns)) if _name_ in ns: t = unstr(_dot_(self.classname, _Names_), *ns) raise _NameError(_name_, _name_, txt=t) return self
def notOverloaded(inst, name, *args, **kwds): # PYCHOK no cover '''Raise an C{AssertionError} for a method or property not overloaded. @arg name: Method, property or name (C{str}). @arg args: Method or property positional arguments (any C{type}s). @arg kwds: Method or property keyword arguments (any C{type}s). ''' n = getattr(name, '__name__', name) n = '%s %s' % (notOverloaded.__name__, _dot_(classname(inst, prefixed=True), n)) m = ', '.join( modulename(c, prefixed=True) for c in inst.__class__.__mro__[1:-1]) raise AssertionError('%s, MRO(%s)' % (unstr(n, *args, **kwds), m))
def unStr(name, *args, **kwds): '''DEPRECATED, use function L{unstr}. ''' from pygeodesy.streprs import unstr return unstr(name, *args, **kwds)
def _xkwds_Error(_xkwds_func, kwds, name_default): from pygeodesy.streprs import unstr t = unstr(_xkwds_func.__name__, kwds, **name_default) n = ('multiple ' if name_default else 'no ') + _name_ return _AssertionError(t, txt=n + '=default kwargs')
def _trilaterate(point1, distance1, point2, distance2, point3, distance3, radius=R_M, height=None, useZ=False, **LatLon_LatLon_kwds): # (INTERNAL) Locate a point at given distances from # three other points, see LatLon.triangulate above def _nd2(p, d, r, _i_, *qs): # .toNvector and angular distance squared for q in qs: if p.isequalTo(q, EPS): raise _ValueError(points=p, txt=_coincident_) return p.toNvector(), (Scalar(d, name=_distance_ + _i_) / r)**2 r = Radius_(radius) n1, r12 = _nd2(point1, distance1, r, _1_) n2, r22 = _nd2(point2, distance2, r, _2_, point1) n3, r32 = _nd2(point3, distance3, r, _3_, point1, point2) # the following uses x,y coordinate system with origin at n1, x axis n1->n2 y = n3.minus(n1) x = n2.minus(n1) z = None d = x.length # distance n1->n2 if d > EPS_2: # and y.length > EPS_2: X = x.unit() # unit vector in x direction n1->n2 i = X.dot(y) # signed magnitude of x component of n1->n3 Y = y.minus(X.times(i)).unit() # unit vector in y direction j = Y.dot(y) # signed magnitude of y component of n1->n3 if abs(j) > EPS_2: # courtesy Carlos Freitas <https://GitHub.com/mrJean1/PyGeodesy/issues/33> x = fsum_(r12, -r22, d**2) / (2 * d) # n1->intersection x- and ... y = fsum_(r12, -r32, i**2, j**2, -2 * x * i) / ( 2 * j) # ... y-component # courtesy AleixDev <https://GitHub.com/mrJean1/PyGeodesy/issues/43> z = fsum_(max(r12, r22, r32), -(x**2), -(y**2)) # XXX not just r12! if z > EPS: n = n1.plus(X.times(x)).plus(Y.times(y)) if useZ: # include Z component Z = X.cross(Y) # unit vector perpendicular to plane n = n.plus(Z.times(sqrt(z))) if height is None: h = fidw((point1.height, point2.height, point3.height), map1(fabs, distance1, distance2, distance3)) else: h = Height(height) kwds = _xkwds(LatLon_LatLon_kwds, height=h) return n.toLatLon(** kwds) # Nvector(n.x, n.y, n.z).toLatLon(...) # no intersection, d < EPS_2 or abs(j) < EPS_2 or z < EPS t = NN(_no_, _intersection_, _SPACE_) raise IntersectionError(point1=point1, distance1=distance1, point2=point2, distance2=distance2, point3=point3, distance3=distance3, txt=unstr(t, z=z, useZ=useZ))