简体   繁体   English

如何为Mayavi mlab中的BuiltinSurface设置动画?

[英]How to animate a BuiltinSurface in Mayavi mlab?

I'm attempting to animate the Earth rotating using Mayavi mlab. 我正在尝试使用Mayavi mlab为地球旋转设置动画。 I've succeeded in the past by just rotating the camera around a BuiltinSurface representation of the Earth, but this becomes inconvenient when I need to plot many other objects (spacecraft, stars, etc) in the frame as well. 过去,我只是通过围绕地球的BuiltinSurface表示旋转相机而获得成功,但是当我还需要在框架中绘制许多其他对象(航天器,恒星等)时,这样做变得很不方便。 The code below seems to "almost" work: on my Windows 10 machine, it runs for 8 iterations and then the animation freezes. 下面的代码似乎“几乎”可以工作:在我的Windows 10计算机上,它运行8次迭代,然后动画冻结。 How can I fix this code, or is there a better way to animate a BuiltinSurface in general? 我该如何解决此代码,或者一般而言,是否有更好的方法来对BuiltinSurface进行动画处理?

import numpy as np
from mayavi import mlab
from mayavi.sources.builtin_surface import BuiltinSurface
from mayavi.modules.surface import Surface
from mayavi.filters.transform_data import TransformData


def rotMat3D(axis, angle, tol=1e-12):
    """Return the rotation matrix for 3D rotation by angle `angle` degrees about an
    arbitrary axis `axis`.
    """
    t = np.radians(angle)
    x, y, z = axis
    R = (np.cos(t))*np.eye(3) +\
    (1-np.cos(t))*np.matrix(((x**2,x*y,x*z),(x*y,y**2,y*z),(z*x,z*y,z**2))) + \
    np.sin(t)*np.matrix(((0,-z,y),(z,0,-x),(-y,x,0)))
    R[np.abs(R)<tol]=0.0
    return R



@mlab.show    
@mlab.animate(delay=200)
def anim():

    fig = mlab.figure()

    engine = mlab.get_engine()

    # Add a cylinder builtin source
    cylinder_src = BuiltinSurface()
    engine.add_source(cylinder_src)
    cylinder_src.source = 'earth'
    # Add transformation filter to rotate cylinder about an axis
    transform_data_filter = TransformData()
    engine.add_filter(transform_data_filter, cylinder_src)
    Rt = np.eye(4)
    Rt[0:3,0:3] = rotMat3D((0,0,1), 0) # in homogeneous coordinates
    Rtl = list(Rt.flatten()) # transform the rotation matrix into a list

    transform_data_filter.transform.matrix.__setstate__({'elements': Rtl})
    transform_data_filter.widget.set_transform(transform_data_filter.transform)
    transform_data_filter.filter.update()
    transform_data_filter.widget.enabled = False   # disable the rotation control further.

    # Add surface module to the cylinder source
    cyl_surface = Surface()
    engine.add_filter(cyl_surface, transform_data_filter)
    #add color property
    #cyl_surface.actor.property.color = (1.0, 0.0, 0.0)

    ind=1
    while ind<90:
        print ind
        Rt[0:3,0:3] = rotMat3D((0,0,1), ind) # in homogeneous coordinates
        Rtl = list(Rt.flatten()) # transform the rotation matrix into a list

        transform_data_filter.transform.matrix.__setstate__({'elements': Rtl})
        transform_data_filter.widget.set_transform(transform_data_filter.transform)
        transform_data_filter.filter.update()
        transform_data_filter.widget.enabled = False   # disable the rotation control further.

        # Add surface module to the cylinder source
        cyl_surface = Surface()
        engine.add_filter(cyl_surface, transform_data_filter)
        # add color property
        #cyl_surface.actor.property.color = (1.0, 0.0, 0.0)

        yield
        ind+=1


anim()

I haven't been able to figure out a way to use Mayavi to make this happen. 我还没有找到使用Mayavi做到这一点的方法。 However, Vpython appears to be much better suited to accomplish this task. 但是,Vpython似乎更适合完成此任务。 I've posted an example section of code below to make a revolving Earth, along with a few other features. 我在下面发布了一个示例代码部分,以制作一个旋转的地球以及其他一些功能。

from visual import *

def destroy():
    for obj in scene.objects:
        obj.visible = False
        del obj

R = 6378. # radius of sphere
angle=0.
scene.range = 10000.
SunDirection=vector(.77,.77,0)
# scene.fov = 0.5
scene.center = (0,0,0)
scene.forward = (-1,0,-1)
scene.up = (0,0,1)
scene.lights=[distant_light(direction=SunDirection, color=color.gray(0.8)),
              distant_light(direction=-SunDirection, color=color.gray(0.3))]
x=0
y=0

while True:
    rate(10)

    angle=angle+1.*pi/180.

    destroy()
    s = sphere(pos=(x,y,0), radius=R, material=materials.BlueMarble)
    s.rotate(angle=90.*pi/180.,axis=(1,0,0)) # Always include this to rotate Earth into correct ECI x y z frame
    s.rotate(angle=90.*pi/180.,axis=(0,0,1)) # Always include this to rotate Earth into correct ECI x y z frame
    s.rotate(angle=angle, axis=(0,0,1)) # This rotation causes Earth to spin on its axis

    xaxis = arrow(pos=(0,0,0),  axis=vector(1,0,0)*7000, shaftwidth=100, color=color.red)
    yaxis = arrow(pos=(0,0,0),  axis=vector(0,1,0)*7000, shaftwidth=100, color=color.green)
    zaxis = arrow(pos=(0,0,0),  axis=vector(0,0,1)*7000, shaftwidth=100, color=color.blue)

    ST = cone(pos=(0,8000,0),axis=(0,700,0),radius=700*tan(10*pi/180),color=color.blue,opacity=1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM