Conic SectionsΒΆ
Animation control:
Visualization |
Frame Value |
---|---|
Contour Line position |
distance parameter per frame |
Contour Line normal |
yz-component parameter per frame |
Contour Line color |
color per frame |
Shading and highlighting |
fixed to the coordinate axis |
Axis coordinate |
constant |
Based on the static plot from the Surface Contours example.
For this animation, the two parameters controlling the planar contours are varied with the frame: the distance of the plane from the origin, and the angle of the plane normal direction (parallel to the x-axis).
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.colors import ListedColormap
import s3dlib.surface as s3d
import numpy as np
#.. Animated Conic Sections
# 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=True)
interval = int(1000.0*totalTime/numFrames) # milliseconds
# 1. Define function to examine .....................................
a, b, c, d = 0.8, 0.4, -.4, -.6
cd = (c+d)/2
p=.5
dist = [ a, b, 0, 0, c, cd, d, -a ]
nang = [ 1, p, p, 0, 0, -p, -1, -1 ]
colors = ['C1','C2','C9','C0','C0','C1','C3' ]
def cone(rtz) :
r,t,z = rtz
R = np.abs(z)+0.001
return R,t,z
def get_line(A,coneSurf) :
# 0 < A < 1
distance,ang = s3d.frame_to_value(A,dist,nang)
color = s3d.frame_to_value(A,colors ,step=True)[0]
phi = np.pi*ang/2
direction = [ np.cos(phi),0,np.sin(phi)]
contour = coneSurf.contourLines(distance,-distance,direction=direction,color=color,coor='p')
return contour.fade(0.2,15)
def indicator_by_A(fig, A, vOld=None) :
symbol, blank = r'$\blacktriangleright$', r'$\blacksquare$'
symbol, blank = r'$\blacktriangleleft$', r'$\blacksquare$'
horz, vBot, vRng = 0.93, 0.208, 0.582
vert = vBot + vRng*A
if vOld is not None:
fig.text(horz+.001,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_A = 4, 0.5
cmap = ListedColormap(colors)
surface = s3d.CylindricalSurface(rez,color='grey',cmap=cmap,lw=0.0)
surface.map_geom_from_op(cone)
surface.shade(.25).set_surface_alpha(.1)
line = get_line(start_A,surface)
# 3. Construct figure, add surface, plot ............................
fig = plt.figure(figsize=plt.figaspect(.7),constrained_layout=True)
ax = plt.axes(projection='3d')
ax.view_init(15)
plt.colorbar(surface.cBar_ScalarMappable, ax=ax, shrink=0.6, pad=.3, ticks=[] )
tL, tB, tD = 0.80, 0.25, 0.08
tL, tB, tD = 0.87, 0.25, 0.08
fig.text(tL,tB, 'Ellipses', ha='right')
fig.text(tL,tB+1*tD,'Parabolas', ha='right')
fig.text(tL,tB+2*tD,'Lines', ha='right')
fig.text(tL,tB+3.5*tD,'Hyperbolas', ha='right')
fig.text(tL,tB+5*tD,'Ellipses', ha='right')
fig.text(tL,tB+6*tD,'Circles', ha='right')
minmax = (-1.1,1.1)
ax.set(xlim=minmax, ylim=minmax, zlim=(-0.6,0.6))
ax.set_axis_off()
ax.add_collection3d(surface)
ax.add_collection3d(line)
prevIndicator = indicator_by_A(fig, start_A)
#plt.show()
# 4. Animation ======================================================
def update_fig(frame):
global line
global prevIndicator
line.remove()
line = get_line(frame,surface)
prevIndicator = indicator_by_A(fig, frame, prevIndicator)
ax.add_collection3d(line)
return
anim = FuncAnimation(fig, update_fig, frames, interval=interval, repeat=True)
anim.save('conic.html',writer='html')
msg = "saved {} frames, values: [{:.3f} to {:.3f}] @ {} milliseconds/frane"
print(msg.format(numFrames,np.min(frames),np.max(frames),interval))