The instructions for building the animations are summed up in a function that will be passed to moviepy
for rendering.
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon, Circle
def draw_witch(theta=1):
POINT_RADIUS = 0.05
CIRCLE_RADIUS = 0.5
ax = plt.gca()
# Triangle
# base vectors
e_x = np.array([1, 0])
e_y = np.array([0, 1])
# points
pt_O = np.array([0, 0])
theta = np.deg2rad(theta)
pt_A = pt_O + 0.5 * e_y + CIRCLE_RADIUS * (np.cos(theta) * (-1 * e_y) + np.sin(theta) * e_x)
pt_N = np.array([pt_A[0]/pt_A[1], 1])
pt_P = np.array([pt_N[0], pt_A[1]])
# Circle
circle = Circle((0, 0.5), radius=0.5, fill=False)
triangle = Polygon(np.vstack((pt_A, pt_N, pt_P)))
# adding artists
ax.add_artist(circle)
ax.add_artist(triangle)
ax.add_artist(Circle(pt_A, radius=POINT_RADIUS, fc='red'))
ax.add_artist(Circle(pt_N, radius=POINT_RADIUS, fc='red'))
ax.add_artist(Circle(pt_P, radius=POINT_RADIUS, fc='red'))
# plot limits
plt.xlim(0, 3)
plt.ylim(0, 3)
plt.figure(figsize=(4, 4))
draw_witch(45)
from IPython.html.widgets import interact
interact(draw_witch,
theta=(1, 180))
The code for rendering the movie, as always inspired by Zulko.
from moviepy.video.io.bindings import mplfig_to_npimage
import moviepy.editor as mpy
duration = 2
fig_mpl, ax = plt.subplots(1, figsize=(3,3), facecolor='white')
ax.set_title("The witch of Maria Agnesi")
# ANIMATE WITH MOVIEPY (UPDATE THE CURVE FOR EACH t). MAKE A GIF.
def make_frame_mpl(t):
draw_witch(37 + (180 - 37) * t/duration) # <= Update the curve
return mplfig_to_npimage(fig_mpl) # RGB image of the figure
animation = mpy.VideoClip(make_frame_mpl, duration=duration)
animation.write_gif("files/witch.gif", fps=20)
[MoviePy] Building file files/witch.gif with imageio
from IPython.display import HTML
HTML("<img src='files/witch.gif'/>")