Coverage for pygeodesy/clipy.py : 96%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# -*- coding: utf-8 -*-
Clip a path or polygon of C{LatLon} points against a rectangular box or a (convex) clip region. '''
_fi_, _i_, _j_, _near_, _not_, _SPACE_, \ _start_, _too_, _0_0, _1_0
'''Clip box or clip region issue. ''' '''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}). '''
'''(INTERNAL) Get the clip box edges.
@see: Class C{_Box} in .ellipsoidalBaseDI.py. ''' raise ValueError except (AttributeError, TypeError, ValueError) as x: raise ClipError(name, 2, (lowerleft, upperright), txt=str(x))
'''(INTERNAL) Check for near-equal points. '''
'''(INTERNAL) Check for not near-equal points. ''' abs(p1.lon - p2.lon) > EPS
'''(INTERNAL) Get the points to clip as a list. ''' # only remove the final, closing point n -= 1 pts = pts[:n] raise PointsError(points=n, txt=_too_(_few_)) else:
'''(INTERNAL) Cohen-Sutherland line clipping. ''' # single-bit clip codes
self._xmax, self._ymax = _box4(lowerleft, upperright, name)
# def clip4(self, p, c): # clip point p for code c # if c & _CS._YMIN: # return self.lon4(p, self._ymin) # elif c & _CS._YMAX: # return self.lon4(p, self._ymax) # elif c & _CS._XMIN: # return self.lat4(p, self._xmin) # elif c & _CS._XMAX: # return self.lat4(p, self._xmax) # # should never get here # raise _AssertionError(self._DOT_(self.clip4.__name__))
else:
return _CS._YMAX, self.lon4, self._ymax, p else: # inside
return _CS._XMIN, self.lat4, self._xmin, p else: # inside
def nop4(self, b, p): # PYCHOK no cover if p: # should never get here raise _AssertionError(self._DOT_(self.nop4.__name__)) return _CS._IN, self.nop4, b, p
'''4-Tuple C{(start, end, i, j)} for each edge of a I{clipped} path with the C{start} and C{end} points (C{LatLon}) of the portion of the edge inside or on the clip box and the indices C{i} and C{j} (C{int}) of the edge start and end points in the original path. '''
'''Clip a path against a rectangular clip box using the U{Cohen-Sutherland <https://WikiPedia.org/wiki/Cohen-Sutherland_algorithm>} algorithm.
@arg points: The points (C{LatLon}[]). @arg lowerleft: Bottom-left corner of the clip box (C{LatLon}). @arg upperright: Top-right corner of the clip box (C{LatLon}). @kwarg closed: Optionally, close the path (C{bool}). @kwarg inull: Optionally, retain null edges if inside (C{bool}).
@return: Yield a L{ClipCS4Tuple}C{(start, end, i, j)} for each edge of the I{clipped} path.
@raise ClipError: The B{C{lowerleft}} and B{C{upperright}} corners specify an invalid clip box.
@raise PointsError: Insufficient number of B{C{points}}. '''
pass else: # inside else: # PYCHOK no cover raise _AssertionError(_DOT_(cs.name, 'for_else'))
elif inull and not c2: yield ClipCS4Tuple(p2, p2, i, j)
'''6-Tuple C{(start, end, i, fi, fj, j)} for each edge of the I{clipped} path with the C{start} and C{end} points (C{LatLon}) of the portion of the edge inside or on the clip box, indices C{i} and C{j} (both C{int}) of the original path edge start and end points and I{fractional} indices C{fi} and C{fj} (both L{FIx}) of the C{start} and C{end} points along the edge of the original path.
@see: Class L{FIx} and function L{pygeodesy.fractional}. '''
'''Clip a path against a rectangular clip box using the U{Liang-Barsky <https://www.CSE.UNT.edu/~renka/4230/LineClipping.pdf>} algorithm.
@arg points: The points (C{LatLon}[]). @arg lowerleft: Bottom-left corner of the clip box (C{LatLon}). @arg upperright: Top-right corner of the clip box (C{LatLon}). @kwarg closed: Optionally, close the path (C{bool}). @kwarg inull: Optionally, retain null edges if inside (C{bool}).
@return: Yield a L{ClipLB6Tuple}C{(start, end, i, fi, fj, j)} for each edge of the I{clipped} path.
@raise ClipError: The B{C{lowerleft}} and B{C{upperright}} corners specify an invalid clip box.
@raise PointsError: Insufficient number of B{C{points}}.
@see: U{Liang-Barsky Line Clipping<https://www.CS.Helsinki.FI/group/goa/ viewing/leikkaus/intro.html>}, U{Liang-Barsky line clipping algorithm <https://www.Skytopia.com/project/articles/compsci/clipping.html>} and U{Liang-Barsky algorithm<https://WikiPedia.org/wiki/Liang-Barsky_algorithm>}. ''' xmax, ymax = _box4(lowerleft, upperright, clipLB6.__name__)
# non-null edge pts[i]...pts[j] _LB( dx, xmax - x1, t) and \ _LB(-dy, -ymin + y1, t) and \ _LB( dy, ymax - y1, t): # clip edge pts[i]...pts[j] # at fractions t[0] to t[1] x1 + f * dx) else:
x1 + t * dx) else:
fi = FIx(fi, fin=fin) yield ClipLB6Tuple(p1, p1, i, fi, fi, j) # else: # outside # pass FIx(j, fin=fin), j)
# Liang-Barsky trim t[0] or t[1] return False # too far below elif q < 0: # vertical or horizontal return False # ... outside
'''(INTERNAL) List of clipped points. '''
'''(INTERNAL) LatLon_ for _SH intersections. ''' # __slots__ are no longer space savers, see # the comments at the class .points.LatLon_ # __slots__ = _lat_, _lon_, 'classof', 'edge', _name_
'''(INTERNAL) Sutherland-Hodgman polyon clipping. '''
LatLon_(t, r), LatLon_(b, r)) raise ValueError(_not_(_convex_)) raise ValueError(NN(_near_, 'zero area')) except (PointsError, TypeError, ValueError) as x: raise ClipError(name, n, cs, txt=str(x))
# clip points, closed always # pca(p1) else: # ... p2 outside # elif d1 > 0: # both outside # pass # replace points, in-place else: raise ClipError(self.name, ne, self._cs, txt=_too_(_few_))
# assert len(pts) == np
# and set self._x1, ._y1, ._dx, ._dy and # ._xy for each non-null clip edge
else: # original point
# clip corner c1 and clip edge c1 to c2, indicating whether # point p is located to the right, to the left or on top # of the (extended) clip edge from c1 to c2 self._dy * float(p.lon - self._x1) # clockwise corners, +1 means point p is to the right # of, -1 means on the left of, 0 means on edge c1 to c2
# of polygon edge p1 to p2 and the current clip edge, # where p1 and p2 are known to NOT be located on the # same side or on top of the current clip edge # <https://StackOverflow.com/questions/563198/ # how-do-you-detect-where-two-line-segments-intersect> if abs(fp) < EPS: # PYCHOK no cover raise _AssertionError(self._DOT_(self.intersect.__name__))
'''3-Tuple C{(start, end, original)} for each edge of a I{clipped} polygon, the C{start} and C{end} points (C{LatLon}) of the portion of the edge inside or on the clip region and C{original} indicates whether the edge is part of the original polygon or part of the clip region (C{bool}). '''
'''Clip a polygon against a clip region or box using the U{Sutherland-Hodgman <https://WikiPedia.org/wiki/Sutherland-Hodgman_algorithm>} algorithm.
@arg points: The polygon points (C{LatLon}[]). @arg corners: Three or more points defining a convex clip region (C{LatLon}[]) or two points to specify a rectangular clip box. @kwarg closed: Close the clipped points (C{bool}). @kwarg inull: Optionally, include null edges (C{bool}).
@return: Yield the clipped points (C{LatLon}[]).
@raise ClipError: The B{C{corners}} specify a polar, zero-area, non-convex or otherwise invalid clip box or region.
@raise PointsError: Insufficient number of B{C{points}}. '''
'''Clip a polygon against a clip region or box using the U{Sutherland-Hodgman <https://WikiPedia.org/wiki/Sutherland-Hodgman_algorithm>} algorithm.
@arg points: The polygon points (C{LatLon}[]). @arg corners: Three or more points defining a convex clip region (C{LatLon}[]) or two points to specify a rectangular clip box. @kwarg closed: Close the clipped points (C{bool}). @kwarg inull: Optionally, include null edges (C{bool}).
@return: Yield a L{ClipSH3Tuple}C{(start, end, original)} for each edge of the I{clipped} polygon.
@raise ClipError: The B{C{corners}} specify a polar, zero-area, non-convex or otherwise invalid clip box or region.
@raise PointsError: Insufficient number of B{C{points}}. '''
# **) MIT License # # Copyright (C) 2018-2021 -- mrJean1 at Gmail -- All Rights Reserved. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included # in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. |