|
| 1 | +import pandas as pd |
| 2 | +import trimesh |
| 3 | +import vtk |
| 4 | +import numpy as np |
| 5 | +from vtk.util.numpy_support import numpy_to_vtk |
| 6 | +import time |
| 7 | +from scipy.spatial import KDTree |
| 8 | +from save_vti import * |
| 9 | + |
| 10 | + |
| 11 | +def kd_tree(voxel_grid, micro_structure): |
| 12 | + """ |
| 13 | + Maps a given voxel grid to a randomized numpy array using KDTree. |
| 14 | +
|
| 15 | + Parameters: |
| 16 | + - voxel_grid: 3D numpy array representing the voxel grid. |
| 17 | + - micro_structure: Not used in this function, but retained for consistency. |
| 18 | +
|
| 19 | + Returns: |
| 20 | + - mapped_array: 3D numpy array with values from the randomized array mapped onto the voxel grid. |
| 21 | + """ |
| 22 | + |
| 23 | + print(voxel_grid.shape) |
| 24 | + random_array_shape = voxel_grid.shape |
| 25 | + |
| 26 | + # Create a randomized numpy array |
| 27 | + random_array = np.random.randint(0, 1001, random_array_shape) |
| 28 | + print(random_array) |
| 29 | + random_array = random_array.astype(float) |
| 30 | + |
| 31 | + # Ensure the voxel grid and random array are of the same shape |
| 32 | + if voxel_grid.shape != random_array.shape: |
| 33 | + raise ValueError("Voxel grid and random array shapes do not match!") |
| 34 | + |
| 35 | + # Create KDTree for the random array |
| 36 | + indices = np.array(np.where(np.ones_like(random_array))).T |
| 37 | + print(indices) |
| 38 | + df = pd.DataFrame(indices) |
| 39 | + df.to_csv("temp.csv", index=False) |
| 40 | + tree = KDTree(indices) |
| 41 | + |
| 42 | + # Get all the indices of the voxel_grid where voxel value is greater than 0 |
| 43 | + voxel_indices = np.array(np.where(voxel_grid.matrix > 0)).T |
| 44 | + |
| 45 | + # Query the KDTree for all voxel indices at once |
| 46 | + _, nearest_indices = tree.query(voxel_indices) |
| 47 | + |
| 48 | + # Create an array of zeros to map the values from random_array using the nearest_indices |
| 49 | + mapped_array = np.zeros_like(random_array, dtype=random_array.dtype) |
| 50 | + for voxel_idx, nearest_idx in zip(voxel_indices, nearest_indices): |
| 51 | + mapped_array[tuple(voxel_idx)] = random_array[tuple(indices[nearest_idx])] |
| 52 | + |
| 53 | + return mapped_array |
| 54 | + |
| 55 | + |
| 56 | +# def voxel_to_vti(input_filename, output_filename): |
| 57 | +# |
| 58 | +# # Load the mesh |
| 59 | +# mesh = trimesh.load_mesh(input_filename) |
| 60 | +# |
| 61 | +# # Voxelization of the mesh |
| 62 | +# voxel = mesh.voxelized(0.01) |
| 63 | +# voxel_matrix = voxel.matrix |
| 64 | +# """ |
| 65 | +# Converts a 3D voxel matrix to a .vti file. |
| 66 | +# |
| 67 | +# Parameters: |
| 68 | +# - voxel_matrix: 3D numpy array. |
| 69 | +# - filename: Name of the file to save to (should end with .vti). |
| 70 | +# """ |
| 71 | +# |
| 72 | +# # Convert the numpy array to a VTK array |
| 73 | +# vtk_data = numpy_to_vtk(num_array=voxel_matrix.ravel(order='F'), deep=True, array_type=vtk.VTK_INT) |
| 74 | +# |
| 75 | +# # Create an ImageData object and assign the vtk array to it |
| 76 | +# image_data = vtk.vtkImageData() |
| 77 | +# image_data.SetDimensions(voxel_matrix.shape) |
| 78 | +# image_data.GetPointData().SetScalars(vtk_data) |
| 79 | +# |
| 80 | +# # Write the ImageData object to a .vti file |
| 81 | +# writer = vtk.vtkXMLImageDataWriter() |
| 82 | +# writer.SetFileName(output_filename) |
| 83 | +# writer.SetInputData(image_data) |
| 84 | +# writer.Write() |
| 85 | + |
| 86 | +def voxelize_stl(filename, voxel_size): |
| 87 | + """ |
| 88 | + Voxelize an STL file. |
| 89 | +
|
| 90 | + Parameters: |
| 91 | + - filename: Path to the STL file |
| 92 | + - voxel_size: Desired size of the voxels |
| 93 | +
|
| 94 | + Returns: |
| 95 | + - voxelized mesh (trimesh.VoxelGrid instance) |
| 96 | + """ |
| 97 | + # Load the STL file as a trimesh mesh |
| 98 | + mesh = trimesh.load_mesh(filename) |
| 99 | + |
| 100 | + # Voxelize the mesh |
| 101 | + voxel_grid = mesh.voxelized(pitch=voxel_size) |
| 102 | + voxel_grid = voxel_grid.fill() |
| 103 | + |
| 104 | + return voxel_grid, mesh |
| 105 | + |
| 106 | + |
| 107 | +def voxel_to_vti(voxels): |
| 108 | + # Convert voxel data to vtkImageData |
| 109 | + image_data = vtk.vtkImageData() |
| 110 | + |
| 111 | + # Set the dimensions of the vtkImageData structure |
| 112 | + image_data.SetDimensions(*voxels.shape) |
| 113 | + image_data.AllocateScalars(vtk.VTK_FLOAT, 1) # Assuming your voxels data type is float |
| 114 | + |
| 115 | + # Convert the voxel data to a flat array |
| 116 | + flat_voxels = voxels.ravel(order='F') # 'F' order means Fortran-style order which is used by vtk |
| 117 | + |
| 118 | + # Convert flat numpy array to vtk array and set it as scalars |
| 119 | + vtk_array = numpy_to_vtk(flat_voxels) |
| 120 | + image_data.GetPointData().SetScalars(vtk_array) |
| 121 | + |
| 122 | + return image_data |
| 123 | + |
| 124 | + |
| 125 | +def main(): |
| 126 | + # Example usage: |
| 127 | + filename = "cad/tube.stl" |
| 128 | + voxel_size = 0.01 # adjust as needed |
| 129 | + start = time.time() |
| 130 | + voxels, mesh = voxelize_stl(filename, voxel_size) |
| 131 | + # filled_voxels = fill_interior_voxels(voxels, mesh) |
| 132 | + end = time.time() |
| 133 | + print(end - start) |
| 134 | + start = time.time() |
| 135 | + |
| 136 | + mapped_array = kd_tree(voxels, []) |
| 137 | + |
| 138 | + image_data = voxel_to_vti(mapped_array) |
| 139 | + |
| 140 | + end = time.time() |
| 141 | + print(end - start) |
| 142 | + save_vti(image_data, r"voxelized_stl\tube_3.vti") |
| 143 | + |
| 144 | + |
| 145 | +if __name__ == "__main__": |
| 146 | + main() |
| 147 | + |
| 148 | +# def main(): |
| 149 | +# # Example usage: |
| 150 | +# |
| 151 | +# filename = r"cad\tube.stl" |
| 152 | +# voxel_size = 0.01 # 10 micrometers |
| 153 | +# |
| 154 | +# dims = (100, 100, 100) |
| 155 | +# |
| 156 | +# voxel_to_vti(filename, "output_2.vti") |
| 157 | + |
| 158 | + |
| 159 | +# result_array = map_voxelized_stl_to_random_array(filename, voxel_size, dims) |
| 160 | + |
| 161 | +# start = time.time() |
| 162 | +# zero_array = np.zeros(dims, dtype=int) |
| 163 | +# random_array = np.random.randint(0, 1001, dims) |
| 164 | +# |
| 165 | +# indices = np.array(np.where(np.ones_like(random_array))).T |
| 166 | +# |
| 167 | +# tree = KDTree(indices) |
| 168 | +# |
| 169 | +# # Get all the indices of the zero_array in a vectorized manner |
| 170 | +# all_indices = np.array(list(np.ndindex(zero_array.shape))) |
| 171 | +# |
| 172 | +# # Query the KDTree for all indices at once |
| 173 | +# _, nearest_indices = tree.query(all_indices) |
| 174 | +# |
| 175 | +# # Map the values from random_array to zero_array using the nearest_indices |
| 176 | +# for idx, nearest_idx in zip(all_indices, nearest_indices): |
| 177 | +# zero_array[tuple(idx)] = random_array[tuple(indices[nearest_idx])] |
| 178 | +# # |
| 179 | +# print("Random Array:") |
| 180 | +# print(random_array) |
| 181 | +# print("\nMapped Zero Array:") |
| 182 | +# print(zero_array) |
| 183 | +# print(time.time() - start) |
| 184 | + |
| 185 | +# filename = "output_2.vti" |
| 186 | +# numpy_to_vtk_image(result_array, filename) |
| 187 | + |
| 188 | +# print(voxels) |
| 189 | + |
| 190 | +# end = time.time() |
| 191 | +# print(end - start) |
| 192 | +# start = time.time() |
| 193 | +# image_data = voxel_to_vti(voxels.matrix.astype(float)) |
| 194 | +# end = time.time() |
| 195 | +# print(end - start) |
| 196 | +# save.save_vti(image_data, r"voxelized_stl\cube.vti") |
| 197 | + |
| 198 | +# |
| 199 | +# if __name__ == "__main__": |
| 200 | +# main() |
0 commit comments