def _label(point, centers):
    """
    Returns an index such that *centers*[index] is the point in *centers* nearest *point*.
    """
    min_sqdist = None
    best_label = None
    for c in range(len(centers)):
        if min_sqdist == None or sqdist(point, centers[c]) < min_sqdist:
            min_sqdist = sqdist(point, centers[c])
            best_label = c
    return best_label
def kmeans(points3, centers, epsilon):
    """
    Returns a list of lists of elements of *points3*, k-means clustered in two dimensions
    around the k centers in *centers* with points weighted by third dimension coordinate.
    Iteration until no center moves more than *epsilon*.
    """
    prevcenters = None
    while prevcenters == None or max([ sqdist(center, prevcenter)
                                       for (center, prevcenter) in zip(centers, prevcenters)
                                       ]) > epsilon**2:
        # empty clusters
        clusters = []
        for center in centers:
            clusters.append([])
        
        # recluster points
        for point in points3:
            clusters[_label(point, centers)].append(point)
        
        # find new centers
        prevcenters = deepcopy(centers)
        for i in range(len(centers)):
            centers[i] = np.average(clusters[i],
                                    axis=0,
                                    weights=[ point[2] for point in clusters[i] ])
    
    return clusters
def local_maxima(points3, radius):
    """
    Returns a list of points from *points3* who have no neighbors of greater intensity
    within *radius* pixels. Ties are arbitrarily broken.
    """
    maxima = []
    for p in points3:
        neighbor_zs = [ q[2] for q in points3 if q != p and sqdist(p, q) < radius**2 ]
        
        if neighbor_zs == [] or p[2] > max(neighbor_zs):
            maxima.append(p)
        elif p[2] == max(neighbor_zs):
            # break ties
            p[2] = 0
    
    return maxima
def best_into_mapping(domain, H, codomain):
    """
    Associates each point in *domain* with the point in *codomain* nearest its image
    under homography *H*. Returns an ordered list of images corresponding to points
    in *domain*, along with some indication of how good or bad the match is.
    """
    RANGE = []
    total_error = 0
    
    for preimage in domain:
        modeled = H * preimage
        
        min_error = None
        image = None
        for point in codomain:
            error = sqdist(htoc(modeled), htoc(point))
            if min_error == None or error < min_error:
                min_error = error
                image = point
        
        total_error += min_error
        RANGE.append(image)
    
    return RANGE, total_error
def _nearest(p, points2):
    """
    Returns the distance from *p* to the nearest other point in *points2*.
    """
    return sqrt(min([ sqdist(p, q) for q in points2 if q != p ]))