Esempio n. 1
0
def hausdorff_(model,
               target,
               both=False,
               early=True,
               seed=None,
               units='',
               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>}.

       @param model: First set of points (C{LatLon}[], C{Numpy2LatLon}[],
                     C{Tuple2LatLon}[] or C{other}[]).
       @param target: Second set of points (C{LatLon}[], C{Numpy2LatLon}[],
                      C{Tuple2LatLon}[] or C{other}[]).
       @keyword both: Return the C{directed} (forward only) or the C{symmetric}
                      (combined forward and reverse) C{Hausdorff} distance (C{bool}).
       @keyword early: Enable or disable U{early breaking<https://Publik.TUWien.ac.AT/
                       files/PubDat_247739.pdf>} (C{bool}).
       @keyword 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>}.
       @keyword units: Optional, name of the distance units (C{str}).
       @keyword distance: Callable returning the distance between a B{C{model}}
                          and B{C{target}} point (signature C{(point1, point2)}).
       @Keyword 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 TypeError('%s not callable: %r' % ('distance', distance))
    if not callable(point):
        raise TypeError('%s not callable: %r' % ('point', point))

    _, ps1 = points2(model, closed=False, Error=HausdorffError)
    _, ps2 = points2(target, closed=False, Error=HausdorffError)
    return _hausdorff_(ps1, ps2, both, early, seed, units, distance, point)
Esempio n. 2
0
def clipCS3(points, lowerleft, upperright, closed=False, inull=False):  # MCCABE 25
    '''Clip a path against a rectangular clip box using the
       U{Cohen-Sutherland
       <https://WikiPedia.org/wiki/Cohen-Sutherland_algorithm>} algorithm.

       @param points: The points (C{LatLon}[]).
       @param lowerleft: Bottom-left corner of the clip box (C{LatLon}).
       @param upperright: Top-right corner of the clip box (C{LatLon}).
       @keyword closed: Optionally, close the path (C{bool}).
       @keyword inull: Optionally, include null edges if inside (C{bool}).

       @return: Yield a L{ClipCS3Tuple}C{(start, end, index)} for each
                edge of the clipped path.

       @raise ValueError: The B{C{lowerleft}} corner is not below and/or
                          not to the left of the B{C{upperright}} corner.
    '''

    cs = _CS(lowerleft, upperright)
    n, points = points2(points, closed=closed)

    i, m = _imdex2(closed, n)
    cmbp = cs.code4(points[i])
    for i in range(m, n):
        c1, m1, b1, p1 = cmbp
        c2, m2, b2, p2 = cmbp = cs.code4(points[i])
        if c1 & c2:  # edge outside
            continue

        if not cs.edge(p1, p2):
            if inull:  # null edge
                if not c1:
                    yield ClipCS3Tuple(p1, p1, i)
                elif not c2:
                    yield ClipCS3Tuple(p2, p2, i)
            continue

        for _ in range(5):
            if c1:  # clip p1
                c1, m1, b1, p1 = m1(b1, p1)
            elif c2:  # clip p2
                c2, m2, b2, p2 = m2(b2, p2)
            else:  # inside
                if inull or _neq(p1, p2):
                    yield ClipCS3Tuple(p1, p2, i)
                break
            if c1 & c2:  # edge outside
                break
        else:  # should never get here
            raise AssertionError('clipCS3.for _')
Esempio n. 3
0
    def symmetric(self, points, early=True):
        '''Compute the combined C{forward and reverse Hausdorff} distance.

           @param points: Second set of points, aka the C{target} (C{LatLon}[],
                          C{Numpy2LatLon}[], C{Tuple2LatLon}[] or C{other}[]).
           @keyword early: Enable or disable U{early breaking<https://
                           Publik.TUWien.ac.AT/files/PubDat_247739.pdf>}
                           (C{bool}).

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

           @raise HausdorffError: Insufficient number of B{C{points}}.
        '''
        _, ps2 = points2(points, closed=False, Error=HausdorffError)
        return _hausdorff_(self._model, ps2, True, early, self.seed,
                           self.units, self.distance, self.point)
Esempio n. 4
0
 def __init__(self, corners):
     n = ''
     try:
         n, cs = len2(corners)
         if n == 2:  # make a box
             b, l, t, r = boundsOf(cs, wrap=False)
             cs = LL_(b, l), LL_(t, l), LL_(t, r), LL_(b, r)
         n, cs = points2(cs, closed=True)
         self._corners = cs = cs[:n]
         self._nc = n
         self._cw = 1 if isclockwise(cs, adjust=False, wrap=False) else -1
         if self._cw != isconvex_(cs, adjust=False, wrap=False):
             raise ValueError
     except ValueError:
         raise ValueError('invalid %s[%s]: %r' % ('corners', n, corners))
     self._clipped = self._points = []
Esempio n. 5
0
    def points2(self, points, closed=True):
        '''Check a polygon represented by points.

           @param points: The polygon points (C{LatLon}[])
           @keyword closed: Optionally, consider the polygon closed,
                            ignoring any duplicate or closing final
                            B{C{points}} (C{bool}).

           @return: 2-Tuple (number, ...) of points (C{int}, C{list} or
                    C{tuple}).

           @raise TypeError: Some B{C{points}} are not C{LatLon}.

           @raise ValueError: Insufficient number of B{C{points}}.
        '''
        return points2(points, closed=closed, base=self)
Esempio n. 6
0
    def __init__(self, points, seed=None, name='', units=''):
        '''New L{Hausdorff} calculator.

           @param points: Initial set of points, aka the C{model} or
                          C{template} (C{LatLon}[], C{Numpy2LatLon}[],
                          C{Tuple2LatLon}[] or C{other}[]).
           @keyword 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>}.
           @keyword name: Optional calculator name (C{str}).
           @keyword units: Optional, distance units (C{str}).

           @raise HausdorffError: Insufficient number of B{C{points}} or
                                  invalid B{C{seed}}.
        '''
        _, self._model = points2(points, closed=False, Error=HausdorffError)
        if seed:
            self.seed = seed
        if name:
            self.name = name
        if units:
            self.units = units
Esempio n. 7
0
def _geodesic(datum, points, closed, line, wrap):
    # Compute the area or perimeter of a polygon,
    # using the GeographicLib package, iff installed
    g = datum.ellipsoid.geodesic

    if not wrap:  # capability LONG_UNROLL can't be off
        raise ValueError('%s invalid: %s' % ('wrap', wrap))

    _, points = points2(points,
                        closed=closed)  # base=LatLonEllipsoidalBase(0, 0)

    g = g.Polygon(line)

    # note, lon deltas are unrolled, by default
    for p in points:
        g.AddPoint(p.lat, p.lon)
    if line and closed:
        p = points[0]
        g.AddPoint(p.lat, p.lon)

    # g.Compute returns (number_of_points, perimeter, signed area)
    return g.Compute(False, True)[1 if line else 2]
Esempio n. 8
0
def polygon(points, closed=True, base=None):
    '''DEPRECATED, use function L{points2}.
    '''
    from pygeodesy.utily import points2
    return points2(points, closed=closed, base=base)