📄 convexhull.py
字号:
#!/usr/bin/env python"""convexhull.pyCalculate the convex hull of a set of n 2D-points in O(n log n) time. Taken from Berg et al., Computational Geometry, Springer-Verlag, 1997.Prints output as EPS file.When run from the command line it generates a random set of pointsinside a square of given length and finds the convex hull for those,printing the result as an EPS file.Usage: convexhull.py <numPoints> <squareLength> <outFile>Dinu C. GhermanDownloaded originally from: http://starship.python.net/~gherman/Playground.htmlModified by Jeremy Stribling"""import sys, string, random####################################################################### Helpers######################################################################def _myDet(p, q, r): """Calc. determinant of a special matrix with three 2D points. The sign, "-" or "+", determines the side, right or left, respectivly, on which the point r lies, when measured against a directed vector from p to q. """ # We use Sarrus' Rule to calculate the determinant. # (could also use the Numeric package...) sum1 = q[0]*r[1] + p[0]*q[1] + r[0]*p[1] sum2 = q[0]*p[1] + r[0]*q[1] + p[0]*r[1] return sum1 - sum2def _isRightTurn((p, q, r)): "Do the vectors pq:qr form a right turn, or not?" assert p != q and q != r and p != r if _myDet(p, q, r) < 0: return 1 else: return 0def _isPointInPolygon(r, P): "Is point r inside a given polygon P?" # We assume the polygon is a list of points, listed clockwise! for i in xrange(len(P[:-1])): p, q = P[i], P[i+1] if not _isRightTurn((p, q, r)): return 0 # Out! return 1 # It's within!def _makeRandomData(numPoints=10, sqrLength=100, addCornerPoints=0): "Generate a list of random points within a square." # Fill a square with random points. min, max = 0, sqrLength P = [] for i in xrange(numPoints): rand = random.randint x = rand(min+1, max-1) y = rand(min+1, max-1) P.append((x, y)) # Add some "outmost" corner points. if addCornerPoints != 0: P = P + [(min, min), (max, max), (min, max), (max, min)] return P####################################################################### Output######################################################################epsHeader = """%%!PS-Adobe-2.0 EPSF-2.0%%%%BoundingBox: %d %d %d %d/r 2 def %% radius/circle %% circle, x, y, r --> -{ 0 360 arc %% draw circle} def/cross %% cross, x, y --> -{ 0 360 arc %% draw cross hair} def1 setlinewidth %% thin linenewpath %% open page0 setgray %% black color"""def saveAsEps(P, H, boxSize, path): "Save some points and their convex hull into an EPS file." # Save header. f = open(path, 'w') f.write(epsHeader % (0, 0, boxSize, boxSize)) format = "%3d %3d" # Save the convex hull as a connected path. if H: f.write("%s moveto\n" % format % H[0]) for p in H: f.write("%s lineto\n" % format % p) f.write("%s lineto\n" % format % H[0]) f.write("stroke\n\n") # Save the whole list of points as individual dots. for p in P: f.write("%s r circle\n" % format % p) f.write("stroke\n") # Save footer. f.write("\nshowpage\n")####################################################################### Public interface######################################################################def convexHull(P): "Calculate the convex hull of a set of points." # Get a local list copy of the points and sort them lexically. points = map(None, P)# points.sort(col2_sort) # Build upper half of the hull.# left = [points[0], points[1]]# for p in points[2:]:# left.append(p)# while len(left) > 2 and not _isRightTurn(left[-3:]):# del left[-2] # Build lower half of the hull. points.sort() points.reverse() lower = [points[0], points[1]] for p in points[2:]: lower.append(p) while len(lower) > 2 and not _isRightTurn(lower[-3:]): del lower[-2] # Remove duplicates.# while (lower[-1])[0] < (left[0])[0]:# del lower[-1] # never go up as you move to the right of the hull . . . while len(lower) > 1 and (lower[0])[1] > (lower[1])[1]: del lower[0] # Concatenate both halfs and return. return tuple(lower)# + left)def col2_sort(x, y): if x[1] > y[1]: return 1 if x[1] == y[1] and x[0] > y[0]: return 1 if x[1] == y[1] and x[0] == y[0]: return 0 return -1####################################################################### Test######################################################################def test(): a = 200 p = _makeRandomData(30, a, 0) c = convexHull(p) saveAsEps(p, c, a, file)######################################################################if __name__ == '__main__': try: numPoints = string.atoi(sys.argv[1]) squareLength = string.atoi(sys.argv[2]) path = sys.argv[3] except IndexError: numPoints = 30 squareLength = 200 path = "sample.eps" p = _makeRandomData(numPoints, squareLength, addCornerPoints=0) c = convexHull(p) saveAsEps(p, c, squareLength, path)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -