Conic SectionsΒΆ

../../_images/anim_conic.png

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))