示例#1
0
def populate_mesh(verts, faces, count, seed, all_triangles, safe_check):

    bvh = bvh_tree_from_polygons(verts,
                                 faces,
                                 all_triangles=all_triangles,
                                 epsilon=0.0,
                                 safe_check=safe_check)
    np.random.seed(seed)
    x_min, x_max, y_min, y_max, z_min, z_max = calc_bounds(verts)
    low = np.array([x_min, y_min, z_min])
    high = np.array([x_max, y_max, z_max])
    result = []
    done = 0
    iterations = 0
    while True:
        if iterations > MAX_ITERATIONS:
            raise Exception("Iterations limit is reached")
        max_pts = max(count, count - done)
        points = np.random.uniform(low, high, size=(max_pts, 3)).tolist()
        points = [p for p in points if point_inside_mesh(bvh, p)]
        n = len(points)
        result.extend(points)
        done += n
        iterations += 1
        if done >= count:
            break
    return result, []
示例#2
0
def lloyd_in_mesh(verts,
                  faces,
                  sites,
                  n_iterations,
                  thickness=None,
                  weight_field=None):
    bvh = BVHTree.FromPolygons(verts, faces)

    if thickness is None:
        x_min, x_max, y_min, y_max, z_min, z_max = calc_bounds(verts)
        thickness = max(x_max - x_min, y_max - y_min, z_max - z_min) / 4.0

    epsilon = 1e-8

    def iteration(points):
        n = len(points)

        all_points = points[:]
        k = 0.5 * thickness
        for p in points:
            p = Vector(p)
            loc, normal, index, distance = bvh.find_nearest(p)
            if distance <= epsilon:
                p1 = p + k * normal
                all_points.append(tuple(p1))

        diagram = Voronoi(all_points)
        centers = []
        for site_idx in range(n):
            region_idx = diagram.point_region[site_idx]
            region = diagram.regions[region_idx]
            region_verts = np.array([diagram.vertices[i] for i in region])
            center = weighted_center(region_verts, weight_field)
            centers.append(tuple(center))
        return centers

    def restrict(points):
        result = []
        for p in points:
            if point_inside_mesh(bvh, p):
                result.append(p)
            else:
                loc, normal, index, distance = bvh.find_nearest(p)
                if loc is not None:
                    result.append(tuple(loc))
        return result

    points = restrict(sites)
    for i in range(n_iterations):
        points = iteration(points)
        points = restrict(points)

    return points
示例#3
0
def voronoi_on_mesh(verts,
                    faces,
                    sites,
                    thickness,
                    spacing=0.0,
                    clip_inner=True,
                    clip_outer=True,
                    do_clip=True,
                    clipping=1.0,
                    mode='REGIONS',
                    precision=1e-8):
    bvh = BVHTree.FromPolygons(verts, faces)
    npoints = len(sites)

    if clipping is None:
        x_min, x_max, y_min, y_max, z_min, z_max = calc_bounds(verts)
        clipping = max(x_max - x_min, y_max - y_min, z_max - z_min) / 2.0

    if mode in {'REGIONS', 'RIDGES'}:
        if clip_inner or clip_outer:
            normals = calc_bvh_normals(bvh, sites)
        k = 0.5 * thickness
        sites = np.array(sites)
        all_points = sites.tolist()
        if clip_outer:
            plus_points = sites + k * normals
            all_points.extend(plus_points.tolist())
        if clip_inner:
            minus_points = sites - k * normals
            all_points.extend(minus_points.tolist())

        return voronoi3d_layer(npoints,
                               all_points,
                               make_regions=(mode == 'REGIONS'),
                               do_clip=do_clip,
                               clipping=clipping)

    else:  # VOLUME, SURFACE
        all_points = sites[:]
        if do_clip:
            for site in sites:
                loc, normal, index, distance = bvh.find_nearest(site)
                if loc is not None:
                    p1 = loc + clipping * normal
                    all_points.append(p1)
        verts, edges, faces = voronoi_on_mesh_bmesh(verts,
                                                    faces,
                                                    len(sites),
                                                    all_points,
                                                    spacing=spacing,
                                                    fill=(mode == 'VOLUME'),
                                                    precision=precision)
        return verts, edges, faces, all_points
示例#4
0
        def process(self):
            if not any(socket.is_linked for socket in self.outputs):
                return

            vertices_s = self.inputs['Vertices'].sv_get()
            clipping_s = self.inputs['Clipping'].sv_get()

            verts_out = []
            edges_out = []
            faces_out = []
            for sites, clipping in zip_long_repeat(vertices_s, clipping_s):
                if isinstance(clipping, (list, tuple)):
                    clipping = clipping[0]

                diagram = Voronoi(sites)
                if self.do_clip:
                    bounds = calc_bounds(sites, clipping)

                if self.out_mode == 'RIDGES':
                    new_verts = diagram.vertices.tolist()
                    new_faces = [e for e in diagram.ridge_vertices if not -1 in e]
                    new_edges = polygons_to_edges([new_faces], True)[0]
                    if self.join:
                        if self.do_clip:
                            new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=False)
                        verts_out.append(new_verts)
                        edges_out.append(new_edges)
                        faces_out.append(new_faces)
                    else:
                        new_verts, new_edges, new_faces = self.split_ridges(new_verts, new_edges, new_faces)
                        if self.do_clip:
                            new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=False, iterate=True)
                        verts_out.extend(new_verts)
                        edges_out.extend(new_edges)
                        faces_out.extend(new_faces)
                else: # REGIONS
                    new_verts, new_edges, new_faces = self.make_regions(diagram)
                    if self.join:
                        new_verts, new_edges, new_faces = mesh_join(new_verts, new_edges, new_faces)
                        new_verts = [new_verts]
                        new_edges = [new_edges]
                        new_faces = [new_faces]
                    if self.do_clip:
                        new_verts, new_edges, new_faces = self.clip_mesh(bounds, new_verts, new_edges, new_faces, fill=True)
                    verts_out.extend(new_verts)
                    edges_out.extend(new_edges)
                    faces_out.extend(new_faces)

            self.outputs['Vertices'].sv_set(verts_out)
            self.outputs['Edges'].sv_set(edges_out)
            self.outputs['Faces'].sv_set(faces_out)
示例#5
0
def voronoi3d_regions(sites,
                      closed_only=True,
                      recalc_normals=True,
                      do_clip=False,
                      clipping=1.0):
    diagram = Voronoi(sites)
    faces_per_site = defaultdict(list)
    nsites = len(diagram.point_region)
    nridges = len(diagram.ridge_points)
    open_sites = set()
    for ridge_idx in range(nridges):
        site_idx_1, site_idx_2 = diagram.ridge_points[ridge_idx]
        face = diagram.ridge_vertices[ridge_idx]
        if -1 in face:
            open_sites.add(site_idx_1)
            open_sites.add(site_idx_2)
            continue
        faces_per_site[site_idx_1].append(face)
        faces_per_site[site_idx_2].append(face)

    new_verts = []
    new_edges = []
    new_faces = []

    for site_idx in sorted(faces_per_site.keys()):
        if closed_only and site_idx in open_sites:
            continue
        done_verts = dict()
        bm = bmesh.new()
        add_vert = bm.verts.new
        add_face = bm.faces.new
        for face in faces_per_site[site_idx]:
            face_bm_verts = []
            for vertex_idx in face:
                if vertex_idx not in done_verts:
                    bm_vert = add_vert(diagram.vertices[vertex_idx])
                    done_verts[vertex_idx] = bm_vert
                else:
                    bm_vert = done_verts[vertex_idx]
                face_bm_verts.append(bm_vert)
            add_face(face_bm_verts)
        bm.verts.index_update()
        bm.verts.ensure_lookup_table()
        bm.faces.index_update()
        bm.edges.index_update()

        if closed_only and any(v.is_boundary for v in bm.verts):
            bm.free()
            continue

        if recalc_normals:
            bm.normal_update()
            bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])

        region_verts, region_edges, region_faces = pydata_from_bmesh(bm)
        bm.free()
        new_verts.append(region_verts)
        new_edges.append(region_edges)
        new_faces.append(region_faces)

    if do_clip:
        verts_n, edges_n, faces_n = [], [], []
        bounds = calc_bounds(sites, clipping)
        for verts_i, edges_i, faces_i in zip(new_verts, new_edges, new_faces):
            bm = bmesh_from_pydata(verts_i, edges_i, faces_i)
            bmesh_clip(bm, bounds, fill=True)
            bm.normal_update()
            bmesh.ops.recalc_face_normals(bm, faces=bm.faces[:])
            verts_i, edges_i, faces_i = pydata_from_bmesh(bm)
            bm.free()
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        new_verts, new_edges, new_faces = verts_n, edges_n, faces_n

    return new_verts, new_edges, new_faces
示例#6
0
def voronoi3d_layer(n_src_sites,
                    all_sites,
                    make_regions,
                    do_clip,
                    clipping,
                    skip_added=True):
    diagram = Voronoi(all_sites)
    src_sites = all_sites[:n_src_sites]

    region_verts = dict()
    region_verts_map = dict()
    n_sites = n_src_sites if skip_added else len(all_sites)
    for site_idx in range(n_sites):
        region_idx = diagram.point_region[site_idx]
        region = diagram.regions[region_idx]
        vertices = [tuple(diagram.vertices[i, :]) for i in region]
        region_verts[site_idx] = vertices
        region_verts_map[site_idx] = {
            vert_idx: i
            for i, vert_idx in enumerate(region)
        }

    open_sites = set()
    region_faces = defaultdict(list)
    for ridge_idx, sites in enumerate(diagram.ridge_points):
        site_from, site_to = sites
        ridge = diagram.ridge_vertices[ridge_idx]
        if -1 in ridge:
            open_sites.add(site_from)
            open_sites.add(site_to)

        site_from_ok = not skip_added or site_from < n_src_sites
        site_to_ok = not skip_added or site_to < n_src_sites

        if make_regions:
            if site_from_ok:
                face_from = [region_verts_map[site_from][i] for i in ridge]
                region_faces[site_from].append(face_from)

            if site_to_ok:
                face_to = [region_verts_map[site_to][i] for i in ridge]
                region_faces[site_to].append(face_to)
        else:
            if site_from_ok and site_to_ok:
                face_from = [region_verts_map[site_from][i] for i in ridge]
                region_faces[site_from].append(face_from)
                face_to = [region_verts_map[site_to][i] for i in ridge]
                region_faces[site_to].append(face_to)

    verts = [region_verts[i] for i in range(n_sites) if i not in open_sites]
    faces = [region_faces[i] for i in range(n_sites) if i not in open_sites]

    empty_faces = [len(f) == 0 for f in faces]
    verts = [vs for vs, mask in zip(verts, empty_faces) if not mask]
    faces = [fs for fs, mask in zip(faces, empty_faces) if not mask]
    edges = polygons_to_edges(faces, True)

    if not make_regions:
        verts_n, edges_n, faces_n = [], [], []
        for verts_i, edges_i, faces_i in zip(verts, edges, faces):
            used_verts = set(sum(faces_i, []))
            mask = [i in used_verts for i in range(len(verts_i))]
            verts_i, edges_i, faces_i = mask_vertices(verts_i, edges_i,
                                                      faces_i, mask)
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        verts, edges, faces = verts_n, edges_n, faces_n

    if do_clip:
        verts_n, edges_n, faces_n = [], [], []
        bounds = calc_bounds(src_sites, clipping)
        for verts_i, edges_i, faces_i in zip(verts, edges, faces):
            bm = bmesh_from_pydata(verts_i, edges_i, faces_i)
            bmesh_clip(bm, bounds, fill=True)
            verts_i, edges_i, faces_i = pydata_from_bmesh(bm)
            bm.free()
            verts_n.append(verts_i)
            edges_n.append(edges_i)
            faces_n.append(faces_i)
        verts, edges, faces = verts_n, edges_n, faces_n

    return verts, edges, faces