Python中旋转3D长方体后出现孔洞问题求助
问题根源与修复方案
核心错误点
- 旋转基准错误:直接对网格原始坐标(原点在网格角落)进行旋转,而非以立方体自身中心为旋转轴,导致旋转后的立方体位置偏移,同时放大了取整带来的误差。
- 正向映射导致采样缺失:遍历原始立方体的每个点,旋转后取整赋值到新网格,这种方式会让旋转后的网格中很多应被填充的点未被覆盖,从而形成孔洞。
修复后的代码
# import standard modules import numpy as np # import modules for 3D visualization of data from mayavi import mlab def plot_simple( data2plot ): # define contour levels contLevels = np.linspace(0, np.amax(data2plot), 5)[1:].tolist() # create figure with white background and black axes and labels fig1 = mlab.figure( bgcolor=(1,1,1), fgcolor=(0,0,0), size=(800,600) ) # make the contour plot cont_plt = mlab.contour3d( data2plot, contours=contLevels, transparent=True, opacity=.4, figure=fig1 ) # create axes instance to modify some of its properties ax1 = mlab.axes( nb_labels=4, extent=[1, data2plot.shape[0], 1, data2plot.shape[1], 1, data2plot.shape[2] ] ) mlab.outline(ax1) ax1.axes.label_format = '%.0f' ax1.axes.x_label = 'x' ax1.axes.y_label = 'y' ax1.axes.z_label = 'z' # set initial viewing angle mlab.view( azimuth=290, elevation=80 ) mlab.show() def Rx(alpha): # rotation matrix for rotation around x-axis return np.matrix([[ 1, 0 , 0 ], [ 0, np.cos(alpha), -np.sin(alpha)], [ 0, np.sin(alpha), np.cos(alpha) ]]) def make_rotated_cube( Nx=100, Ny=70, Nz=40 ): arr = np.zeros( [Nx, Ny, Nz] ) # define center of cuboid xc = Nx/2 yc = Ny/2 zc = Nz/2 # define width of cuboid in each direction dx = Nx/4 dy = Ny/4 dz = Nz/4 # rotation angle in degrees alpha = 20 alpha = np.radians(alpha) rot_mat = Rx(alpha) # 正交旋转矩阵的逆等于转置,计算更高效 inv_rot_mat = rot_mat.T # 绘制原始立方体 for ii in range(Nx): for jj in range(Ny): for kk in range(Nz): if ( (ii > (xc-dx/2) and ii < (xc+dx/2)) and (jj > (yc-dy/2) and jj < (yc+dy/2)) and (kk > (zc-dz/2) and kk < (zc+dz/2)) ): arr[ii,jj,kk] = 5. # 反向映射:遍历每个网格点,判断逆旋转后是否属于原始立方体 for ii in range(Nx): for jj in range(Ny): for kk in range(Nz): # 转换为以立方体中心为原点的局部坐标 local_coord = np.array([[ii - xc], [jj - yc], [kk - zc]]) # 逆旋转得到原始局部坐标 original_local = inv_rot_mat * local_coord # 转换回全局坐标 orig_x = original_local[0,0] + xc orig_y = original_local[1,0] + yc orig_z = original_local[2,0] + zc # 判断是否在原始立方体内 if ( (orig_x > (xc-dx/2) and orig_x < (xc+dx/2)) and (orig_y > (yc-dy/2) and orig_y < (yc+dy/2)) and (orig_z > (zc-dz/2) and orig_z < (zc+dz/2)) ): arr[ii,jj,kk] = 2 return arr def main(): cubes = make_rotated_cube() plot_simple(cubes) if __name__ == '__main__': main()
关键修复说明
- 基于中心旋转:先将网格坐标转换为以立方体中心为原点的局部坐标,旋转后再转换回全局坐标,确保立方体绕自身中心旋转,位置准确。
- 反向映射填充:不再从原始点映射到旋转后点,而是遍历每个网格点,检查其逆旋转后是否属于原始立方体,完整填充旋转区域,避免孔洞。
- 高效逆矩阵计算:利用正交旋转矩阵的特性,直接用转置作为逆矩阵,提升计算效率。
内容的提问来源于stack exchange,提问作者Alf
相关产品推荐
相关产品推荐

