def process_data(self, params): point_clouds_out = [] for vertices, normals, colors in zip(*params): pcd = o3d.geometry.PointCloud() pcd.points = o3d.utility.Vector3dVector(np.array(vertices)) if has_element(normals): pcd.normals = o3d.utility.Vector3dVector(np.array(normals)) elif self.normal_method != 'NONE': calc_point_cloud_normals(pcd, self.normal_quality, self.normal_method) if has_element(colors): pcd.colors = o3d.utility.Vector3dVector( np.array(colors)[:, :3]) point_clouds_out.append(pcd) return point_clouds_out
def edges_length(vertices, edges, sum_length=False, out_numpy=False): ''' calculate edges length using numpy vertices: list as [vertex, vertex, ...] being each vertex [float, float, float]. Also accept numpy arrays with two axis edges: list as [edge, edge,..] being each edge [int, int]. Also accept numpy arrays with one axis sum_length: boolean to determine if outputtig each length or the sum of all out_numpy: boolean to determine if outputtig np_array or regular python list returns length of edges or sum of lengths ''' if not has_element(vertices): return if not has_element(edges): edges = edges_aux(vertices) v_edges = get_v_edges(vertices, edges) vect = v_edges[:, 1, :] - v_edges[:, 0, :] length = np.linalg.norm(vect, axis=1) if sum_length: length = np.sum(length)[np.newaxis] return length if out_numpy else length.tolist()
def process_data(self, params): mesh_out = [] matched = numpy_full_list_cycle vec_3f = o3d.utility.Vector3dVector vec_3i = o3d.utility.Vector3iVector for base_mesh, vertices, verts_normals, verts_colors, faces, f_normals, uv_verts, uv_faces, material_id in zip( *params): if base_mesh: mesh = copy.deepcopy(base_mesh) else: mesh = o3d.geometry.TriangleMesh() if has_element(vertices): np_vertices = np.array(vertices) mesh.vertices = vec_3f(np_vertices) if has_element(faces): try: np_triangles = np.array(faces).astype(np.int32) except ValueError: raise Exception('Only Triangular Faces Accepted') if np_triangles.shape[1] != 3: raise Exception('Only Triangular Faces Accepted') mesh.triangles = vec_3i(np_triangles) vert_len = len(mesh.vertices) tri_len = len(mesh.triangles) if has_element(verts_normals): mesh.vertex_normals = vec_3f( matched(np.array(verts_normals), vert_len)) if has_element(verts_colors): mesh.vertex_colors = vec_3f( matched(np.array(verts_colors)[:, :3], vert_len)) if has_element(f_normals): print(len(f_normals)) mesh.triangle_normals = vec_3f( matched(np.array(f_normals), tri_len)) if has_element(uv_verts) and has_element(uv_faces): np_uv_faces = np.array(uv_faces) np_uv_verts = np.array(uv_verts) uvs_0 = np_uv_verts[np_uv_faces][:, :, :2] uvs = o3d.utility.Vector2dVector( matched(uvs_0, tri_len).reshape(-1, 2)) mesh.triangle_uvs = uvs if len(material_id) > 0: mesh.triangle_material_ids = o3d.utility.IntVector( matched(np.array(material_id), tri_len)) mesh_out.append(mesh) return mesh_out
def calc_mesh_normals_np(vertices, faces, get_f_normals=True, get_v_normals=True, non_planar=True, v_normal_alg='MWE', output_numpy=True): if not has_element(faces): return [], vertices np_verts, np_faces = prepare_arrays(vertices, faces) if get_v_normals: v_normals = np.zeros(np_verts.shape, dtype=np_verts.dtype) if v_normal_alg in ('MWE', 'MWAT'): norm_func = mean_weighted_equally else: norm_func = mean_weighted_unequally if np_faces.dtype == object: np_len = np.vectorize(len) lens = np_len(np_faces) pol_types = np.unique(lens) f_normals = np.zeros((len(np_faces), 3), dtype=np.float64) for pol_sides in pol_types: mask = lens == pol_sides np_faces_g = np.array(np_faces[mask].tolist()) v_pols = np_verts[np_faces_g] if get_v_normals: f_normal_g, v_normals = norm_func(np_faces_g, v_pols, v_normals, non_planar, v_normal_alg) else: f_normals = np_faces_normals(v_pols) f_normals[mask, :] = f_normal_g else: pol_sides = np_faces.shape[1] v_pols = np_verts[np_faces] if get_v_normals: f_normals, v_normals = norm_func(np_faces, v_pols, v_normals, non_planar, v_normal_alg) else: f_normals = np_faces_normals(v_pols) if output_numpy: return (f_normals if get_f_normals else [], np_normalize_vectors(v_normals) if get_v_normals else []) return (f_normals.tolist() if get_f_normals else [], np_normalize_vectors(v_normals).tolist() if get_v_normals else [])
def np_process_polygons(verts, faces, func=None, dims=3, output_numpy=False): if not func: return if not (has_element(verts) and has_element(faces)): return if isinstance(verts, np.ndarray): np_verts = verts else: np_verts = np.array(verts) if isinstance(faces, np.ndarray): np_faces = faces else: np_faces = np.array(faces) if np_faces.dtype == object: np_len = np.vectorize(len) lens = np_len(np_faces) pol_types = np.unique(lens) if dims == 1: vals = np.zeros(np_faces.shape[0], dtype=float) else: vals = np.zeros((np_faces.shape[0], dims), dtype=float) for p in pol_types: mask = lens == p np_faces_g = np.array(np_faces[mask].tolist()) v_pols = np_verts[np_faces_g] if dims == 1: vals[mask] = func(v_pols) else: vals[mask, :] = func(v_pols) else: v_pols = np_verts[np_faces] #num pols, num sides vals = func(v_pols) if output_numpy: return vals return vals.tolist()
def is_triangles_only(faces): if has_element(faces): return all((len(f) == 3 for f in faces))
def inset_special_np(vertices, faces, inset_rates, distances, ignores, make_inners, custom_normals, matrices, zero_mode="SKIP", offset_mode='CENTER', proportional=False, concave_support=True, output_old_face_id=False, output_old_v_id=False, output_pols_groups=False, output_new_verts_mask=False): if not has_element(faces): return new_faces, new_ignores, new_insets = [], [], [] original_face_ids, original_vertex_id, new_pols_groups, new_verts_mask = [], [], [], [] inset_faces_id, fan_faces_id, ignores_id, fan_faces = [], [], [], [] np_distances, np_matrices = [], [] np_verts = vertices if isinstance(vertices, np.ndarray) else np.array(vertices) invert_face_mask = numpy_full_list(np_array(ignores, dtype=bool), len(faces)) np_faces_mask = np.invert(invert_face_mask) if not any(np_faces_mask): return np_faces = np_array(faces) np_faces_id = np.arange(len(faces)) if output_old_face_id else [] np_inset_rate = numpy_full_list(inset_rates, len(faces)) if has_element(custom_normals): np_custom_normals = numpy_full_list(custom_normals, len(faces)) use_custom_normals = True else: np_custom_normals = [] use_custom_normals = False if offset_mode == 'CENTER': zero_inset = np_inset_rate == 0 if zero_mode == 'SKIP': np_faces_mask[zero_inset] = False invert_face_mask[zero_inset] = True inset_pols = np_faces[np_faces_mask] np_distances = numpy_full_list(distances, len(faces))[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] new_ignores = np_faces[invert_face_mask].tolist() if output_old_face_id: ignores_id = np_faces_id[invert_face_mask].tolist() inset_faces_id = np_faces_id[np_faces_mask] else: # FAN if output_old_face_id: ignores_maks = np.invert(np_faces_mask) ignores_id = np_faces_id[ignores_maks].tolist() new_ignores = np_faces[ignores_maks].tolist() else: new_ignores = np_faces[np.invert(np_faces_mask)].tolist() np_faces_mask[zero_inset] = False inset_pols = np_faces[np_faces_mask] np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] np_all_distances = numpy_full_list(distances, len(faces)) np_distances = np_all_distances[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] fan_faces = np_faces[zero_inset] fan_distances = np_all_distances[zero_inset] if output_old_face_id: inset_faces_id = np_faces_id[np_faces_mask] fan_faces_id = np_faces_id[zero_inset] else: #SIDES mode inset_pols = np_faces[np_faces_mask] if offset_mode == 'SIDES': np_distances = numpy_full_list(distances, len(faces))[np_faces_mask] np_inset_rate = np_inset_rate[np_faces_mask] else: #MATRIX if len(matrices) == len(faces): np_matrices = np.array(matrices)[np_faces_mask] else: np_matrices = numpy_full_list(matrices, len(inset_pols)) np_make_inners = numpy_full_list( make_inners, len(faces)).astype(bool)[np_faces_mask] new_ignores = np_faces[invert_face_mask].tolist() fan_faces = [] if output_old_face_id: ignores_id = np_faces_id[invert_face_mask].tolist() inset_faces_id = np_faces_id[np_faces_mask] common_args = { 'use_custom_normals': use_custom_normals, 'output_old_v_id': output_old_v_id, 'output_old_face_id': output_old_face_id, 'output_pols_groups': output_pols_groups } new_verts = np_verts.tolist() if output_old_v_id: original_vertex_id = list(range(len(vertices))) if output_new_verts_mask: new_verts_mask.extend([0] * len(new_verts)) variable_pols = inset_pols.dtype == 'object' np_len = np_vectorize(len) index_offset = 0 if len(inset_pols) > 0: if variable_pols: lens = np_len(inset_pols) pol_types = np.unique(lens) else: pol_types = [inset_pols.shape[1]] for pol_sides in pol_types: if variable_pols: mask = lens == pol_sides pols_group = np_array(inset_pols[mask].tolist(), dtype=int) res = inset_regular_pols( np_verts, pols_group, np_distances[mask] if offset_mode != 'MATRIX' else [], np_inset_rate[mask] if offset_mode != 'MATRIX' else [], np_make_inners[mask], inset_faces_id[mask] if output_old_face_id else [], np_custom_normals[mask] if use_custom_normals else [], np_matrices[mask] if offset_mode == 'MATRIX' else [], offset_mode=offset_mode, proportional=proportional, concave_support=concave_support, index_offset=index_offset, **common_args) else: res = inset_regular_pols( np_verts, inset_pols, np_distances, np_inset_rate, np_make_inners, inset_faces_id if output_old_face_id else [], np_custom_normals if use_custom_normals else [], np_matrices, offset_mode=offset_mode, proportional=proportional, concave_support=concave_support, index_offset=index_offset, **common_args) index_offset += len(res[0]) new_verts.extend(res[0]) new_faces.extend(res[1]) new_insets.extend(res[2]) original_vertex_id.extend(res[3]) original_face_ids.extend(res[4]) new_pols_groups.extend(res[5]) if output_new_verts_mask: new_verts_mask.extend([1] * len(res[0])) if zero_mode == 'FAN' and len(fan_faces) > 0: if variable_pols: lens = np_len(fan_faces) pol_types = np.unique(lens) else: pol_types = [inset_pols.shape[1]] for pol_sides in pol_types: if variable_pols: mask = lens == pol_sides pols_group = np_array(fan_faces[mask].tolist(), dtype=int) res = fan_regular_pols( np_verts, pols_group, fan_distances[mask], fan_faces_id[mask] if output_old_face_id else [], np_custom_normals[mask] if use_custom_normals else [], index_offset=index_offset, **common_args) else: res = fan_regular_pols( np_verts, fan_faces, fan_distances, fan_faces_id if output_old_face_id else [], np_custom_normals if use_custom_normals else [], index_offset=index_offset, **common_args) index_offset += len(res[0]) new_verts.extend(res[0]) new_faces.extend(res[1]) original_vertex_id.extend(res[2]) original_face_ids.extend(res[3]) new_pols_groups.extend(res[4]) if output_new_verts_mask: new_verts_mask.extend([1] * len(res[0])) return (new_verts, new_faces + new_ignores, new_ignores, new_insets, original_vertex_id, original_face_ids + ignores_id, new_pols_groups + [0] * len(new_ignores), new_verts_mask)
def bmesh_from_pydata(verts=None, edges=[], faces=[], markup_face_data=False, markup_edge_data=False, markup_vert_data=False, normal_update=False, index_edges=False): """ verts : necessary edges / faces : optional normal_update : optional - will update verts/edges/faces normals at the end index_edges (bool) : optional - will make it possible for users of the bmesh to manually iterate over any edges or do index lookups """ bm = bmesh.new() bm_verts = bm.verts add_vert = bm_verts.new py_verts = verts.tolist() if type(verts) == np.ndarray else verts for co in py_verts: add_vert(co) bm_verts.index_update() bm_verts.ensure_lookup_table() if has_element(faces): add_face = bm.faces.new py_faces = faces.tolist() if type(faces) == np.ndarray else faces for face in py_faces: add_face(tuple(bm_verts[i] for i in face)) bm.faces.index_update() if has_element(edges): if markup_edge_data: initial_index_layer = bm.edges.layers.int.new("initial_index") add_edge = bm.edges.new get_edge = bm.edges.get py_faces = edges.tolist() if type(edges) == np.ndarray else edges for idx, edge in enumerate(edges): edge_seq = tuple(bm_verts[i] for i in edge) bm_edge = get_edge(edge_seq) if not bm_edge: bm_edge = add_edge(edge_seq) if markup_edge_data: bm_edge[initial_index_layer] = idx if has_element(edges) or index_edges: bm.edges.index_update() if markup_vert_data: bm_verts.ensure_lookup_table() layer = bm_verts.layers.int.new("initial_index") for idx, vert in enumerate(bm_verts): vert[layer] = idx if markup_face_data: bm.faces.ensure_lookup_table() layer = bm.faces.layers.int.new("initial_index") for idx, face in enumerate(bm.faces): face[layer] = idx if normal_update: bm.normal_update() return bm
def bmesh_from_pydata(verts=None, edges=[], faces=[], markup_face_data=False, markup_edge_data=False, markup_vert_data=False, normal_update=False): ''' verts is necessary, edges/faces are optional normal_update, will update verts/edges/faces normals at the end ''' bm = bmesh.new() bm_verts = bm.verts add_vert = bm_verts.new py_verts = verts.tolist() if type(verts) == np.ndarray else verts for co in py_verts: add_vert(co) bm_verts.index_update() bm_verts.ensure_lookup_table() if has_element(faces): add_face = bm.faces.new py_faces = faces.tolist() if type(faces) == np.ndarray else faces for face in py_faces: add_face(tuple(bm_verts[i] for i in face)) bm.faces.index_update() if has_element(edges): if markup_edge_data: initial_index_layer = bm.edges.layers.int.new("initial_index") add_edge = bm.edges.new get_edge = bm.edges.get py_faces = edges.tolist() if type(edges) == np.ndarray else edges for idx, edge in enumerate(edges): edge_seq = tuple(bm_verts[i] for i in edge) bm_edge = get_edge(edge_seq) if not bm_edge: bm_edge = add_edge(edge_seq) if markup_edge_data: bm_edge[initial_index_layer] = idx bm.edges.index_update() if markup_vert_data: bm_verts.ensure_lookup_table() layer = bm_verts.layers.int.new("initial_index") for idx, vert in enumerate(bm_verts): vert[layer] = idx if markup_face_data: bm.faces.ensure_lookup_table() layer = bm.faces.layers.int.new("initial_index") for idx, face in enumerate(bm.faces): face[layer] = idx if normal_update: bm.normal_update() return bm
def triangle_mesh_poke(mesh, mask_in, offset_in, v_color, mat_id, relative_offset=False, deepcopy=True): if deepcopy: triangle_mesh = copy.deepcopy(mesh) else: triangle_mesh = mesh np_verts = np.asarray(triangle_mesh.vertices) mask = numpy_full_list(mask_in, len(triangle_mesh.triangles)).astype('bool') if len(offset_in) == np.sum(mask): offset = np.array(offset_in)[:, np.newaxis] elif len(offset_in) > 1: offset = numpy_full_list(offset_in, len(triangle_mesh.triangles))[mask, np.newaxis] else: offset = offset_in np_faces = np.asarray(triangle_mesh.triangles) faces_masked = np_faces[mask] v_pols = np_verts[np_faces[mask]] center = np.sum(v_pols, axis=1) / 3 normals = get_normals(triangle_mesh, np_verts, np_faces, mask) faces_num = np_faces[mask].shape[0] if relative_offset: areas = calc_tris_areas(v_pols) new_vecs = center + normals * (offset* areas[:, np.newaxis]) else: new_vecs = center + normals * offset all_vecs = np.concatenate([np_verts, new_vecs]) new_faces = np.zeros((faces_num, 3, 3), dtype='int') new_faces[:, :, 2] = (np.arange(faces_num) + len(np_verts))[:, np.newaxis] for i in range(3): new_faces[:, i, 0] = np_faces[mask, i] new_faces[:, i, 1] = np_faces[mask, (i + 1) % 3] new_faces_shaped = new_faces.reshape(-1, 3) all_faces = np.concatenate([np_faces[np.invert(mask)], new_faces_shaped]) if has_element(v_color): if triangle_mesh.has_vertex_colors(): v_col = numpy_full_list(v_color, len(new_vecs))[:,:3] triangle_mesh.vertex_colors = vec_3f(np.concatenate([np.asarray(triangle_mesh.vertex_colors), v_col])) else: spread_vertex_attrib(triangle_mesh, faces_masked, 'vertex_colors') spread_vertex_attrib(triangle_mesh, faces_masked, 'vertex_normals') spread_face_attrib(triangle_mesh, mask, 'triangle_normals', 3, vec_3f) if len(mat_id) > 0: if triangle_mesh.has_triangle_material_ids(): mat_id_shaped = numpy_full_list(mat_id, len(new_faces_shaped)) triangle_mesh.triangle_material_ids = vec_1i( np.concatenate( [np.asarray(triangle_mesh.triangle_material_ids)[np.invert(mask)], mat_id_shaped] )) else: mat_id_shaped = numpy_full_list(mat_id, len(all_faces)) triangle_mesh.triangle_material_ids = vec_1i(mat_id_shaped) else: spread_face_attrib(triangle_mesh, mask, 'triangle_material_ids', 1, vec_1i) poke_uvs(triangle_mesh, mask) triangle_mesh.vertices = vec_3f(all_vecs) triangle_mesh.triangles = vec_3i(all_faces) return (triangle_mesh, new_vecs, np.arange(len(np_verts), len(np_verts)+len(new_vecs)), np.arange(len(all_faces)-len(new_faces_shaped), len(all_faces)) )