Catenoid to HelicoidΒΆ
Animation control:
Visualization |
Frame Value |
---|---|
Surface geometry |
functional parameter per frame |
Surface position |
fixed to the coordinate axis |
Surface color |
color per frame |
Shading and highlighting |
fixed to the coordinate axis |
Axis coordinate |
constant |
Based on the static plots from the Surface Displacement Vector Field and Parametric Set of Surfaces 2 examples.
A parametrization of the deformation is given at Helicoid transformation
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import s3dlib.surface as s3d
import s3dlib.cmap_utilities as cmu
#.. Helicoid Transformation Animation
# 0. Define animation control parameters ............................
totalTime, f_domain, numFrames = 4, (-1.0,1.0), 80 # time in seconds
frames=np.linspace(*f_domain, numFrames, endpoint=False)
interval = int(1000.0*totalTime/numFrames) # milliseconds
# 1. Define functions to examine ....................................
def catenoid_helicoid(rtz, A) :
r,t,z = rtz
theta = A*np.pi # -1 < A < 1
cosT, sinT = np.cos(theta), np.sin(theta)
U, V = t, z
x = cosT * np.sinh(V) * np.sin(U) + sinT * np.cosh(V) * np.cos(U)
y = -cosT * np.sinh(V) * np.cos(U) + sinT * np.cosh(V) * np.sin(U)
Z = ( U/np.pi- 1.0 ) *cosT + V * sinT
return x,y,Z
def colormap_by_A(A) :
hue = (A + 1.0) / 2.0
return cmu.hsv_cmap_gradient( [hue,1.0,0.25], [hue,0.5,1],smooth=1.6 )
def indicator_by_A(fig, A, vOld=None) :
symbol, blank = r'$\blacktriangleright$', r'$\blacksquare$'
horz, vCen, vRng = 0.8, 0.5, 0.28
vert = vCen + vRng*A
if vOld is not None:
fig.text(horz,vOld,blank, ha='right', va='center', fontsize='x-large', color='w')
fig.text(horz,vert,symbol, ha='right', va='center', fontsize='large')
return vert
# 2. Setup and map surfaces .........................................
rez, start_F = 5, -1.0
surface = s3d.CylindricalSurface(rez, basetype='squ_s', cmap=cmu.hue_cmap())
surface.map_geom_from_op( lambda rtz : catenoid_helicoid(rtz,start_F), returnxyz=True )
# 3. Construct figures, add surface, plot ...........................
fig = plt.figure(figsize=plt.figaspect(1))
ax = plt.axes(projection='3d', aspect='equal')
cbar = plt.colorbar(surface.cBar_ScalarMappable, ax=ax, ticks=np.linspace(-1,1,5), shrink=0.6 )
cbar.set_label(r'$\theta$ parameter', rotation=270, labelpad = 15)
cbar.ax.set_yticklabels([r'-$\pi$',r'-$\pi$/2','0',r'$\pi$/2',r'$\pi$'])
# surface mapping placed here to change colormap after colorbar defined.
surface.map_cmap_from_op( lambda rtz : rtz[0],colormap_by_A(start_F))
prevIndicator = indicator_by_A(fig, start_F)
# ....
minmax = (-1.2,1.2)
ax.set(xlim=minmax, ylim=minmax, zlim=minmax )
ax.view_init(25, -28)
ax.set_axis_off()
ax.add_collection3d(surface)
fig.tight_layout(pad=1)
#plt.show()
# 4. Animation ======================================================
def update_fig(frame):
global surface
global prevIndicator
surface.remove()
surface = s3d.CylindricalSurface(rez, basetype='squ_s', antialiased=True)
surface.map_geom_from_op( lambda rtz : catenoid_helicoid(rtz,frame), returnxyz=True )
surface.map_cmap_from_op( lambda rtz : rtz[0],colormap_by_A(frame))
prevIndicator = indicator_by_A(fig, frame, prevIndicator)
ax.add_collection3d(surface)
return surface,
anim = FuncAnimation(fig, update_fig, frames, interval=interval, repeat=True)
anim.save('cat2heli.html',writer='html')
msg = "saved {} frames, values: [{:.3f} to {:.3f}] @ {} milliseconds/frane"
print(msg.format(numFrames,np.min(frames),np.max(frames),interval))