【问题标题】:Mayavi: rotate around y axisMayavi:绕 y 轴旋转
【发布时间】:2016-12-11 22:58:20
【问题描述】:

我正在使用 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 空间工作的新手,我的大脑还不这么认为)。

谁能指出我正确的方向?

【问题讨论】:

    标签: python 3d mayavi


    【解决方案1】:

    事实证明有一些解决方法。

    您可以独立于摄像机沿轴旋转演员。 (这会使可视化与数据标签不同步,但由于我实际上隐藏了图形的轴,因此在这种情况下并不重要。)

    您需要做的就是:

    m.actor.actor.rotate_y(desired_angle)
    

    ...你可以走了。

    【讨论】:

    • btw desired_angle 是度数,不是弧度,负数也可以
    【解决方案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]))
    

    【讨论】:

    • 非常感谢,这看起来很有用。我会在星期一试一试,看看效果如何。
    • 嗯,不完全在那里(它在错误的轴上旋转)。我可能不得不尝试一种完全不同的方法......
    猜你喜欢
    • 1970-01-01
    • 2021-07-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多