Platonic Solids

../../_images/anim_bases.png

Animation control:

Visualization

Frame Value

Surface geometry

constant

Surface position

fixed to the coordinate axis

Surface color

constant

Shading and highlighting

illumination direction per frame

Axis coordinate

azim per frame using view_init

When changing the axis coordinate, the cmap shading results in ‘stationary viewer’ perception. The view is rotated about multiple surface objects.

import copy
import numpy as np
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu

#.. Relative to the Viewer Animation

# 0. Define animation control parameters ............................

totalTime, f_domain, numFrames = 9, (0.0,1.0), 90   # time in seconds
frames=np.linspace(*f_domain, numFrames, endpoint=False)
interval = int(1000.0*totalTime/numFrames)          # milliseconds

# 2. Setup surfaces and text ........................................
cmu.rgb_cmap_gradient([0.25,0.15,0],[1,.9,.75],'cardboard')
surfdata = [ ['tetra', [0,-2,0] ], ['octa', [2,1,0] ],
             ['icosa', [-2,1,0] ], ['cube', [0,0,2] ], ['dodeca', [0,0,-2] ] ]
view_elev, illum_dir = 33, [.5,1,.7]
start_f = 0

surface_set,surf_labels = [],[]
for data in surfdata :
    surface = s3d.SphericalSurface.platonic(basetype=data[0])
    surface.transform(translate=data[1])
    surface_set.append(surface)
    surf_labels.append( [ data[1][0], data[1][1], data[1][2] +1.3, data[0] ] )

# 3. Construct figure, add surfaces, and plot ......................

minmax = (-2,2)
fig = plt.figure(figsize=plt.figaspect(1))
ax = fig.add_subplot(111, projection='3d', aspect='equal')
ax.set(xlim=minmax, ylim=minmax, zlim=minmax)
for text in surf_labels : ax.text(*text,ha='center', va='center')
ax.set_axis_off()

azim = 360*start_f
ax.view_init(elev=view_elev, azim=azim)
illum = s3d.rtv(illum_dir, view_elev, azim)

for orig_surface in surface_set :
    surface = copy.copy(orig_surface)
    azim = 360*start_f
    illum = s3d.rtv(illum_dir, view_elev, azim)
    surface.map_cmap_from_normals( cmap='cardboard', direction=illum )
    ax.add_collection3d(surface)

fig.tight_layout(pad=0)
#plt.show()

# 4. Animation ======================================================

def update_fig(frame):
    azim = 360*frame
    ax.view_init( elev=view_elev, azim=azim )
    illum = s3d.rtv(illum_dir, view_elev, azim)

    for orig_surface in surface_set :
        surface = copy.copy(orig_surface)
        surface.map_cmap_from_normals( cmap='cardboard', direction=illum )
        ax.add_collection3d(surface)
    return

anim = FuncAnimation(fig, update_fig, frames, interval=interval, repeat=True)
anim.save('bases.html',writer='html')

msg = "saved {} frames, values: [{:.3f} to {:.3f}] @ {} milliseconds/frane"
print(msg.format(numFrames,np.min(frames),np.max(frames),interval))