在Python中旋转3D物体导致物体出现孔洞
我有一个3D的物体,假设是一个长方体,我想让它旋转。为了简单起见,我们就假设它只围绕x轴旋转。所以我使用对应的旋转矩阵R
,然后把它和坐标向量v
相乘,得到新的坐标向量v'
:v'=R*v
。为了可视化这个过程,我使用了mayavi这个工具。
虽然旋转是有效的,但它有一个让人烦恼的副作用:旋转后的长方体里面有些值缺失了。在下面的快照中,你可以看到,蓝色的长方体就是旋转后的物体,它里面有一些“洞”。
我现在的问题是,我在旋转时做错了什么?
这里是对应的python代码:
# 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)
# loop through arr and define cuboid and rotated cuboid
# note that this is a very inefficient way to define a cuboid
# (the actual thing to rotate is different, this is just to make it simple)
for ii in range(Nx):
for jj in range(Ny):
for kk in range(Nz):
# check if coordinate is inside original cuboid
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)) ):
# set density of original cuboid
arr[ii,jj,kk] = 5.
# apply rotation
new_coords = Rx(alpha)*np.array([[ii],[jj],[kk]])
# set density of rotated cuboid to different value
arr[ round(new_coords[0,0]),
round(new_coords[1,0]),
round(new_coords[2,0]) ] = 2
return arr
def main():
cubes = make_rotated_cube()
plot_simple(cubes)
if __name__ == '__main__':
main()
1 个回答
0
感谢@Julien和他的评论,我试了一下扭曲的方法。从下面的图可以看到,之前的孔确实消失了!不过,现在可以明显看出边缘有点难看,我觉得这可能是因为网格的分辨率不够好(因为用这种方法我没有“丢失”任何像素,之前是有的)。
我只是修改了for
循环中的代码(在# apply rotation
这条评论之后):
# translations
skew_1 = np.tan(alpha/2)
skew_2 = -np.sin(alpha)
skew_3 = skew_1
# calculating new coords
kk_new = kk + round(skew_1*jj)
jj_new = jj + round(skew_2*kk_new)
kk_new = kk_new + round(skew_1*jj_new)
arr[ ii, jj_new, kk_new ] = 2
我还是希望能看到一个涉及插值的解决方案(不过这个扭曲的方法真的很不错)。