You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中旋转3D长方体后出现孔洞问题求助

问题根源与修复方案

核心错误点

  1. 旋转基准错误:直接对网格原始坐标(原点在网格角落)进行旋转,而非以立方体自身中心为旋转轴,导致旋转后的立方体位置偏移,同时放大了取整带来的误差。
  2. 正向映射导致采样缺失:遍历原始立方体的每个点,旋转后取整赋值到新网格,这种方式会让旋转后的网格中很多应被填充的点未被覆盖,从而形成孔洞。

修复后的代码

# 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:52:04