Go to the documentation of this file.00001 """convexhull.py
00002
00003 Calculate the convex hull of a set of n 2D-points in O(n log n) time.
00004 Taken from Berg et al., Computational Geometry, Springer-Verlag, 1997.
00005 Prints output as EPS file.
00006
00007 When run from the command line it generates a random set of points
00008 inside a square of given length and finds the convex hull for those,
00009 printing the result as an EPS file.
00010
00011 Usage:
00012
00013 convexhull.py <numPoints> <squareLength> <outFile>
00014
00015 Dinu C. Gherman
00016 """
00017
00018
00019 import sys, string, random
00020
00021
00022
00023
00024
00025
00026 def _myDet(p, q, r):
00027 """Calc. determinant of a special matrix with three 2D points.
00028
00029 The sign, "-" or "+", determines the side, right or left,
00030 respectivly, on which the point r lies, when measured against
00031 a directed vector from p to q.
00032 """
00033
00034
00035
00036 sum1 = q[0]*r[1] + p[0]*q[1] + r[0]*p[1]
00037 sum2 = q[0]*p[1] + r[0]*q[1] + p[0]*r[1]
00038
00039 return sum1 - sum2
00040
00041
00042 def _isRightTurn((p, q, r)):
00043 "Do the vectors pq:qr form a right turn, or not?"
00044
00045 assert p != q and q != r and p != r
00046
00047 if _myDet(p, q, r) < 0:
00048 return 1
00049 else:
00050 return 0
00051
00052
00053 def _isPointInPolygon(r, P):
00054 "Is point r inside a given polygon P?"
00055
00056
00057 for i in xrange(len(P[:-1])):
00058 p, q = P[i], P[i+1]
00059 if not _isRightTurn((p, q, r)):
00060 return 0
00061
00062 return 1
00063
00064
00065 def _makeRandomData(numPoints=10, sqrLength=100, addCornerPoints=0):
00066 "Generate a list of random points within a square."
00067
00068
00069 min, max = 0, sqrLength
00070 P = []
00071 for i in xrange(numPoints):
00072 rand = random.randint
00073 x = rand(min+1, max-1)
00074 y = rand(min+1, max-1)
00075 P.append((x, y))
00076
00077
00078 if addCornerPoints != 0:
00079 P = P + [(min, min), (max, max), (min, max), (max, min)]
00080
00081 return P
00082
00083
00084
00085
00086
00087
00088
00089
00090 def convex_hull(P):
00091 "Calculate the convex hull of a set of points."
00092
00093
00094 points = map(None, P)
00095 points.sort()
00096
00097
00098 upper = [points[0], points[1]]
00099 for p in points[2:]:
00100 upper.append(p)
00101 while len(upper) > 2 and not _isRightTurn(upper[-3:]):
00102 del upper[-2]
00103
00104
00105 points.reverse()
00106 lower = [points[0], points[1]]
00107 for p in points[2:]:
00108 lower.append(p)
00109 while len(lower) > 2 and not _isRightTurn(lower[-3:]):
00110 del lower[-2]
00111
00112
00113 del lower[0]
00114 del lower[-1]
00115
00116
00117 return tuple(upper + lower)
00118
00119
00120
00121
00122
00123
00124 def test():
00125 a = 200
00126 p = _makeRandomData(30, a, 0)
00127 c = convexHull(p)
00128
00129
00130