Example #1
0
def frechet_(points1, points2, distance=None, units=''):
    '''Compute the I{discrete} U{Fréchet<https://WikiPedia.org/wiki/Frechet_distance>}
       distance between two paths given as sets of points.

       @param points1: First set of points (C{LatLon}[], C{Numpy2LatLon}[],
                       C{Tuple2LatLon}[] or C{other}[]).
       @param points2: Second set of points (C{LatLon}[], C{Numpy2LatLon}[],
                       C{Tuple2LatLon}[] or C{other}[]).
       @keyword distance: Callable returning the distance between a B{C{points1}}
                          and a B{C{points2}} point (signature C{(point1, point2)}).
       @keyword 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: Keyword C{fraction}, intermediate B{C{points1}} and B{C{points2}}
              and I{fractional} indices are I{not} supported in this L{frechet_}
              function.
    '''
    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)
Example #2
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 _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))
            y *= E.a
            x *= E.a / r
        return self._xnamed(LatLon2Tuple(degrees90(y), degrees180(x)))
Example #3
0
    def __init__(self, knots, datum=None, beta=2, wrap=False, name=''):
        '''New L{HeightIDWhaversine} interpolator.

           @param knots: The points with known height (C{LatLon}s).
           @keyword datum: Optional datum (L{Datum} to use, overriding
                           the default C{B{knots}[0].datum}
           @keyword beta: Inverse distance power (C{int} 1, 2, or 3).
           @keyword wrap: Wrap and L{unroll180} longitudes (C{bool}).
           @keyword name: Optional height interpolator name (C{str}).

           @raise HeightError: Insufficient number of B{C{knots}} or
                               invalid B{C{knot}}, B{C{datum}} or
                               B{C{beta}}.

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

           @raise TypeError: Invalid B{C{datum}}.
        '''
        n, self._lls = len2(knots)
        if n < self._kmin:
            raise HeightError('insufficient %s: %s, need %s' %
                              ('knots', n, self._kmin))
        try:
            self._datum = self._lls[0].datum if datum is None else datum
            if not isinstance(self.datum, Datum):
                raise TypeError
        except (AttributeError, TypeError):
            raise _IsNotError('valid', datum=self.datum or datum)
        self._geodesic = self.datum.ellipsoid.geodesic

        self.beta = beta
        if wrap:
            self._wrap = True
        if name:
            self.name = name
Example #4
0
    def toLatLon(self, LatLon=None, height=None):
        '''Convert this L{Css} to an (ellipsoidal) geodetic point.

           @keyword LatLon: Optional, ellipsoidal (sub-)class to return
                            the geodetic point (C{LatLon}) or C{None}.
           @keyword height: Optional height for the point, overriding
                            the default height (C{meter}).

           @return: The point (B{C{LatLon}}) or a
                    L{LatLon4Tuple}C{(lat, lon, height, datum)} if
                    B{C{LatLon}} is C{None}.

           @raise TypeError: If B{C{LatLon}} or B{C{datum}} is not ellipsoidal.
        '''
        if LatLon and not issubclassof(LatLon, _LLEB):
            raise _IsNotError(_LLEB.__name__, LatLon=LatLon)

        lat, lon = self.latlon
        d = self.cs0.datum
        h = self.height if height is None else height

        r = LatLon4Tuple(lat, lon, h, d) if LatLon is None else \
                  LatLon(lat, lon, height=h, datum=d)
        return self._xnamed(r)
Example #5
0
def _2epoch(epoch):  # imported by .ellipsoidalBase.py
    '''(INTERNAL) Validate an C{epoch}.
    '''
    if isscalar(epoch) and epoch > 0:  # XXX 1970?
        return _F(epoch)
    raise _IsNotError('scalar', epoch=epoch)