def trivial_mesher(self):
            solids = self.inputs[self["shape_type"]].sv_get()

            verts = []
            faces = []
            for solid in solids:
                if self.shape_type == 'Solid':
                    shape = solid
                else:
                    shape = solid.face
                new_verts, new_edges, new_faces = mesh_from_solid_faces(shape)
                new_verts, new_edges, new_faces = recalc_normals(
                    new_verts, new_edges, new_faces)

                verts.append(new_verts)
                faces.append(new_faces)

            return verts, faces
        def trivial_mesher(self):
            """
            this mode will produce a variety of polygon types (tris, quads, ngons...)
            """
            solids = self.inputs[self["shape_type"]].sv_get()

            verts = []
            faces = []
            for solid in solids:
                if self.shape_type == 'Solid':
                    shape = solid
                else:
                    shape = solid.face

                new_verts, new_edges, new_faces = mesh_from_solid_faces(shape)
                new_verts, new_edges, new_faces = recalc_normals(
                    new_verts, new_edges, new_faces)

                verts.append(new_verts)
                faces.append(new_faces)

            return verts, faces
Exemple #3
0
    def process(self):

        if not any(socket.is_linked for socket in self.outputs):
            return

        verts_in = self.inputs['Vertices'].sv_get(deepcopy=False)
        faces_in = self.inputs['Faces'].sv_get(deepcopy=False)
        sites_in = self.inputs['Sites'].sv_get(deepcopy=False)
        #thickness_in = self.inputs['Thickness'].sv_get()
        spacing_in = self.inputs['Spacing'].sv_get(deepcopy=False)

        verts_in = ensure_nesting_level(verts_in, 4)
        input_level = get_data_nesting_level(sites_in)
        sites_in = ensure_nesting_level(sites_in, 4)
        faces_in = ensure_nesting_level(faces_in, 4)
        #thickness_in = ensure_nesting_level(thickness_in, 2)
        spacing_in = ensure_nesting_level(spacing_in, 2)

        nested_output = input_level > 3

        precision = 10 ** (-self.accuracy)

        verts_out = []
        edges_out = []
        faces_out = []
        sites_out = []
        for params in zip_long_repeat(verts_in, faces_in, sites_in, spacing_in):
            new_verts = []
            new_edges = []
            new_faces = []
            new_sites = []
            for verts, faces, sites, spacing in zip_long_repeat(*params):
                verts, edges, faces, sites = voronoi_on_mesh(verts, faces, sites, thickness=0,
                            spacing = spacing,
                            #clip_inner = self.clip_inner, clip_outer = self.clip_outer,
                            do_clip=True, clipping=None,
                            mode = self.mode,
                            precision = precision)
                if self.mode == 'VOLUME' and self.normals:
                    verts, edges, faces = recalc_normals(verts, edges, faces, loop=True)

                if self.join_mode == 'FLAT':
                    new_verts.extend(verts)
                    new_edges.extend(edges)
                    new_faces.extend(faces)
                    new_sites.extend(sites)
                elif self.join_mode == 'SEPARATE':
                    new_verts.append(verts)
                    new_edges.append(edges)
                    new_faces.append(faces)
                    new_sites.append(sites)
                else: # JOIN
                    verts, edges, faces = mesh_join(verts, edges, faces)
                    new_verts.append(verts)
                    new_edges.append(edges)
                    new_faces.append(faces)
                    new_sites.append(sites)

            if nested_output:
                verts_out.append(new_verts)
                edges_out.append(new_edges)
                faces_out.append(new_faces)
                sites_out.append(new_sites)
            else:
                verts_out.extend(new_verts)
                edges_out.extend(new_edges)
                faces_out.extend(new_faces)
                sites_out.extend(new_sites)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
Exemple #4
0
def alpha_shape(verts, alpha, fix_normals=True, volume_threshold=1e-4):
    """
    Compute the alpha shape (concave hull) of a set of 3D points.
    Parameters:
        verts - np.array of shape (n, 3) points.
        alpha - alpha value.
    return
        outer surface edge indices and triangle indices
    """
    def calc_volume(tetra_verts):
        a = tetra_verts[:, 0, :]
        b = tetra_verts[:, 1, :]
        c = tetra_verts[:, 2, :]
        d = tetra_verts[:, 3, :]

        e1 = b - a
        e2 = c - a
        e3 = d - a

        e1 /= np.linalg.norm(e1, axis=1, keepdims=True)
        e2 /= np.linalg.norm(e2, axis=1, keepdims=True)
        e3 /= np.linalg.norm(e3, axis=1, keepdims=True)

        volume = np.cross(e1, e2)
        volume = (volume * e3).sum(axis=1) / 6
        return abs(volume)

    alpha2 = alpha**2
    tetra = Delaunay(verts)
    # Find radius of the circumsphere.
    # By definition, radius of the sphere fitting inside the tetrahedral needs
    # to be smaller than alpha value
    # http://mathworld.wolfram.com/Circumsphere.html
    tetra_verts = np.take(verts, tetra.simplices,
                          axis=0)  # (n_simplices, 4, 3)
    normsq = np.sum(tetra_verts**2, axis=2)[:, :, None]
    ones = np.ones((tetra_verts.shape[0], tetra_verts.shape[1], 1))
    a = np.linalg.det(np.concatenate((tetra_verts, ones), axis=2))
    Dx = np.linalg.det(
        np.concatenate((normsq, tetra_verts[:, :, [1, 2]], ones), axis=2))
    Dy = -np.linalg.det(
        np.concatenate((normsq, tetra_verts[:, :, [0, 2]], ones), axis=2))
    Dz = np.linalg.det(
        np.concatenate((normsq, tetra_verts[:, :, [0, 1]], ones), axis=2))
    c = np.linalg.det(np.concatenate((normsq, tetra_verts), axis=2))
    r2 = (Dx**2 + Dy**2 + Dz**2 - 4 * a * c) / (4 * np.abs(a)**2)

    small_radius = r2 < alpha2
    volumes = calc_volume(tetra_verts)
    non_planar = volumes >= volume_threshold
    good = np.logical_and(small_radius, non_planar)

    # Find tetrahedrals
    tetras = tetra.simplices[good, :]
    # triangles
    triangle_combinations = np.array([(0, 1, 2), (0, 1, 3), (0, 2, 3),
                                      (1, 2, 3)])
    triangles = tetras[:, triangle_combinations].reshape(-1, 3)
    triangles = np.sort(triangles, axis=1)
    # Remove triangles that occurs twice, because they are within shapes
    triangles_dict = defaultdict(int)
    for tri in triangles:
        triangles_dict[tuple(tri)] += 1
    triangles = np.array(
        [tri for tri in triangles_dict if triangles_dict[tri] == 1])
    #edges
    edges_comb = np.array([(0, 1), (0, 2), (1, 2)])
    edges = triangles[:, edges_comb].reshape(-1, 2)
    edges = np.sort(edges, axis=1)
    edges = np.unique(edges, axis=0)

    edges = edges.tolist()
    triangles = triangles.tolist()

    used_vert_idxs = set()
    for triangle in triangles:
        used_vert_idxs.update(set(triangle))
    verts_mask = [i in used_vert_idxs for i in range(len(verts))]

    verts, edges, faces = mask_vertices(verts, edges, triangles, verts_mask)
    if fix_normals:
        verts, edges, faces = recalc_normals(verts, edges, faces)

    return verts, edges, faces
Exemple #5
0
    def process(self):

        if not any(socket.is_linked for socket in self.outputs):
            return

        surface_in = self.inputs['Surface'].sv_get()
        uvpoints_in = self.inputs['UVPoints'].sv_get()
        maxsides_in = self.inputs['MaxSides'].sv_get()
        thickness_in = self.inputs['Thickness'].sv_get()
        clipping_in = self.inputs['Clipping'].sv_get()

        surface_in = ensure_nesting_level(surface_in,
                                          2,
                                          data_types=(SvSurface, ))
        input_level = get_data_nesting_level(uvpoints_in)
        uvpoints_in = ensure_nesting_level(uvpoints_in, 4)
        maxsides_in = ensure_nesting_level(maxsides_in, 2)
        thickness_in = ensure_nesting_level(thickness_in, 2)
        clipping_in = ensure_nesting_level(clipping_in, 2)

        nested_output = input_level > 3

        verts_out = []
        edges_out = []
        faces_out = []
        uvverts_out = []
        for params in zip_long_repeat(surface_in, uvpoints_in, maxsides_in,
                                      thickness_in, clipping_in):
            new_verts = []
            new_edges = []
            new_faces = []
            new_uvverts = []
            for surface, uvpoints, maxsides, thickness, clipping in zip_long_repeat(
                    *params):
                if self.mode == 'UV':
                    uvverts, verts, edges, faces = self.voronoi_uv(
                        surface, uvpoints, maxsides)
                    new_uvverts.append(uvverts)
                else:
                    verts, edges, faces = voronoi_on_surface(
                        surface, uvpoints, thickness, self.do_clip, clipping,
                        self.mode == 'REGIONS')

                if (self.mode in {'RIDGES', 'REGIONS'}
                        or self.make_faces) and self.normals:
                    verts, edges, faces = recalc_normals(
                        verts,
                        edges,
                        faces,
                        loop=(self.mode in {'REGIONS', 'RIDGES'}))

                new_verts.append(verts)
                new_edges.append(edges)
                new_faces.append(faces)

            if self.mode in {'RIDGES', 'REGIONS'} and self.flat_output:
                new_verts = sum(new_verts, [])
                new_edges = sum(new_edges, [])
                new_faces = sum(new_faces, [])

            if nested_output:
                verts_out.append(new_verts)
                edges_out.append(new_edges)
                faces_out.append(new_faces)
                if self.mode == 'UV':
                    uvverts_out.append(new_uvverts)
            else:
                verts_out.extend(new_verts)
                edges_out.extend(new_edges)
                faces_out.extend(new_faces)
                if self.mode == 'UV':
                    uvverts_out.extend(new_uvverts)

        self.outputs['Vertices'].sv_set(verts_out)
        self.outputs['Edges'].sv_set(edges_out)
        self.outputs['Faces'].sv_set(faces_out)
        self.outputs['UVVertices'].sv_set(uvverts_out)