voxelization to 3D numpy.ndarray #5652
-
Hello everybody. I am new with pyvista. I would like to export the voxelization that pyvista does of a geometry to a numpy 3D array. I was looking for related posts and found the discussions #141 and #4339. In my case, I modified the code as follows:
However, I always get the same error on the
I've been trying different options but I don't think I quite understand this library (sorry). I am using python 3.8 and pyvista v0.43.3. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
I've been trying to do this the whole morning and finally got to a working solution. I'm also new to pyvista so maybe the menta model I have is not accurate and I might be wrong, but this is what I think is going on: The first thing is that you cannot put the array of selection = voxels.select_enclosed_points(mesh.extract_surface(),
tolerance=0.0,
check_surface=False) the result is that all the points are inside (as could be expected, since all the points in Actually, if you change the tolerance slightly to 0.1, most of the points in Now
Now you can plot the grid with the scalar values from So what you want is to get the array points_C_order = mask.reshape(grid.dimensions) your result will look something like this (as reported in pyvista/pyvista-support#141 and #5778): The problem is the reshape order as hinted here: #4504: points_F_order = mask.reshape(grid.dimensions, order='F') will result in: where The complete code with some additionall plotting: from pyvista import examples
import pyvista
import numpy as np
import matplotlib.pyplot as plt
def get_array(mesh: pyvista.PolyData, density:float):
x_min, x_max, y_min, y_max, z_min, z_max = mesh.bounds
x = np.arange(x_min, x_max, density)
y = np.arange(y_min, y_max, density)
z = np.arange(z_min, z_max, density)
x, y, z = np.meshgrid(x, y, z)
# Create unstructured grid from the structured grid
grid = pyvista.StructuredGrid(x, y, z)
ugrid = pyvista.UnstructuredGrid(grid)
# get part of the mesh within the mesh's bounding surface.
selection = ugrid.select_enclosed_points(mesh.extract_surface(),
tolerance=0.0,
check_surface=False)
mask = selection['SelectedPoints'].view(bool)
mask = mask.reshape(x.shape, order='F')
mask = np.array(mask)
return mask
mesh = examples.download_foot_bones()
mask = get_array(mesh, mesh.length/100)
print(mask.shape, type(mask))
fig, axes = plt.subplots(1, 3)
axes[0].imshow(mask.sum(0))
axes[0].set_title('Sum along X-axis')
axes[1].imshow(mask.sum(1))
axes[1].set_title('Sum along Y-axis')
axes[2].imshow(mask.sum(2))
axes[2].set_title('Sum along Z-axis')
plt.show()
# # Plot mask in 3D with matplotlib
mask = np.transpose(mask, (1,2,0))
xs, ys, zs = np.where(mask)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.voxels(mask)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
ax.set_box_aspect((np.ptp(xs), np.ptp(ys), np.ptp(zs))) # aspect ratio is 1:1:1 in data space
plt.show() |
Beta Was this translation helpful? Give feedback.
I've been trying to do this the whole morning and finally got to a working solution. I'm also new to pyvista so maybe the menta model I have is not accurate and I might be wrong, but this is what I think is going on:
The first thing is that you cannot put the array of
mask
into thegrid
since they have different dimensions as the error says. The problem is thatvoxels
is just an array of points defining the coordinates of the voxels extracted from the mesh (I think that each point can have additional attributes) . So when you select the points ofvoxels
that are inside themesh
: