Dual Surface Face ColorΒΆ
Animation control:
Visualization | Frame Value |
---|---|
Surface geometry | constant |
Surface position | fixed to the coordinate axis |
Surface color | axis per frame using map_cmap_from_normals |
Shading and highlighting | illumination direction per frame |
Axis coordinate | elev and azim per frame using view_init |
Surface construction is based on the Inner and Outer Surface Coloring example. Color mapping based on the view in the map_cmap_from_normals method, as in the Inner and Outer Surface Coloring example, provides front and back surface coloring (direction=ax). Now, both the elev and azim change the shading per frame, same as the Python Cube animation, with the addition of the view information provided by the ax=ax parameter changing surface color.
import copy
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.colors as colors
from matplotlib.animation import FuncAnimation
import matplotlib.animation as animation
import matplotlib.patheffects as path_effects
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu
#.. Elev and Azim changes setting illumination direction and surface coloring.
# 1. Define functions to examine ....................................
view_elev, view_azim = 0, 0
illum_dir = [1,1,1]
def fig_8_knot(t,isInner) :
T = 2*np.pi*t
# https://en.wikipedia.org/wiki/Figure-eight_knot_(mathematics)#Description
x = (2 + np.cos(2*T))*np.cos(3*T)
y = (2 + np.cos(2*T))*np.sin(3*T)
z = 3*np.sin(4*T)
f = 0.8 if isInner else 1.2
return f*x,f*y,f*z
inn_eight = lambda t : fig_8_knot(t,True)
out_eight = lambda t : fig_8_knot(t,False)
# 2. Setup and map surface .........................................
rez=8
bcmap = cmu.binary_cmap('orange', 'yellowgreen', name='orng_yg' )
line_1 = s3d.ParametricLine(rez,inn_eight)
line_2 = s3d.ParametricLine(rez,out_eight)
knot = line_1.get_surface_to_line(line_2)
orig_knot = copy.copy(knot)
# 3. Construct figure, add surface plot ............................
minmax = (-3,3)
fig = plt.figure(figsize=plt.figaspect(1), facecolor='black')
ax = plt.axes(projection='3d')
ax.set(xlim=(-1,1), ylim=(-1,1), zlim=(-1,1))
ax.set_facecolor('black')
ax.set_axis_off()
ax.set(xlim=minmax,ylim=minmax,zlim=minmax)
info = 'Created with S3Dlib 1.1.0, 2022 - https://s3dlib.org'
kgreen, korange = colors.to_rgba('green'), colors.to_rgba('orange')
text = fig.text(0.02, 0.02, info, color=korange, fontsize=9 )
text.set_path_effects([path_effects.withSimplePatchShadow(linewidth=3, foreground=kgreen)])
knot.map_cmap_from_normals(direction=ax,cmap=bcmap)
knot.shade(0.1,direction=illum_dir,ax=ax).hilite(.5,direction=illum_dir,ax=ax)
ax.add_collection3d(knot)
fig.tight_layout(pad=0)
# 4. Animation ......................................................
def init_fig():
return knot,
def update_fig(frame):
global knot
ax.collections.remove(knot)
view_elev = 360*frame
view_azim = 360*frame
if view_elev >= 270 : view_elev = view_elev - 360
ax.view_init( elev=view_elev, azim=view_azim )
knot = copy.copy(orig_knot)
knot.map_cmap_from_normals(direction=ax,cmap=bcmap)
knot.shade(0.1,direction=illum_dir,ax=ax).hilite(.5,direction=illum_dir,ax=ax)
ax.add_collection3d(knot)
return knot,
ani = FuncAnimation(fig, update_fig, frames=np.linspace(0.0, 1.0, 91),
init_func=init_fig, blit=False, repeat=True, interval=100)
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()
print(">>>>>>>>>>>>>>> process completed")