Earth InteriorΒΆ

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 colormaps
from matplotlib import pyplot as plt
from matplotlib.animation import FuncAnimation
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu

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

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

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

rez, inner_size, core_size = 6, 0.7, 0.325
refmap = "hot"
ex_color   =  (colormaps[refmap](1))
core_color =  (colormaps[refmap](1-core_size))
inner_color = (colormaps[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 :
        if (1-absA) < 0.05 : 
            plane = s3d.PolarSurface(5, color=colormaps[refmap](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', aspect='equal', 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)
#plt.show()

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

def update_fig(frame):
    global surface
    surface.remove()

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

    return

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

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