def example_import_mesh_from_arrays(): # lines needed to run this specific example print('\n') from . import samples_common output_path = samples_common.test_output_path() # create a numpy 8x3 array of vertices # columns are the coordinates (x, y, z) # every row represents a vertex verts = numpy.array([[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5]]) # create a numpy 12x3 array of faces # every row represents a face (trianlge in this case) # for every triangle, the index of the vertex # in the vertex array faces = numpy.array([[2, 1, 0], [1, 2, 3], [4, 2, 0], [2, 4, 6], [1, 4, 0], [4, 1, 5], [6, 5, 7], [5, 6, 4], [3, 6, 7], [6, 3, 2], [5, 3, 7], [3, 5, 1]]) # create a new Mesh with the two arrays m = pymeshlab.Mesh(verts, faces) assert m.vertex_number() == 8 assert m.face_number() == 12 # create a new MeshSet ms = pymeshlab.MeshSet() # add the mesh to the MeshSet ms.add_mesh(m, "cube_mesh") # save the current mesh ms.save_current_mesh(output_path + "saved_cube_from_array.ply") # create a 1D numpy array of 8 elements to store per vertex quality vert_quality = numpy.array([1, 2, 3, 4, 5, 6, 7, 8]) # create a 1D numpy array of 12 elements to store per face quality face_quality = numpy.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]) # create a new mesh with the selected arrays m1 = pymeshlab.Mesh(vertex_matrix=verts, face_matrix=faces, v_quality_array=vert_quality, f_quality_array=face_quality) # add the mesh to the MeshSet ms.add_mesh(m1, "cube_quality_mesh") # colorize the cube according to the per face and per vertex quality ms.colorize_by_vertex_quality() ms.colorize_by_face_quality() # save the mesh ms.save_current_mesh(output_path + "colored_cube_from_array.ply")
def __init__(self, point_cloud_file="", output_file="", filter_script_file="", clean_up=True): self.mesh_set = pymeshlab.MeshSet() self.point_cloud = pymeshlab.Mesh() self.mesh = pymeshlab.Mesh() super().__init__(point_cloud_file, output_file, filter_script_file, clean_up)
def example_import_mesh_from_arrays(): # lines needed to run this specific example print('\n') from . import samples_common output_path = samples_common.test_output_path() # create a numpy 8x3 array of vertices # columns are the coordinates (x, y, z) # every row represents a vertex verts = numpy.array([ [-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5]]) # create a numpy 12x3 array of faces # every row represents a face (trianlge in this case) # for every triangle, the index of the vertex # in the vertex array faces = numpy.array([ [2, 1, 0], [1, 2, 3], [4, 2, 0], [2, 4, 6], [1, 4, 0], [4, 1, 5], [6, 5, 7], [5, 6, 4], [3, 6, 7], [6, 3, 2], [5, 3, 7], [3, 5, 1]]) # create a new Mesh with the two arrays m = pymeshlab.Mesh(verts, faces) assert m.vertex_number() == 8 assert m.face_number() == 12 # create a new MeshSet ms = pymeshlab.MeshSet() # add the mesh to the MeshSet ms.add_mesh(m, "cube_mesh") # save the current mesh ms.save_current_mesh(output_path + "saved_cube_from_array.ply")
def exportMeshToMeshLab(blenderMesh): # NB pymeshlab is fussy # verts and faces have to be provided in a numpy array with verts as type float64 and faces as int32 # faces have to be triangulated - quads and ngons are not allowed verts = [] #numpyp.empty((0,3), float64) for v in blenderMesh.vertices: verts.append([v.co[0], v.co[1], v.co[2]]) verts = numpy.asarray(verts, dtype=numpy.float64) if len(verts) == 0: print("No vertices were found, so function aborting") return # print(verts.shape) # must report (numOfVerts, 3) # print(verts.dtype.name) # must report float64 faces = [] tooManyVerts = False for poly in blenderMesh.polygons: curFace = [] for loop_index in range(poly.loop_start, poly.loop_start + poly.loop_total): curFace.append(blenderMesh.loops[loop_index].vertex_index) if len(curFace) == 3: faces.append(curFace) else: tooManyVerts = True if tooManyVerts: print("WARNING: Meshlab will only accept faces with THREE vertices") if len(faces) == 0: print("No triangular faces were found, so function aborting") return faces = numpy.asarray(faces, dtype=numpy.int32) # print(faces.shape) # must report (numOfVerts, 3) # print(faces.dtype.name) # create a new Mesh with the two arrays meshlabMesh = pymeshlab.Mesh(verts, faces) # create a new MeshSet (a meshset can have multiple meshes each in a differnt layer - but that's not covered with this function) meshlabMeshSet = pymeshlab.MeshSet() # add the mesh to the MeshSet with the current name meshlabMeshSet.add_mesh(meshlabMesh, blenderMesh.name) return meshlabMeshSet
def example_import_poly_mesh_from_arrays(): # lines needed to run this specific example print('\n') from . import samples_common output_path = samples_common.test_output_path() # create a numpy 8x3 array of vertices # columns are the coordinates (x, y, z) # every row represents a vertex verts = numpy.array([[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5]]) # create a list of 6 polygonal faces # every row represents a face (quads in this case) # faces do not need to have all the same number of vertex indices faces = [[0, 2, 3, 1], [0, 4, 6, 2], [0, 1, 5, 4], [7, 6, 4, 5], [7, 3, 2, 6], [7, 5, 1, 3]] # create a new Mesh with the two arrays m = pymeshlab.Mesh(verts, faces) assert m.vertex_number() == 8 # number of faces of the mesh remains 12, since meshes in meshlab are stored as triangle meshes # with faux edges assert m.face_number() == 12 # when creating a mesh from a polymesh, a custom per face scalar attribute is added to the newly created mesh # storing the birth polygon faces for each triangle # get the birth polygon for each face of the mesh birth_faces = m.face_custom_scalar_attribute_array('poly_birth_faces') print(birth_faces) # the birth face of triangle with id 5 is 2 assert (birth_faces[5] == 2) # create a new MeshSet ms = pymeshlab.MeshSet() # add the mesh to the MeshSet (note: ms contains a *copy* of m) ms.add_mesh(m, "cube_mesh") # save the current mesh # obj format in meshlab supports saving polygonal meshes ms.save_current_mesh(output_path + "saved_polygonal_cube_from_array.obj")
def test_import_mesh_from_array(): print('\n') output_path = samples_common.test_output_path() verts = numpy.array([[-0.5, -0.5, -0.5], [0.5, -0.5, -0.5], [-0.5, 0.5, -0.5], [0.5, 0.5, -0.5], [-0.5, -0.5, 0.5], [0.5, -0.5, 0.5], [-0.5, 0.5, 0.5], [0.5, 0.5, 0.5]]) faces = numpy.array([[2, 1, 0], [1, 2, 3], [4, 2, 0], [2, 4, 6], [1, 4, 0], [4, 1, 5], [6, 5, 7], [5, 6, 4], [3, 6, 7], [6, 3, 2], [5, 3, 7], [3, 5, 1]]) m = ml.Mesh(verts, faces) assert m.vertex_number() == 8 assert m.face_number() == 12 ms = ml.MeshSet() ms.add_mesh(m, "cube_mesh") ms.save_current_mesh(output_path + "saved_cube_from_array.ply")
def get_pointclouds(self, num_points=None) -> PointClouds3D: """ Returns points, normals and color in object coordinate """ if hasattr(self, 'point_clouds'): if num_points is None or ( self.point_clouds.points_packed().shape[0] == num_points): return self.point_clouds if num_points is None or num_points == self.data_dict['points'].shape[ 0]: points = torch.tensor( self.data_dict["points"]).to(dtype=torch.float32) normals = torch.tensor( self.data_dict["normals"]).to(dtype=torch.float32) colors = torch.tensor( self.data_dict["colors"]).to(dtype=torch.float32) self.point_clouds = PointClouds3D([points], [normals], [colors]) else: import pymeshlab meshes = self.get_meshes() # sample on the mesh with poisson disc sampling points_list = [] normals_list = [] for i in range(len(meshes)): mesh = meshes[i] m = pymeshlab.Mesh(mesh.verts_packed().cpu().numpy(), mesh.faces_packed().cpu().numpy()) breakpoint() ms = pymeshlab.MeshSet() ms.add_mesh(m, 'mesh0') ms.poisson_disk_sampling(samplenum=num_points, approximategeodesicdistance=True, exactnumflag=True) m = ms.current_mesh() points = m.vertex_matrix().astype(np.float32) normals = m.vertex_normal_matrix().astype(np.float32) points_list.append(torch.from_numpy(points)) normals_list.append(torch.from_numpy(normals)) self.point_clouds = PointClouds3D(points_list, normals_list) return self.point_clouds
"""pymeshlab interoperability example: Surface reconstruction by ball pivoting""" import pymeshlab import vedo pts = vedo.Mesh(vedo.dataurl + 'cow.vtk').points() # numpy array of vertices m = pymeshlab.Mesh(vertex_matrix=pts) ms = pymeshlab.MeshSet() ms.add_mesh(m) ms.surface_reconstruction_ball_pivoting(ballradius=0.15) # ms.compute_normals_for_point_sets() # ms.surface_reconstruction_screened_poisson() mlab_mesh = ms.current_mesh() reco_mesh = vedo.Mesh(mlab_mesh).computeNormals().flat() vedo.show(__doc__, reco_mesh, axes=True, bg2='blue9', title="vedo + pymeshlab") ################################################################################ # Full list of filters, https://pymeshlab.readthedocs.io/en/latest/filter_list.html # # MeshLab offers plenty of useful filters, among which: # # ambient_occlusion # compute_curvature_principal_directions # colorize_by_geodesic_distance_from_a_given_point # colorize_by_border_distance
def simplify_mesh_pyml(x, F, method='quadric', inplace=False, **kwargs): """Simplify mesh using pymeshlab. Parameters ---------- x : MeshNeuron | Volume | Trimesh Mesh object to simplify. F : float [0-1] For method "quadric" this is the target number of faces as fraction of the original face count. For method "cluster" this is the size of the cells used for clustering: larger values = coarser mesh. method : "quadric" | "cluster" Which method to use for simplification: quadratic mesh decimation or vertex clustering. inplace : bool If True, will perform simplication on ``x``. If False, will simplify and return a copy. **kwargs Passed to pymeshlab filter functions: `simplification_quadric_edge_collapse_decimation` or `simplification_clustering_decimation` depending on method. Returns ------- simp Simplified mesh-like object. """ try: with warnings.catch_warnings(): warnings.simplefilter("ignore") import pymeshlab except ImportError: raise ImportError('Please install pymeshlab: pip3 install pymeshlab') except BaseException: raise utils.eval_param(method, name='method', allowed_values=('quadric', 'cluster')) if not isinstance(x, (core.MeshNeuron, tm.Trimesh, core.Volume)): raise TypeError( f'Expected MeshNeuron, Volume or Trimesh, got "{type(x)}"') if (F <= 0) or (F >= 1): raise ValueError(f'`t` must be between 0-1, got {F}') verts, faces = x.vertices, x.faces # Create mesh from vertices and faces m = pymeshlab.Mesh(verts, faces) # Create a new MeshSet ms = pymeshlab.MeshSet() # Add the mesh to the MeshSet ms.add_mesh(m, "mymesh") # Apply filter if method == 'quadric': defaults = {'targetperc': F} defaults.update(kwargs) ms.simplification_quadric_edge_collapse_decimation(**defaults) else: # Threshold is for some reason in percent, not fraction defaults = {'thresholds': F * 100} defaults.update(kwargs) ms.simplification_clustering_decimation(**defaults) # Get update mesh m2 = ms.current_mesh() # Get new vertices and faces new_verts = m2.vertex_matrix() new_faces = m2.face_matrix() # Make copy of the original mesh and assign new vertices + faces if not inplace: x = x.copy() x.vertices = new_verts x.faces = new_faces if isinstance(x, core.MeshNeuron): x._clear_temp_attr() return x
if faces.shape[0] != max_faces: print("Model with more than {} faces ({}): {}".format(max_faces, faces.shape[0], out_dir)) continue # move to center center = (np.max(vertices, 0) + np.min(vertices, 0)) / 2 vertices -= center # normalize max_len = np.max(vertices[:, 0]**2 + vertices[:, 1]**2 + vertices[:, 2]**2) vertices /= np.sqrt(max_len) # get normal vector ms.clear() mesh = pymeshlab.Mesh(vertices, faces) ms.add_mesh(mesh) face_normal = ms.current_mesh().face_normal_matrix() # get neighbors faces_contain_this_vertex = [] for i in range(len(vertices)): faces_contain_this_vertex.append(set([])) centers = [] corners = [] for i in range(len(faces)): [v1, v2, v3] = faces[i] x1, y1, z1 = vertices[v1] x2, y2, z2 = vertices[v2] x3, y3, z3 = vertices[v3] centers.append([(x1 + x2 + x3) / 3, (y1 + y2 + y3) / 3, (z1 + z2 + z3) / 3])
def main(): argv = sys.argv argv = argv[argv.index("--") + 1:] # get all args after "--" inputPath = argv[0] # "output" inputExt = argv[1] # "_final.ply" samplePercentage = float(argv[2]) #0.1 minStrokePoints = int(argv[3]) #2 la = latk.Latk() la.layers.append(latk.LatkLayer()) counter = 0 urls = [] for fileName in os.listdir(inputPath): if fileName.endswith(inputExt): url = os.path.abspath(os.path.join(inputPath, fileName)) urls.append(url) urls.sort() la = latk.Latk() layer = latk.LatkLayer() la.layers.append(layer) for i in range(0, len(urls)): frame = latk.LatkFrame(frame_number=i) la.layers[0].frames.append(frame) for i in range(0, len(urls)): print("\nLoading meshes " + str(i + 1) + " / " + str(len(urls))) ms = ml.MeshSet() ms.load_new_mesh(urls[i]) mesh = ms.current_mesh() newSampleNum = int(mesh.vertex_number() * samplePercentage) if (mesh.edge_number() == 0 and mesh.face_number() == 0): ms.poisson_disk_sampling(samplenum=newSampleNum, subsample=True) else: ms.poisson_disk_sampling(samplenum=newSampleNum, subsample=False) ms.surface_reconstruction_ball_pivoting() ms.vertex_attribute_transfer(sourcemesh=0, targetmesh=1) ms.save_current_mesh("input.ply", save_vertex_color=True) os.system("SynDraw -p test.template") print("parsing SVG") tree = etree.parse("out.svg") root = tree.getroot() for element in root: if (element.tag.endswith("polyline")): points = element.get("points3d").split(" ") lPoints = [] for point in points: point2 = point.split(",") try: point3 = (float(point2[0]), float(point2[2]), float(point2[1])) lPoints.append(latk.LatkPoint(point3)) except: pass if (len(lPoints) >= minStrokePoints): la.layers[0].frames[counter].strokes.append( latk.LatkStroke(lPoints)) allPoints = [] for stroke in la.layers[0].frames[counter].strokes: for point in stroke.points: allPoints.append([point.co[0], point.co[2], point.co[1]]) vertices = np.array(allPoints) faces = np.array([[0, 0, 0]]) mesh = ml.Mesh(vertices, faces) ms.add_mesh(mesh) ms.vertex_attribute_transfer(sourcemesh=1, targetmesh=2) strokeCounter = 0 pointCounter = 0 vertexColors = ms.current_mesh().vertex_color_matrix() for vertexColor in vertexColors: color = (vertexColor[0], vertexColor[1], vertexColor[2], 1.0) color = (color[0] * color[0], color[1] * color[1], color[2] * color[2], 1.0) la.layers[0].frames[counter].strokes[strokeCounter].points[ pointCounter].vertex_color = color pointCounter += 1 if (pointCounter > len( la.layers[0].frames[counter].strokes[strokeCounter].points) - 1): pointCounter = 0 strokeCounter += 1 print("Finished frame " + str(counter + 1)) counter += 1 la.write("output.latk") print("Wrote latk")
def process_mesh(path, max_faces): ms = pymeshlab.MeshSet() ms.clear() # load mesh ms.load_new_mesh(path) mesh = ms.current_mesh() # # clean up # mesh, _ = pymesh.remove_isolated_vertices(mesh) # mesh, _ = pymesh.remove_duplicated_vertices(mesh) # get elements vertices = mesh.vertex_matrix() faces = mesh.face_matrix() if faces.shape[ 0] != max_faces: # only occur once in train set of Manifold40 print("Model with more than {} faces ({}): {}".format( max_faces, faces.shape[0], path)) return None, None # move to center center = (np.max(vertices, 0) + np.min(vertices, 0)) / 2 vertices -= center # normalize max_len = np.max(vertices[:, 0]**2 + vertices[:, 1]**2 + vertices[:, 2]**2) vertices /= np.sqrt(max_len) # get normal vector ms.clear() mesh = pymeshlab.Mesh(vertices, faces) ms.add_mesh(mesh) face_normal = ms.current_mesh().face_normal_matrix() # get neighbors faces_contain_this_vertex = [] for i in range(len(vertices)): faces_contain_this_vertex.append(set([])) centers = [] corners = [] for i in range(len(faces)): [v1, v2, v3] = faces[i] x1, y1, z1 = vertices[v1] x2, y2, z2 = vertices[v2] x3, y3, z3 = vertices[v3] centers.append([(x1 + x2 + x3) / 3, (y1 + y2 + y3) / 3, (z1 + z2 + z3) / 3]) corners.append([x1, y1, z1, x2, y2, z2, x3, y3, z3]) faces_contain_this_vertex[v1].add(i) faces_contain_this_vertex[v2].add(i) faces_contain_this_vertex[v3].add(i) neighbors = [] for i in range(len(faces)): [v1, v2, v3] = faces[i] n1 = find_neighbor(faces, faces_contain_this_vertex, v1, v2, i) n2 = find_neighbor(faces, faces_contain_this_vertex, v2, v3, i) n3 = find_neighbor(faces, faces_contain_this_vertex, v3, v1, i) neighbors.append([n1, n2, n3]) centers = np.array(centers) corners = np.array(corners) faces = np.concatenate([centers, corners, face_normal], axis=1) neighbors = np.array(neighbors) return faces, neighbors