def vwr(self, attr): '''Return the Visvalingam-Whyatt results, optionally including the triangular area (in meters) as attribute attr to each simplified point. ''' pts, r = self.pts, self.r # double check the minimal triangular area assert min(t2.h2 for t2 in r) > self.s2 > 0 if attr: # return the trangular area (actually # the sqrt of double the triangular area) # converted back from degrees to meter if isNumpy2(pts): raise AttributeError('%r invalid' % (attr,)) m = radians(1.0) * self.radius r[0].h2 = r[-1].h2 = 0 # zap sentinels for t2 in r: # convert back to meter setattr(pts[t2.ix], attr, sqrt(t2.h2) * m) # double check for duplicates n = len(r) r = dict((t2.ix, True) for t2 in r) assert len(r) == n return self.points(r)
def __init__(self, points, tolerance, radius, shortest, indices, **options): '''New C{Simplify} state. ''' n, self.pts = len2(points) if n > 0: self.n = n self.r = {0: True, n - 1: True} # dict to avoid duplicates if isNumpy2(points) or isTuple2(points): # NOT self.pts self.subset = points.subset if indices: self.indices = True if radius: self.radius = float(radius) if self.radius < self.eps: raise ValueError('%s too small: %.6e' % ('radius', radius)) if options: self.options = options # tolerance converted to degrees squared self.s2 = degrees(tolerance / self.radius)**2 if min(self.s2, tolerance) < self.eps: raise ValueError('%s too small: %.6e' % ('tolerance', tolerance)) self.s2e = self.s2 + 1 # sentinel # compute either the shortest or perpendicular distance self.d2i = self.d2iS if shortest else self.d2iP # PYCHOK false
def points(self, r): '''Return the list of simplified points or indices. ''' r = sorted(r.keys()) if self.indices: return list(r) elif isNumpy2(self.pts) or isTuple2(self.pts): return self.pts.subset(r) else: return [self.pts[i] for i in r]
def points2(points, closed=True, base=None, Error=PointsError): '''Check a path or polygon represented by points. @arg points: The path or polygon points (C{LatLon}[]) @kwarg closed: Optionally, consider the polygon closed, ignoring any duplicate or closing final B{C{points}} (C{bool}). @kwarg base: Optionally, check all B{C{points}} against this base class, if C{None} don't check. @kwarg Error: Exception to raise (C{ValueError}). @return: A L{Points2Tuple}C{(number, points)} with the number of points and the points C{list} or C{tuple}. @raise PointsError: Insufficient number of B{C{points}}. @raise TypeError: Some B{C{points}} are not B{C{base}} compatible. ''' n, points = len2(points) if closed: # remove duplicate or closing final points while n > 1 and points[n - 1] in (points[0], points[n - 2]): n -= 1 # XXX following line is unneeded if points # are always indexed as ... i in range(n) points = points[:n] # XXX numpy.array slice is a view! if n < (3 if closed else 1): raise Error('too few %s: %s' % ('points', n)) if base and not (isNumpy2(points) or isTuple2(points)): for i in range(n): base.others(points[i], name='%s[%s]' % ('points', i)) return Points2Tuple(n, points)