2016-06-13 18 views
0

Ich versuche die Erde zu rotieren mit Mayavi mlab. Es ist mir in der Vergangenheit gelungen, die Kamera nur um eine Built-in-Surface-Darstellung der Erde zu drehen, aber das wird unpraktisch, wenn ich viele andere Objekte (Raumschiffe, Sterne usw.) in den Rahmen plotten muss. Der folgende Code scheint "fast" zu funktionieren: auf meinem Windows 10-Computer läuft er für 8 Iterationen und dann friert die Animation ein. Wie kann ich diesen Code reparieren oder gibt es eine bessere Möglichkeit, eine BuiltInSurface allgemein zu animieren?Wie man eine BuiltInSurface in Mayavi mlab animiert?

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() 

Antwort

0

Ich war nicht in der Lage, eine Möglichkeit zu finden, Mayavi zu verwenden, um dies zu erreichen. Jedoch scheint Vpython viel besser geeignet zu sein, um diese Aufgabe zu erfüllen. Ich habe unten einen Codeabschnitt geschrieben, um eine rotierende Erde zusammen mit einigen anderen Features zu erstellen.

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)