Earth InteriorΒΆ

../../_images/anim_inner_earth.png

Animation control:

Visualization Frame Value
Surface geometry functional clipping per frame
Planar geometry functional parameter per frame
Surface position fixed to the coordinate axis
Planar position functional parameter per frame
Surface color constant
Planar color color map slice per frame
Shading and highlighting fixed to the coordinate axis
Axis coordinate constant
import copy
import numpy as np
from matplotlib import cm
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import matplotlib.animation as animation
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu

# 1. Define function to examine ....................................

rez, inner_size, core_size = 6, 0.7, 0.325
refmap = "hot"
ex_color   =  (cm.get_cmap(refmap)(1))
core_color =  (cm.get_cmap(refmap)(1-core_size))
inner_color = (cm.get_cmap(refmap)(1-inner_size))

def getParams(f):
    a_list = [ 1.0, -inner_size, 1.0]
    s_list = [ 1.0, 0.0, -1.0]
    return s3d.frame_to_value(f,a_list,s_list)

def ringDef(rtz,minRad,maxRad) :
    r,t,z = rtz
    m = (maxRad-minRad)/2.0
    b = (maxRad+minRad)/2.0
    R = m*z + b
    Z = np.zeros(len(z))
    return R,t,Z
 
def getPlane(a,cSize) :
    # -1 < a < 1
    absA = np.abs(a)
    b = np.sqrt( 1 - a*a )
    if absA < cSize :
        cmap = cmu.section_cmap(refmap,0,1-cSize)
        plane = s3d.CylindricalSurface.grid(30,50,cmap=cmap)
        plane.map_cmap_from_op( lambda rtz : 1-rtz[2] )
        c = np.sqrt( cSize*cSize - a*a )
        plane.map_geom_from_op( lambda rtz :ringDef(rtz,c,b))
        plane.transform( [ [0,0,-1], [0,1,0], [1,0,0] ] , 1, [a,0,0] )
    else :    
        cmap = cmu.section_cmap(refmap,0,1-absA)
        plane = s3d.PolarSurface(5, cmap=cmap)
        plane.map_cmap_from_op( lambda rtz : 1-rtz[0]  )
        plane.transform( [ [0,0,-1], [0,1,0], [1,0,0] ] , b, [a,0,0] )
    return plane

def getSurfaces(f,core,interior,exterior) :
    aVal, sVal = getParams(f)
    surface = core + exterior.clip( lambda xyz : xyz[0]<aVal , usexyz=True )
    if sVal>0 :
        surface = surface + getPlane(aVal,core_size)
    else :
        if np.abs(aVal) <  inner_size :
            temp = interior.clip( lambda xyz : xyz[0]<aVal , usexyz=True )
            surface = surface + temp   # + getPlane(aVal,inner_size)
        surface = surface  + getPlane(aVal,inner_size)
    return surface

# 2. Setup and map surface .........................................

fID = .265

core = s3d.SphericalSurface(rez-1, basetype='octa', color=core_color).transform(scale=core_size)
core.shade(.8).hilite(.5,[1,-1,1])

base_exterior = s3d.SphericalSurface(rez)
base_exterior.map_color_from_image('data/blue_marble.png').shade(.5,[0,0,1])
exterior = copy.copy(base_exterior)
base_interior = s3d.SphericalSurface(rez, basetype='octa', color=inner_color).transform(scale=inner_size)
base_interior.shade(.5,[-1,0,-1]).hilite(.5,[1,-1,-1])
interior = copy.copy(base_interior)

surface = getSurfaces(fID,core,interior,exterior)

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

minmax = (-0.75,0.75)
fig = plt.figure(figsize=plt.figaspect(1), facecolor='k' )
ax = fig.add_subplot(111, projection='3d')
ax.set_facecolor('k')
ax.set(xlim=minmax, ylim=minmax, zlim=minmax)
ax.set_axis_off()
ax.view_init(elev=20,azim=-50)

ax.add_collection3d(surface)

fig.tight_layout(pad=0.1)

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

def init_fig():
    return surface,

def update_fig(frame):
    global surface

    ax.collections.remove(surface)

    interior = copy.copy(base_interior)
    exterior = copy.copy(base_exterior)
    surface = getSurfaces(frame,core,interior,exterior)
    ax.add_collection3d(surface)

    return surface,

ani = FuncAnimation(fig, update_fig, frames=np.linspace(0.0, 1.0, 101),
                    init_func=init_fig, blit=False, repeat=True, interval=50)

print(">>>>>>>>>>>>>>> Animation completed, file save proceeds")
#ani.save('ZZZ.mp4')                                   # use for movie file.
ani.save(None,writer=animation.FFMpegFileWriter())    # use for temp files.
print(">>>>>>>>>>>>>>> Save completed, screen display proceeds")

plt.show()