Search code examples
pythonanimationmayavi

Mayavi: animating an octahedron outline without blocking


I am trying to animate an octahedron. Here is the code for that. A simpler version of this code would be found on this different question on SO. Using the code there and the style of the animate object as used here I tried to make a functional animation. The only problem is- the animation hangs up the plot window!

import numpy as np
import mayavi.mlab as ML
import math
import time

def produce_verts(A,t):
    delta=lambda A,t:A*math.sin(t)
    verts =lambda d: [(1+d,0,0), (0,1+d,0), (-1-d,0,0), (0,-1-d,0), (0,0,1+d), (0,0,-1-d)]
    return zip(*verts(delta(A,t)))

t=0.
dt=0.01
A=0.5
ML.clf()
nverts=6
x, y, z = produce_verts(A,t)
# Each triangle is a 3-tuple of indices. The indices are indices of `verts`.                                                                                                                                        
triangles = [(i, (i+1)%4, j) for i in range(4) for j in (4,5)]
colorval = [x[i]**2+y[i]**2+z[i]**2 for i in range(nverts)]
mesh=ML.triangular_mesh(x, y, z, triangles, scalars=colorval, opacity=1,representation='mesh')
MS=mesh.mlab_source
Bool=True
while Bool:
    t=(t+dt)%(2*math.pi)
    x,y,z=produce_verts(A,t)
    colorval = [x[i]**2+y[i]**2+z[i]**2 for i in range(nverts)]
    MS.reset(x=x,y=y,z=z,scalars=colorval)
    time.sleep(1.)
    print t,dt
    if t>4:
        Bool=False

Solution

  • I don't think the plot is hanging. It's just that dt is so small and the time.sleep is so large that it tries your patience. If you set dt equal to, say, 0.1, and remove the time.sleep call, then the plot becomes more animated.

    Also, use MS.reset when the size of the arrays change. When the size of the arrays stays the same, you'll get better performance using MS.set:

    import numpy as np
    import mayavi.mlab as ML
    import math
    import time
    
    
    def produce_verts(A, t):
        def delta(A, t):
            return A * math.sin(t)
        def verts(d):
            return [(1 + d, 0, 0), (0, 1 + d, 0), (-1 - d, 0, 0), (0, -1 - d, 0),
                    (0, 0, 1 + d), (0, 0, -1 - d)]
        return zip(*verts(delta(A, t)))
    
    t = 0.
    dt = 0.1
    A = 0.5
    ML.clf()
    nverts = 6
    x, y, z = produce_verts(A, t)
    # Each triangle is a 3-tuple of indices. The indices are indices of `verts`.
    triangles = [(i, (i + 1) % 4, j) for i in range(4) for j in (4, 5)]
    colorval = [xi ** 2 + yi ** 2 + zi ** 2 for xi, yi, zi in zip(x, y, z)]
    mesh = ML.triangular_mesh(
        x, y, z, triangles, scalars=colorval, opacity=1, representation='mesh')
    ms = mesh.mlab_source
    while True:
        t = (t + dt) % (2 * math.pi)
        x, y, z = produce_verts(A, t)
        colorval = [xi ** 2 + yi ** 2 + zi ** 2 for xi, yi, zi in zip(x, y, z)]
        ms.set(x=x, y=y, z=z, scalars=colorval)
        # time.sleep(0.1)
        print t, dt
        if t > 4:
            break
    
    ML.show()