Mayavi:围绕y轴旋转

时间:2016-08-05 13:38:41

标签: python 3d mayavi

我使用mayavi的triangular_mesh方法绘制3D网格。数据描述了在3D空间中面朝下放置的人体轮廓(因此cmap可用于表示与相机的距离)。

这里是用于生成绘图的代码(面和顶点来自外部对象,这里有太多不能显示):

from mayavi import mlab

import math
import numpy as np
import sys
import os


fig = mlab.figure(fgcolor=(0, 0, 0), bgcolor=(1, 1, 1), size=(1920, 980))

a = np.array(this_mesh.vertices - refC.conj().transpose())  # this_mesh is an object created from external data files 

this_mesh.faces = this_mesh.faces.astype(int) -1  # mesh data is generated by matlab, which is 1-indexed

m = mlab.triangular_mesh(x, y, z, this_mesh.faces, opacity=0.75)

mlab.axes(extent=[-1100, 1100, -1100, 1100, -1100, 1100])

不移动相机,剪影面朝下。为了正面观看模型,我改变了相机的方位角和高度,以便自上而下地查看图形。这显示了预期的轮廓。

mlab.view(azimuth=0, elevation=180)
mlab.show()

我的下一个任务是创建一系列图像,其中摄像机围绕绘图平移,从面向右侧的轮廓开始,并朝向左侧完成。

复杂的是,为了获得深度信息的色彩图,我已经移动了视图的方位角和高度(如上面的代码所示)。 Mayavi有更多选择移动相机而不是matplotlib,但它似乎没有办法围绕Y轴旋转,所以我猜测我需要对它进行一些复杂的计算。方位角和仰角可以达到相同的效果 - 但是我不知道从哪里开始(我在3D空间工作的新手,我的大脑还没有想到这一点)。

有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:4)

事实证明,这有一个解决方法。

您可以独立于相机旋转轴上的演员。 (这会使可视化与数据标记不一致,但实际上我隐藏了图形的轴,在这种情况下它并不重要。)

您需要做的就是:

m.actor.actor.rotate_y(desired_angle)

......你很高兴。

答案 1 :(得分:2)

你需要一些数学。好的,这里是如何在代码方面做到这一点,它不是最好的代码,但我想让它不言自明。我使用Rodrigues公式在3d中旋转来实现这一点,az_new和el_new是你的新视角。更改theta的值以在您的参照系中获得不同的视角,我在下面的代码中使用了45度:

import numpy as np
import math

def rotation_matrix(axis, theta):
    """
    Return the rotation matrix associated with counterclockwise rotation about
    the given axis by theta radians.
    """
    axis = np.asarray(axis)
    theta = np.asarray(theta)
    axis = axis/math.sqrt(np.dot(axis, axis))
    a = math.cos(theta/2.0)
    b, c, d = -axis*math.sin(theta/2.0)
    aa, bb, cc, dd = a*a, b*b, c*c, d*d
    bc, ad, ac, ab, bd, cd = b*c, a*d, a*c, a*b, b*d, c*d
    return np.array([[aa+bb-cc-dd, 2*(bc+ad), 2*(bd-ac)],
                     [2*(bc-ad), aa+cc-bb-dd, 2*(cd+ab)],
                     [2*(bd+ac), 2*(cd-ab), aa+dd-bb-cc]])


az = 90
el = -75

x = np.cos(np.deg2rad(el))*np.cos(np.deg2rad(az))
y = np.cos(np.deg2rad(el))*np.sin(np.deg2rad(az))
z = np.sin(np.deg2rad(el))

# So your viewing vector in x,y coordinates on unit sphere
v = [x,y,z]

# Since you want to rotate about the y axis from this viewing angle, we just increase the
# elevation angle by 90 degrees to obtain our axis of rotation

az2 = az
el2 = el+90

x = np.cos(np.deg2rad(el2))*np.cos(np.deg2rad(az2))
y = np.cos(np.deg2rad(el2))*np.sin(np.deg2rad(az2))
z = np.sin(np.deg2rad(el2))

axis = [x,y,z]

# Now to rotate about the y axis from this viewing angle we use the rodrigues formula
# We compute our new viewing vector, lets say we rotate by 45 degrees
theta = 45
newv = np.dot(rotation_matrix(axis,np.deg2rad(theta)), v)

#Get azimuth and elevation for new viewing vector
az_new = np.rad2deg(np.arctan(newv[1]/newv[0]))
el_new = np.rad2deg(np.arcsin(newv[2]))