Example #1
0
def draw_vor(pos, partition):

    # stack coordinates of nodes in coor_lis to draw the Voronoi Diagram
    # indices of coor_lis correspond to the node
    coor_lis = []
    for p in range(0, len(pos.keys())):
        coor_lis.append(pos[str(p)])
    vor = Voronoi(np.stack(coor_lis))
    
    # build dictionary to store community info
    # com_node = {community: [nodes in community]}
    com_node = {}
    for p, com in partition.items():
        com_node.setdefault(com, []).append(p)

    # merge voronoi cells for each community
    # record attributes of vor needed to be modified
    regions_remove = []
    point_region_remove = []
    ridge_points_remove = []
    ridge_vertices_remove = []
    vor_ridge_points = vor.ridge_points.tolist()
    vor_point_region = vor.point_region.tolist()
    for p_lis in com_node.values():
        regions_lis, point_region_lis, ridge_points_lis, ridge_vertices_lis\
             = merge_vor(vor_ridge_points, vor.ridge_vertices, vor.regions, vor_point_region, p_lis)
        regions_remove += regions_lis
        point_region_remove += point_region_lis
        ridge_points_remove += ridge_points_lis
        ridge_vertices_remove += ridge_vertices_lis

    # modified attributes of vor
    # vor.point_region
    for r in point_region_remove:
        vor_point_region.remove(r)
    vor.point_region = np.array(vor_point_region)

    # vor.regions
    for i in regions_remove:
        vor.regions.remove(i)
    
    # vor.ridge_points
    for pair in ridge_points_remove:
        vor_ridge_points.remove(pair)
    vor.ridge_points = np.array(vor_ridge_points)

    # vor.ridge_vertices
    for pair in ridge_vertices_remove:
        try: vor.ridge_vertices.remove(pair)
        except:
            v1, v2 = pair
            vor.ridge_vertices.remove([v2, v1])

    # plot Voronoi diagram
    voronoi_plot_2d(vor, show_vertices=False, line_width=0)
    plt.show()
Example #2
0
def finite_voronoi(vor, scale=1):
    """
    finite_voronoi(vor, scale=1)

    Construct finite boundaries for Voronoi diagram.

    Parameters
    ----------
    points : ndarray of floats, shape (npoints, 2)
        Coordinates of points to construct a convex hull from
    scale : float, optional
        Scale of extension lines. Some points may be outside their associated
        region if scale < 1

    Attributes
    ----------
    points : ndarray of double, shape (npoints, 2)
        Coordinates of input points.
    vertices : ndarray of double, shape (nvertices, 2)
        Coordinates of the Voronoi vertices.
    ridge_points : ndarray of ints, shape (nridges, 2)
        Indices of the points between which each Voronoi ridge lies.
    ridge_vertices : list of list of ints, shape (nridges, *)
        Indices of the Voronoi vertices forming each Voronoi ridge.
    regions : list of list of ints, shape (nregions, *)
        Indices of the Voronoi vertices forming each Voronoi region.
    point_region : list of ints, shape (npoints)
        Index of the Voronoi region for each input point.
    """

    vor = Voronoi(points)

    # Calculate size of extension lines
    ptp_bound = vor.points.ptp(axis=0).max() * scale

    # Count number of new vertices required
    nv_existing = len(vor.vertices)
    nv_required = len([v for v in vor.ridge_vertices if v[0] < 0])
    new_vertices = list(range(nv_existing, nv_existing + nv_required))
    outer_vertices = []

    center = vor.points.mean(axis=0)
    for idx, pointidx, simplex in zip(range(len(vor.ridge_points)),
                                      vor.ridge_points, vor.ridge_vertices):
        simplex = np.asarray(simplex)
        if np.any(simplex < 0):

            # Find finite end Voronoi vertex
            i = simplex[simplex >= 0][0]

            # Calculate tangent and normal
            t = vor.points[pointidx[1]] - vor.points[pointidx[0]]
            t /= np.linalg.norm(t)
            n = np.array([-t[1], t[0]])

            # Draw line
            midpoint = vor.points[pointidx].mean(axis=0)
            direction = np.sign(np.dot(midpoint - center, n)) * n
            far_point = vor.vertices[i] + direction * ptp_bound
            outer_vertices.append(list(pointidx))

            # Add start point to ridge vertices
            vor.ridge_vertices[idx][0] = len(vor.vertices)
            vor.vertices = np.vstack([vor.vertices, far_point])

    # Assign points to outer vertices
    outer_points = list(
        set([item for sublist in outer_vertices for item in sublist]))

    for op in outer_points:
        p = [nv for nv, ov in zip(new_vertices, outer_vertices) if op in ov]
        vor.ridge_vertices = np.vstack([vor.ridge_vertices, p])
        vor.ridge_points = np.vstack([vor.ridge_points, [op, -1]])

    # Cycle through points
    for point_idx in range(len(vor.points)):
        region_idx = vor.point_region[point_idx]
        segs = vor.ridge_vertices[(vor.ridge_points == point_idx).any(axis=1)]

        # Remove first point from segment, to force correct direction
        segs[0, 0] = segs[0, 1]

        # Put segments in correct order
        for i in range(1, len(segs)):
            idx = np.where([np.any(np.in1d(segs[i - 1], s))
                            for s in segs[i:]])[0][-1]
            segs[i:] = np.roll(segs[i:], -idx, axis=0)

        # Extract vertices from segments
        pts = segs.flatten()
        _, i = np.unique(pts, return_index=True)
        vor.regions[region_idx] = pts[np.sort(i)]

    return vor