docs: def voronoi(points, buffer_percent=100):
      """
      Surrounds each point in an input list of xy tuples with a
      unique Voronoi polygon.
  
      Arguments:
      
      - **points**: A list of xy or xyz point tuples to triangulate. 
      - **buffer_percent** (optional): Controls how much bigger than
          the original bbox of the input points to set the bbox of fake points,
          used to account for lacking values around the edges (default is 100 percent).
  
      Returns:
      
      - Returns a list of 2-tuples, with the first item in each tuple being the
          original input point (or None for each corner of the bounding box buffer),
          and the second item being the point's corressponding Voronoi polygon. 
  
      """
      # Remove duplicate xy points bc that would make delauney fail, and must remember z (if any) for retrieving originals from index results
      seen = set() 
      uniqpoints = [ p for p in points if str( p[:2] ) not in seen and not seen.add( str( p[:2] ) )]
      classpoints = [_Point(*point[:2]) for point in uniqpoints]
  
      # Create fake sitepoints around the point extent to correct for infinite polygons
      # For a similar approach and problem see: http://gis.stackexchange.com/questions/11866/voronoi-polygons-that-run-out-to-infinity
      xs,ys = list(zip(*uniqpoints))[:2]
      pointswidth = max(xs) - min(xs)
      pointsheight = max(ys) - min(ys)
      xbuff,ybuff = ( pointswidth / 100.0 * buffer_percent , pointsheight / 100.0 * buffer_percent )
      midx,midy = ( sum(xs) / float(len(xs)) , sum(ys) / float(len(ys)) )
      #bufferbox = [(midx-xbuff,midy-ybuff),(midx+xbuff,midy-ybuff),(midx+xbuff,midy+ybuff),(midx-xbuff,midy+ybuff)] # corner buffer
      bufferbox = [(midx-xbuff,midy),(midx+xbuff,midy),(midx,midy+ybuff),(midx,midy-ybuff)] # mid sides buffer
      classpoints.extend([_Point(*corner) for corner in bufferbox])
  
      # Compute Voronoi
      vertices,edges,poly_dict = tesselator.computeVoronoiDiagram(classpoints)
  
      # Turn unordered result edges into ordered polygons
      polygons = list()
      for sitepoint,polyedges in list(poly_dict.items()):
          polyedges = [edge[1:] for edge in polyedges]
          poly = list()
          firststart,firstend = polyedges.pop(0)
          poly.append(firstend)
          while polyedges:
              curend = poly[-1]
              for i,other in enumerate(polyedges):
                  otherstart,otherend = other
                  if otherstart == curend:
                      poly.append(otherend)
                      ##print otherstart,otherend
                      polyedges.pop(i)
                      break
                  elif otherend == curend:
                      ##print otherend,otherstart
                      poly.append(otherstart)
                      polyedges.pop(i)
                      break
          # Get vertices from indexes
          try: sitepoint = uniqpoints[sitepoint]
          except IndexError:
              sitepoint = None # fake bbox sitepoints shouldnt be in the results
          poly = [vertices[vi] for vi in poly if vi != -1]
          polygons.append((sitepoint, poly))
  
      # Maybe clip parts of polygons that stick outside screen?
      # ...
  
      return polygons