Setup¶

In [1]:
import math
import matplotlib
from matplotlib.animation import FuncAnimation as FA
from matplotlib.patches import Circle as mpC

import matplotlib.pyplot as plt
import numpy as np

Constants and Helpers¶

In [2]:
#Path Colors.
pc = ['#7AD151FF', '#2A788EFF', '#440154FF']



#Clear axes.
def clearAx(ax) :
    ax.spines["top"].set_visible(False)
    ax.spines["right"].set_visible(False)
    ax.spines["bottom"].set_visible(False)
    ax.spines["left"].set_visible(False)
    ax.set_xticks([])
    ax.set_yticks([])
    return(ax)


#Your data.
#Your path, (x, y).
#Your tank, in gallons.
#i = 0 - 800 
def getXYG(i) :
    
    #Radians.
    #800 frames.
    #Use North as 0 degrees, going counterclockwise.
    r = 2 * math.pi * i / 800 + math.pi/2

    if i <= 100 : 
        g = 20 - i/20
    elif i <= 200 :
        g = 25 - i/20
    elif i <= 600 : 
        g = 30 - i/20
    elif i <= 700 : 
        g = 35 - i/20   
    else :
        g = 40 - i/20
   
    return([1.03 * math.cos(r), 1.03 * math.sin(r), g])



#Helper 1's data.
#Helper 1's path, (x, y).
#Helper 1's tank, in gallons.
#i = 0 - 800 
def get_H1_XYG(i): 

    if i <= 200 :
        xyg = getXYG(i)
    #Goes back to Gas Station.    
    elif i <= 400 :
        xyg = [getXYG(400-i)[0], getXYG(400-i)[1], 20 - i/20]
    #Goes back to you around other side.
    elif i <= 600 :
        xyg = [getXYG(1200-i)[0], getXYG(1200-i)[1], 40 - i/20]
    else :
        xyg = getXYG(i)
    
    return((np.array([xyg]) / np.array([1.03, 1.03, 1]))[0])

        
#Helper 2's data.
#Helper 2's path, (x, y).
#Helper 2's tank, in gallons.
#i = 0 - 800 
def get_H2_XYG(i): 

    if i <= 100 :
        xyg = getXYG(i)
    elif i <= 200 :
        #Goes back to Gas Station.
        xyg = [getXYG(200-i)[0], getXYG(200-i)[1], 10 - i/20]
    elif i <= 600 :
        xyg = [0, 1.03, 20]
    elif i <= 700 :
        xyg = [getXYG(1400-i)[0], getXYG(1400-i)[1], 50 - i/20]
    else :
        xyg = getXYG(i)
    
    return((np.array([xyg]) / np.array([1.03/0.97, 1.03/0.97, 1]))[0])


#Total gas consumed.
def totGas(i):
    
    #A frame is 1/20 of a gallon.
    
    #All three are moving.
    if i <= 200 :
        g = 3 * i/20
    #Helper 2 is stationary.
    elif i <= 600 :
        g = 10 + 2 * i/20
    #All three are moving.
    else :
        g = 3 * i/20 - 20 
        
    return(g)

Animate¶

In [3]:
matplotlib.rc_file_defaults()

fig = plt.figure(figsize = (9, 6))
ax = fig.add_subplot(xlim = (-1.1, 2.2),
                     ylim = (-1.1, 1.1))

#Remove axes and ticks.
ax = clearAx(ax)

font = {'size' : 14, 'weight' : 'bold'}

#Twelve artists:
#Road, Gas Station.
#Your car, H1's car, H2's car.
#Your gas, H1's gas, H2's gas.
#Total gas burned.

road = mpC(xy = [0, 0], 
           radius = 1,
           edgecolor = '#999999FF',
           linewidth = 7,
           facecolor = 'white',
           zorder = 1)

gs = mpC(xy = [0, 1], 
         radius = 0.05,
         edgecolor = '#333333FF',
         linewidth = 3,
         facecolor = '#333333FF',
         zorder = 1)

c1 = mpC(xy = [0, 1.03], 
         radius = 0.025,
         edgecolor = pc[0],
         linewidth = 3,
         facecolor = pc[0],
         zorder = 2,
         label = 'Helper1')
c2 = mpC(xy = [0, 1], 
         radius = 0.025,
         edgecolor = pc[1],
         linewidth = 3,
         facecolor = pc[1],
         zorder = 2,
         label = 'You')
c3 = mpC(xy = [0, 0.97], 
         radius = 0.025,
         edgecolor = pc[2],
         linewidth = 3,
         facecolor = pc[2],
         zorder = 2,
         label = 'Helper 2')

g1_text = plt.text(1, -0.45, '', c = pc[0], ha = 'left', va = 'center', **font)
g2_text = plt.text(1, -0.6, '', c = pc[1], ha = 'left', va = 'center', **font)
g3_text = plt.text(1, -0.75, '', c = pc[2], ha = 'left', va = 'center', **font)
gAll_text = plt.text(1, -0.9, '', c = '#999999FF', ha = 'left', va = 'center', **font)
gs_text = plt.text(0, 1.1, '', c = '#333333FF', ha = 'center', va = 'center', **font)


def init():

    ax.add_patch(road)
    ax.add_patch(gs)
    
    ax.add_patch(c1)
    ax.add_patch(c2)
    ax.add_patch(c3)
    
    g1_text.set_text('')
    g2_text.set_text('')
    g3_text.set_text('')
    gAll_text.set_text('')
    gs_text.set_text('Gas Station')
    
    return road, gs, c1, c2, c3, g1_text, g2_text, g3_text, gAll_text, gs_text

def animate(i):
    
    
    new_you = getXYG(i)
    #print(new_you)
    new_h1 = get_H1_XYG(i)
    #print(new_h1)
    new_h2 = get_H2_XYG(i)
    #print(new_h2)
  
    c1.set_center([new_you[0], new_you[1]])
    c2.set_center([new_h1[0], new_h1[1]])
    c3.set_center([new_h2[0], new_h2[1]])
    

    g1_text.set_text('Your Tank: %.2f gallons' % new_you[2])
    g2_text.set_text('H1 Tank: %.2f gallons' % new_h1[2])
    g3_text.set_text('H2 Tank: %.2f gallons' % new_h2[2])
    gAll_text.set_text('Total Consumed: %.2f gallons' % totGas(i))

    return c1, c2, c3, g1_text, g2_text, g3_text, gAll_text

#Run animation.
anim = FA(fig, animate, init_func = init, frames = 801, interval = 30, blit = True)       

#Save animation.
anim.save('2024.03.08 EC.mp4');

Rohan Lewis¶

2024.03.11¶