如何在 Mayavi mlab 中为 BuiltinSurface 设置动画?
How to animate a BuiltinSurface in Mayavi mlab?
我正在尝试使用 Mayavi mlab 制作地球旋转的动画。过去,我通过围绕地球的 BuiltinSurface 表示旋转相机取得了成功,但是当我还需要在框架中绘制许多其他物体(航天器、恒星等)时,这变得不方便。下面的代码似乎 "almost" 有效:在我的 Windows 10 机器上,它运行了 8 次迭代,然后动画停止。我该如何修复此代码,或者是否有更好的方法来为 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()
我还没有想出使用 Mayavi 来实现这一目标的方法。然而,Vpython 似乎更适合完成这项任务。我在下面发布了一段代码示例来制作一个旋转的地球,以及一些其他功能。
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)
我正在尝试使用 Mayavi mlab 制作地球旋转的动画。过去,我通过围绕地球的 BuiltinSurface 表示旋转相机取得了成功,但是当我还需要在框架中绘制许多其他物体(航天器、恒星等)时,这变得不方便。下面的代码似乎 "almost" 有效:在我的 Windows 10 机器上,它运行了 8 次迭代,然后动画停止。我该如何修复此代码,或者是否有更好的方法来为 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()
我还没有想出使用 Mayavi 来实现这一目标的方法。然而,Vpython 似乎更适合完成这项任务。我在下面发布了一段代码示例来制作一个旋转的地球,以及一些其他功能。
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)