convexhull.py
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 # Helpers
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     # We use Sarrus' Rule to calculate the determinant.
00035     # (could also use the Numeric package...)
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     # We assume the polygon is a list of points, listed clockwise!
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 # Out!        
00061 
00062     return 1 # It's within!
00063 
00064 
00065 def _makeRandomData(numPoints=10, sqrLength=100, addCornerPoints=0):
00066     "Generate a list of random points within a square."
00067     
00068     # Fill a square with random points.
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     # Add some "outmost" corner points.
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 # Public interface
00088 ######################################################################
00089 
00090 def convex_hull(P):
00091     "Calculate the convex hull of a set of points."
00092 
00093     # Get a local list copy of the points and sort them lexically.
00094     points = map(None, P)
00095     points.sort()
00096 
00097     # Build upper half of the hull.
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     # Build lower half of the hull.
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     # Remove duplicates.
00113     del lower[0]
00114     del lower[-1]
00115 
00116     # Concatenate both halfs and return.
00117     return tuple(upper + lower)
00118 
00119 
00120 ######################################################################
00121 # Test
00122 ######################################################################
00123 
00124 def test():
00125     a = 200
00126     p = _makeRandomData(30, a, 0)
00127     c = convexHull(p)
00128 
00129 
00130 


semanticmodel
Author(s): Julian ("Mac") Mason
autogenerated on Thu Dec 12 2013 12:39:10