def clean_mesh(mesh, connected=True, fill_internals=False): print('\t - Cleaning mesh (this may take a moment)') vert_list = [] mesh, info = pymesh.remove_isolated_vertices(mesh) mesh, info = pymesh.remove_duplicated_vertices(mesh) mesh, info = pymesh.remove_degenerated_triangles(mesh) mesh, info = pymesh.remove_duplicated_faces(mesh) if connected or fill_internals: mesh_list = pymesh.separate_mesh(mesh, 'auto') max_verts = 0 print(' - Total number of meshes (ideally 1): %d' % len(mesh_list)) for mesh_obj in mesh_list: nverts = mesh_obj.num_vertices if nverts > max_verts: max_verts = nverts mesh = mesh_obj if fill_internals: for mesh_obj in mesh_list: if mesh_obj.num_vertices != max_verts: vert_list.append(mesh_obj.vertices) return mesh, vert_list return mesh, vert_list
def main(): args = parse_args() mesh = load_mesh(args.mesh_in) comps = separate_mesh(mesh, args.connectivity_type) if args.highlight: if (args.connectivity_type == "face"): comp_indicator = np.zeros(mesh.num_faces) elif (args.connectivity_type == "voxel"): comp_indicator = np.zeros(mesh.num_voxels) elif (mesh.num_voxels > 0): comp_indicator = np.zeros(mesh.num_voxels) else: comp_indicator = np.zeros(mesh.num_faces) for i in range(len(comps)): elem_sources = comps[i].get_attribute("ori_elem_index")\ .ravel().astype(int) comp_indicator[elem_sources] = i mesh.add_attribute("component_index") mesh.set_attribute("component_index", comp_indicator) save_mesh(args.mesh_out, mesh, *mesh.get_attribute_names()) else: basename, ext = os.path.splitext(args.mesh_out) for i, comp in enumerate(comps): filename = "{}_cc{}{}".format(basename, i, ext) save_mesh(filename, comp, *comp.get_attribute_names())
def main(): args = parse_args(); mesh = load_mesh(args.mesh_in); comps = separate_mesh(mesh, args.connectivity_type); if args.highlight: if (args.connectivity_type == "face"): comp_indicator = np.zeros(mesh.num_faces); elif (args.connectivity_type == "voxel"): comp_indicator = np.zeros(mesh.num_voxels); elif (mesh.num_voxels > 0): comp_indicator = np.zeros(mesh.num_voxels); else: comp_indicator = np.zeros(mesh.num_faces); for i in range(len(comps)): elem_sources = comps[i].get_attribute("ori_elem_index")\ .ravel().astype(int); comp_indicator[elem_sources] = i; mesh.add_attribute("component_index"); mesh.set_attribute("component_index", comp_indicator); save_mesh(args.mesh_out, mesh, *mesh.get_attribute_names()); else: basename, ext = os.path.splitext(args.mesh_out); for i,comp in enumerate(comps): filename = "{}_cc{}{}".format(basename, i, ext); save_mesh(filename, comp, *comp.get_attribute_names());
def separate_single_mesh(src_mesh, tar_mesh): src_mesh = pymesh.load_mesh(src_mesh) dis_meshes = pymesh.separate_mesh(src_mesh, connectivity_type='auto') pymesh.save_mesh_raw(tar_mesh+".obj", src_mesh.vertices, src_mesh.faces) count=0 for dis_mesh in dis_meshes: print("dis_mesh.vertices.shape",dis_mesh.vertices.shape) print("dis_mesh.faces.shape",dis_mesh.faces.shape) pymesh.save_mesh_raw(tar_mesh+"_"+str(count)+".obj", dis_mesh.vertices, dis_mesh.faces) count+=1
def test_simple(self): mesh_1 = generate_box_mesh(np.zeros(3), np.ones(3)); mesh_2 = generate_box_mesh(np.array([0.5, 0.5, 0.5]), np.ones(3)); out_mesh = merge_meshes([mesh_1, mesh_2]); components = separate_mesh(out_mesh); self.assertEqual(2, len(components)); for comp in components: self.assertEqual(8, comp.num_vertices); self.assertEqual(12, comp.num_faces);
def test_face_connectivity(self): vertices = np.array([ [0, 0, 0], [1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 1], ], dtype=float); faces = np.array([ [0, 1, 2], [2, 3, 4], ]); mesh = form_mesh(vertices, faces); components = separate_mesh(mesh, "vertex"); self.assertEqual(1, len(components)); components = separate_mesh(mesh, "face"); self.assertEqual(2, len(components));
def clean_single_mesh(src_mesh, tar_mesh, dist_thresh, num_thresh): src_mesh_obj = pymesh.load_mesh(src_mesh) dis_meshes = pymesh.separate_mesh(src_mesh_obj, connectivity_type='auto') max_mesh_verts = 0 for dis_mesh in dis_meshes: if dis_mesh.vertices.shape[0] > max_mesh_verts: max_mesh_verts = dis_mesh.vertices.shape[0] collection=[] for dis_mesh in dis_meshes: if dis_mesh.vertices.shape[0] > max_mesh_verts*num_thresh: centroid = np.mean(dis_mesh.vertices, axis=0) if np.sqrt(np.sum(np.square(centroid))) < dist_thresh: collection.append(dis_mesh) tar_mesh_obj = pymesh.merge_meshes(collection) pymesh.save_mesh_raw(tar_mesh, tar_mesh_obj.vertices, tar_mesh_obj.faces) print("threshes:", str(dist_thresh), str(num_thresh), " clean: ", src_mesh, " create: ",tar_mesh)
def separate(vertex, faces, d_max=2): new_faces = list() for face in faces: p1 = vertex[face[0]] p2 = vertex[face[1]] p3 = vertex[face[2]] if not (distance(p1, p2) > d_max or distance(p2, p3) > d_max or distance(p1, p3) > d_max): new_faces.append(face) mesh = form_mesh(np.array(vertex), np.array(new_faces)) meshs = separate_mesh(mesh) max_v = 0 for i in range(len(meshs)): if meshs[i].num_vertices > max_v: max_v = meshs[i].num_vertices mesh = meshs[i] pcloud_2d = cloud2D(mesh.vertices) face = Delaunay(pcloud_2d) face = [(p[0], p[1], p[2]) for p in face.simplices] return parseToList(mesh.vertices), face
def slice(the_mesh, step=1.0, epsilon=0.001): n = math.ceil((the_mesh.bbox[1][2] - the_mesh.bbox[0][2]) / step) print("slicing into %d slices" % (n)) return [[Contour(component) for component in pymesh.separate_mesh(slice)] for slice in pymesh.slice_mesh(the_mesh, numpy.array([0, 0, 1]), n) ]
def __init__(self, path, backplate_thickness=6.35): self.path = path self.reference_mesh = pymesh.load_mesh(path) # we want to separate the submeshes based on face connectivity, # since that will give us all the discrete parts self.submeshes = pymesh.separate_mesh( self.reference_mesh, connectivity_type="face") # get all the pattern meshes, which are the submeshes that are # NOT the: backplate, pattern plate, or fiducial tag locations self.backplate_thickness = backplate_thickness self.pattern_plate_thickness = 3 self.pattern_meshes = [] self.fiducial_meshes = [] self.backplate_mesh = None self.pattern_plate_mesh = None for submesh in self.submeshes: if not submesh.is_closed(): # these are the fiducial marker locations # because they are the ones that are 1-dimensional self.fiducial_meshes.append(submesh) elif (submesh.bbox[0][2] == 0 and submesh.bbox[1][2] == self.backplate_thickness) or \ (submesh.bbox[1][2] == 0 and submesh.bbox[0][2] == self.backplate_thickness): # this is the backplate, since the bounding box extends to 0 self.backplate_mesh = submesh elif (submesh.bbox[0][2] == self.backplate_thickness + self.pattern_plate_thickness and submesh.bbox[1][2] == self.backplate_thickness) or \ (submesh.bbox[1][2] == self.backplate_thickness + self.pattern_plate_thickness and submesh.bbox[0][2] == self.backplate_thickness): # this is the pattern plate, since the bounding box starts # from the end of the backplate and goes the thickness of # the pattern plate self.pattern_plate_mesh = submesh else: self.pattern_meshes.append(submesh) # the fiducial locations on the reference mesh # TODO: generate these automatically from the meshes self.fiducial_locations = { # top left 231: { TOP_LEFT: [-75.5625, 48.575, self.backplate_thickness], TOP_RIGHT: [-55.5625, 48.575, self.backplate_thickness], BOTTOM_RIGHT: [-55.5625, 28.575, self.backplate_thickness], BOTTOM_LEFT: [-75.5625, 28.575, self.backplate_thickness], }, # top right 123: { TOP_LEFT: [55.5625, 48.575, self.backplate_thickness], TOP_RIGHT: [75.5625, 48.575, self.backplate_thickness], BOTTOM_RIGHT: [75.5625, 28.575, self.backplate_thickness], BOTTOM_LEFT: [55.5625, 28.575, self.backplate_thickness], }, # bottom left 114: { TOP_LEFT: [-75.5625, -28.575, self.backplate_thickness], TOP_RIGHT: [-55.5625, -28.575, self.backplate_thickness], BOTTOM_RIGHT: [-55.5625, -48.575, self.backplate_thickness], BOTTOM_LEFT: [-75.5625, -48.575, self.backplate_thickness], }, # bottom right 141: { TOP_LEFT: [55.5625, -28.575, self.backplate_thickness], TOP_RIGHT: [75.5625, -28.575, self.backplate_thickness], BOTTOM_RIGHT: [75.5625, -48.575, self.backplate_thickness], BOTTOM_LEFT: [55.5625, -48.575, self.backplate_thickness], } }
def components(self): comps = pm.separate_mesh(self.mesh) return [Topex(c) for c in comps]
def main(): args = parse_args() mesh = pymesh.load_mesh(args.input_mesh) if not mesh.has_attribute("corner_texture"): raise RuntimeError("Mesh contains no uv!") mesh.add_attribute("face_area") uv = mesh.get_attribute("corner_texture").reshape((-1, 2)) if len(uv) == 0: raise RuntimeError("Invalid uv size.") faces = np.arange(mesh.num_faces * mesh.vertex_per_face).reshape( (-1, mesh.vertex_per_face)) uv_mesh = pymesh.form_mesh(uv, faces) uv_mesh.add_attribute("face_area") ori_area = mesh.get_face_attribute("face_area") uv_area = uv_mesh.get_face_attribute("face_area") area_ratio = np.divide(uv_area, ori_area) uv_mesh.add_attribute("area_ratio") uv_mesh.set_attribute("area_ratio", area_ratio) mesh.add_attribute("area_ratio") mesh.set_attribute("area_ratio", area_ratio) mesh.add_attribute("u") mesh.set_attribute("u", uv[:, 0]) if (args.separate): uv_mesh, info = pymesh.remove_duplicated_vertices(uv_mesh) comps = pymesh.separate_mesh(uv_mesh) segments = [] uv = uv.reshape((-1, 6), order="C") vertices = mesh.vertices combined_uv = [] for comp in comps: ori_vertex_indices = comp.get_attribute( "ori_vertex_index").ravel() ori_elem_indices = comp.get_attribute( "ori_elem_index").ravel().astype(int) segment = pymesh.submesh(mesh, ori_elem_indices, 0) ori_face_indices = segment.get_attribute( "ori_face_index").ravel().astype(int) ori_uv = uv[ori_face_indices] combined_uv.append(ori_uv) segment.add_attribute("corner_texture") segment.set_attribute("corner_texture", ori_uv.ravel()) segments.append(segment) combined_uv = np.vstack(combined_uv) mesh = pymesh.merge_meshes(segments) mesh.add_attribute("corner_texture") mesh.set_attribute("corner_texture", combined_uv.ravel(order="C")) elif args.cut: uv_mesh, info = pymesh.remove_duplicated_vertices(uv_mesh) index_map = info["index_map"] vertices = mesh.vertices faces = mesh.faces vertices = vertices[faces.ravel(order="C")] new_vertices = np.zeros((uv_mesh.num_vertices, 3)) new_vertices[index_map] = vertices mesh = pymesh.form_mesh(new_vertices, uv_mesh.faces) mesh.add_attribute("corner_texture") mesh.set_attribute("corner_texture", uv) if args.save_uv: pymesh.save_mesh(args.output_mesh, uv_mesh, *uv_mesh.attribute_names) else: pymesh.save_mesh(args.output_mesh, mesh, *mesh.attribute_names)