Added box_cut tool and some documentation. master
Added box_cut tool and some documentation.

--- a/voronoi/tools.py
+++ b/voronoi/tools.py
@@ -1,3 +1,18 @@
+##
+# img_coords(edge,width,height)
+# 
+# Clips an edge to be within the window, defined by width and height.  The edge of
+# the window is taken to be at (0,0).
+#
+# Parameters: 
+#  edge - Edge objects describing the edge that should be clipped.
+#  width - Width of the window
+#  height - Height of the window
+# 
+# Return:
+#  The returned value is an line segment, defined as [(p1x,p1y),(p2x,p2y)], where 
+#  the coordinates are integers. None is returned if the edge misses the window 
+#  completely.
 def img_coords(edge,width,height):
     intersections=[]
 
@@ -55,3 +70,90 @@
     end=edge.value(p2t)
     return ((int(start[0]),int(start[1])),(int(end[0]),int(end[1])))
 
+##
+# box_cut(edge,box)
+#
+# Cuts a box in half using an edge, and returns the part that lies on the same side
+# as the left point of the edge. The edge is taken to be infinite in length.
+#
+# Parameters:
+#  edge - Edge object describing the edge that is doing the cutting.
+#  box - Description of the box as (x,y,width,height), where (x,y) are the
+#        coordinates of the lower left corner.
+#
+# Return:
+#  A polygon in the form [(x1,y1),(x2,y2),...]. In the case the entire box lies on
+#  the same side as the right poing of the edge, the polygon is empty: [].
+def box_cut(edge,box):
+    intersections=[]
+    # Intersection with north and south edges (horizontal)
+    if edge.direction[1]!=0:
+        # North (y=height)
+        t=(box[3]-edge.r[1]+box[1])/edge.direction[1]
+        x=edge.value_x(t)-box[0]
+        if 0<x and x<box[2]:
+            intersections.append((0,t))
+        # South (y=0)
+        t=(-edge.r[1]+box[1])/edge.direction[1]
+        x=edge.value_x(t)-box[0]
+        if 0<x and x<box[2]:
+            intersections.append((2,t))
+
+    # Intersections with east and west (vertical)
+    if edge.direction[0]!=0:
+        # East (x=width)
+        t=(box[2]-edge.r[0]+box[0])/edge.direction[0]
+        y=edge.value_y(t)-box[1]
+        if 0<y and y<box[3]:
+            intersections.append((1,t))
+        # West (x=0)
+        t=(box[0]-edge.r[0])/edge.direction[0]
+        y=edge.value_y(t)-box[1]
+        if 0<y and y<box[3]:
+            intersections.append((3,t))
+
+    if len(intersections)==0:  # Line misses box completely
+        # Determine what side the entire box lies on. Might have to add the
+        # entire thing.
+        point=(box[0],box[1])
+        side=point[0]*edge.direction[1]-point[1]*edge.direction[0]
+        if side<0:
+            return [(box[0],box[1]),(box[0],box[1]+box[3]),(box[0]+box[2],box[1]+box[3]),(box[0]+box[2],box[1])]
+        else:
+            return []
+
+    # Determine the points that cross the box.
+    out_edge,in_edge=None,None
+    out_t,in_t=None,None
+    if intersections[0][1]>intersections[1][1]:
+        out_edge,in_edge=intersections[0][0],intersections[1][0]
+        out_t,in_t=intersections[0][1],intersections[1][1]
+    else:
+        out_edge,in_edge=intersections[1][0],intersections[0][0]
+        out_t,in_t=intersections[1][1],intersections[0][1]
+
+    # Build a list of edges of the box that should be added
+    sides=[]
+    if out_edge<in_edge:
+        sides=range(in_edge,3+1)
+        sides.extend(range(0,out_edge+1))
+    else:
+        sides=range(in_edge,out_edge+1)
+
+    # Loop over corners from the above list and add them
+    polygon=[edge.value(in_t)]
+    for i in range(len(sides)-1):
+        s1=sides[i]
+        s2=sides[i+1]
+        if (s1==0 and s2==1) or (s1==1 and s2==0): # North <-> East
+            polygon.append((box[0]+box[2],box[1]+box[3]))
+        elif (s1==1 and s2==2) or (s1==2 and s2==1): # East <-> South
+            polygon.append((box[0]+box[2],box[1]))
+        elif (s1==2 and s2==3) or (s1==3 and s2==2): # South <-> West
+            polygon.append((box[0],box[1]))
+        elif (s1==3 and s2==0) or (s1==0 and s2==3): # West <-> North
+            polygon.append((box[0],box[1]+box[3]))
+    polygon.append(edge.value(out_t))
+
+    return polygon
+