<jupyter_start><jupyter_text>Today we are going to see how some of the math we have learned can be applied to video games. We are going to calculate and animate the trajectory of a soccer ball that has been kicked (think Fifa).  This might seem like a difficult and tedious task, but really we only need a little bit of physics and coding ability to accomplish this .  As we go, we will build up our equations to account for different conditions (like spin and wind speed), but first, we need to talk about parametric vector equations.We know that vectors have a direction and magnitude and that we may place them anywhere in a coordinate system without changing the vector (eg. we can put the vector $ \left[ {\begin{array}{cc}   1  \\   1  \\  \end{array} } \right]$ with its tail at the origin or at the point $(5,0)$, and it will be the same vector.<jupyter_code>import matplotlib.pyplot as plt
import numpy as np 


# create vector as numpy array
a = np.array([1,1])

# create figure with vector plotted at (0,0) and (5,0)
f, ((ax1,ax2)) = plt.subplots(1,2, sharex = True, sharey=True)
f.set_size_inches((10,3))

#set x and y axis limits for subplots
plt.xlim((0,7))
plt.ylim((0,2))

#plot the vector at (0,0) and (5,0)
ax1.quiver([0],[0], a[0],a[1], color = 'b', angles='xy', scale_units='xy', scale=1)
ax2.quiver([5],[0], a[0],a[1], color = 'b', angles='xy', scale_units='xy', scale=1)
plt.show()<jupyter_output><empty_output><jupyter_text>For trajectories of objects it is customary to choose the tail of a vector to remain fixed and for the head of the arrow to point to the location of the object in our coordinate system for a given point in time.  Therefore, we can define a time dependent vector $ \left[ {\begin{array}{cc}   x(t)  \\   y(t)  \\  \end{array} } \right]$ which tracks the $x$ position, $x(t)$, and $y$ position, $y(t)$, of our object in time and has its tail at the origin.  As an example, we show how this vector changes in time and points to an object that is moving in a sinusoidal trajectory.For this system the parametric equation is    ${\bf{g}}(t) =  \left[ {\begin{array}{cc}   x(t)  \\   y(t)  \\  \end{array} } \right]=\left[ {\begin{array}{cc}   t  \\   sin(t)  \\  \end{array} } \right]$    The trajectory is given below, and the animation tracks the position of the object along the trajectory as time evolves.  You can imagine that this is the trajectory of some kind of bug running from side to side (y-direction) and forward (x-direction) on a desk as you try to squash it.<jupyter_code>from matplotlib import animation, rc
import matplotlib.pyplot as plt
import numpy as np 
from IPython.display import HTML, Image

#clear figure
plt.clf()

# define a function that tracks the y position as a function of time
def y(t):
    return np.sin(t)

# define a function that tracks the x position as a function of time 
def x(t):
    return t

# create figure and axes object
fig, ax = plt.subplots(1,1)

# create a quiver object which we will later use to draw our vectors with 
Q= ax.quiver([0],[0],color='b',angles='xy', scale_units='xy', scale=1)

# create a text object which we will later use to denote the time
R = ax.text(5,1,'')

# set limits for x and y axes in the plot
ax.set_xlim(-1, 11)
ax.set_ylim(-1.25,1.25)

# name the axes
plt.xlabel('x(t)')
plt.ylabel('y(t)')

# plot the trajectory, first step creates array of values for time from 0 to 10 with 1000 equally spaced values
t = np.linspace(0,10, 1000)
ax.plot(t, y(t))

def init():
    # the init function will draw the initial frames for our animation.  In this case, we set the data in our 
    # quiver object to nothing and the text to nothing
    Q.set_UVC([],[])
    R.set_text('')
    return Q,  R, 

def animate(i):
    # in animate we draw the objects that will change from frame to frame
    
    # set the 
    Q.set_UVC([x(i/10.0)],[y(i/10.0)])
    #ax.quiver([x(i/10.0)],[y(i/10.0)],color='b',angles='xy', scale_units='xy', scale=1)
    R.set_text('t = '+str(i/10.0))
    return Q, R,

# create animation object
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True)

# this allows us to view the animation in the jupyter notebook 
rc('animation', html='html5')

# call on the animation object
anim<jupyter_output><empty_output><jupyter_text>Derivatives of parametric functions behave somewhat similarly to typical derivatives.  Recall that the definition of a derivative for one variable is given by$f'(t)=\lim_{\Delta t \to 0 } \frac{f(t+\Delta t) -f(t)}{\Delta t}$, and evaluating the derivative at a given point results in the slope of the tangent line to the curve at that point.  This is illustrated below.<jupyter_code>import matplotlib.pyplot as plt 

plt.clf()

# create figure and axis object
fig, ax = plt.subplots(1,1)

# create array of times to use for plotting
t = np.linspace(-5,5, 1000)

# create function
def f(t):
    return 2*t**3-3*t-1

# array of points to evaluate tangent line on 
x = np.linspace(-2,5, 200)

# line tangent to curve at 
def g(x):
    return 51*x -109

    
# create artist objects to add to legend later (in this case plots)
curve1, = ax.plot(t, f(t), label = r'f(t)')
curve2, =ax.plot(x, g(x), color= 'r', label = 'tangent curve')

#plotting line segments for derivative definition stuff
ax.plot([3, 3.7],[44,44])
ax.plot([3.7, 3.7],[44,89.2])

# label x axis and line segments
ax.set_xlabel('t')
ax.text(4, 55, r'$f(t+\Delta t)-f(t)$')
ax.text(3.2, 10, r'$\Delta t$')

# Create a legend for the first line.
first_legend = plt.legend(handles=[curve1, curve2], loc=2)
# Add the legend manually to the current Axes.
plt.gca().add_artist(first_legend)

#display plot
plt.show()<jupyter_output><empty_output><jupyter_text>What is the geometric interpretation the derivative of a parametric equation? The definition is similar to the derivative for a one variable function. ${\bf{f}}(t) =  \left[ {\begin{array}{cc}   x(t)  \\   y(t)  \\  \end{array} } \right]$  $\lim_{\Delta t \to 0 } \frac{{\bf{f}}(t+\Delta t) -{\bf{f}}(t)}{\Delta t}=\lim_{\Delta t \to 0 }\frac{\left[ {\begin{array}{cc}   x(t+\Delta t)  \\   y(t +\Delta t)  \\  \end{array} } \right]-\left[ {\begin{array}{cc}   x(t)  \\   y(t)  \\  \end{array} } \right] }{\Delta t}$.    Below, the red vector shows the difference vector between the two blue vectors, ${\bf{f}}(t + \Delta t)$ and ${\bf{f}}(t)$.  What happens as $\Delta t$ shrinks to 0?  What is the interpretration of ${\bf{f}}'(t)$ if ${\bf{f}}(t)$ is a trajectory?     Also, notice that although a one variable derivative has a similar geometric meaning to a vector derivative, time does not appear on any of the axes for the trajectory.  Instead, it controls how quickly the object moves over the trajectory.<jupyter_code>import matplotlib.pyplot as plt
# define a function that tracks the y position as a function of time
def y(t):
    return np.sin(t)

# define a function that tracks the x position as a function of time 
def x(t):
    return t**2

# create array for time values
t = np.linspace(0,10, 100)

# create figure and axis object
fig, ax = plt.subplots(1,1)

# name the axes
plt.xlabel('x(t)')
plt.ylabel('y(t)')

# plot the curve
ax.plot(x(t), y(t))

#plot vectors
ax.quiver([x(6.5)],[y(6.5)],color='b',angles='xy', scale_units='xy', scale=1)
ax.quiver([x(7.25)],[y(7.25)],color='b',angles='xy', scale_units='xy', scale=1)
ax.quiver([x(6.5)], [y(6.5)],[x(7.25)-x(6.5)], [y(7.25)-y(6.5)], color='r',angles='xy', scale_units='xy', scale=1)

#label vectors
ax.text(20, 0, r'${\bf{f}}(t)$')
ax.text(20, .55, r'${\bf{f}}(t+\Delta t)$')
ax.text(47, .35, r'${\bf{f}}(t+\Delta t)-{\bf{f}}(t)$')

# display plot
plt.show()<jupyter_output><empty_output><jupyter_text>Below, we animate the position vector (blue) as it follows the trajectory of the object, and we show the velocity vector (red) of the particle.  We put the velocity vector at the position of the object at the given time in the trajectory.<jupyter_code>from matplotlib import animation, rc
import matplotlib.pyplot as plt
import numpy as np 
from IPython.display import HTML, Image

plt.clf()

# define a function that tracks the y position as a function of time
def y(t):
    return np.sin(t)

# define a function that tracks the x position as a function of time 
def x(t):
    return t**2


def vy(t):
    return np.cos(t)

def vx(t):
    return 2*t
# create figure and axes object
fig, ax = plt.subplots(1,1)
ax.clear()
# create a quiver object which we will later use to draw our vectors with 
Q= ax.quiver([0],[0],color='b',angles='xy', scale_units='xy', scale=1)
Q1= ax.quiver([0],[0],color='r',angles='xy', scale_units='xy', scale=1)
# create a text object which we will later use to denote the time
R = ax.text(20,1,'')

#set frame area
ax.set_xlim(-1, 101)
ax.set_ylim(-1.25,1.25)


# plot the curve
t = np.linspace(0,10, 1000)
ax.plot(t**2, y(t))

def init():

    # define a function that tracks the y position as a function of time
    Q.set_UVC([],[])
    Q1.set_UVC([],[])

    R.set_text('')
    return Q, Q1, R,

def animate(i):
    #clear the axis
    ax.clear()
    #reset frame area
    ax.set_xlim(-1, 101)
    ax.set_ylim(-1.25,1.25)

    # name the axes
    plt.xlabel('x(t)')
    plt.ylabel('y(t)')
    
    #plot the curve
    t = np.linspace(0,10, 1000)
    ax.plot(t**2, y(t))
    
    #plot position vector and velocity vector
    Q= ax.quiver([x(i/10.0)],[y(i/10.0)],color='b',angles='xy', scale_units='xy', scale=1)
    Q1= ax.quiver([x(i/10.0)],[y(i/10.0)],[vx(i/10.0)],[vy(i/10.0)],color='r',angles='xy', scale_units='xy', scale=1)
    #show time
    R = ax.text(20,1, 't = '+str(i/10.0))
    return Q, Q1, R,
    
# create animation object
anim = animation.FuncAnimation(fig, animate, init_func=init, frames=100, interval=20, blit=True)
# set rc parameter
rc('animation', html='html5')
#call animation object
anim<jupyter_output><empty_output><jupyter_text>Just as the velocity vector is given by the derivative of the position parametric curve, the acceleration vector is given by the derivative of the velocity vector curve or the second derivative of the position parametric curve. As a final treat, we can make a 3 dimensional curve in python and track the position (blue), velocity (red) and acceleration (green) vectors.  Feel free to play around with the functions used and make sure to scale the limits of the x, y and z axes accordingly.  Have Fun!<jupyter_code>from matplotlib import animation, rc
import matplotlib.pyplot as plt
import numpy as np 
from IPython.display import HTML, Image
from mpl_toolkits.mplot3d import Axes3D
from ipywidgets import *


def makeAnimation(phi, theta):
    plt.close()
    def x(t):
        return 10*t
    def y(t):
        return 5*np.sin(t) 
    def z(t):
        return 5*np.cos(t)
    def vx(t):
        return 10
    def vy(t):
        return 5*np.cos(t)
    def vz(t):
        return -5*np.sin(t)
    def acx(t):
        return 0
    def acy(t):
        return -5*np.sin(t)
    def acz(t):
        return -5* np.cos(t)
    
    fig = plt.figure(figsize=(10, 10), dpi= 80, facecolor='w', edgecolor='k')
    ax = fig.add_subplot(111,projection='3d')

    ax.clear()
    def init():
        t = np.linspace(0,10, 100)
        xdat = x(t)
        ydat = y(t)
        zdat = z(t)
        ax.set_xlim(np.min(xdat)-1,np.max(xdat)+1)
        ax.set_ylim(np.min(ydat)-1,np.max(ydat)+1)
        ax.set_zlim(np.min(zdat)-1,np.max(zdat)+1)
        ax.set_xlabel('x(t)')
        ax.set_ylabel('y(t)')
        ax.set_zlabel('z(t)')

        S = ax.plot(xdat, ydat, zdat)
        Q1 = ax.quiver([0],[0],[0], [x(0)], [y(0)],[z(0)], color='b')
        Q2 = ax.quiver([x(0)], [y(0)],[z(0)], [vx(0)], [vy(0)],[vz(0)],color='r')
        Q3 = ax.quiver([x(0)], [y(0)],[z(0)], [acx(0)], [acy(0)],[acz(0)],color='g')
        ax.view_init(elev= phi, azim = theta)
        return  Q1, Q2, Q3

    def animate(i):
        ax.clear()
        t = np.linspace(0,10, 100)
        xdat = x(t)
        ydat = y(t)
        zdat = z(t)
        ax.set_xlim(np.min(xdat)-1,np.max(xdat)+1)
        ax.set_ylim(np.min(ydat)-1,np.max(ydat)+1)
        ax.set_zlim(np.min(zdat)-1,np.max(zdat)+1)
        ax.set_xlabel('x(t)')
        ax.set_ylabel('y(t)')
        ax.set_zlabel('z(t)')
        
        S = ax.plot(xdat, ydat, zdat)
        ax.text(0,0,0,'t = '+str(i*10.0/100) )

        Q1 = ax.quiver([0],[0],[0], [x(i*10./50)], [y(i*10./50)],[z(i*10./50)],color='b')
        Q2 = ax.quiver([x(i*10./50)], [y(i*10./50)],[z(i*10./50)], [vx(i*10./50)], [vy(i*10./50)],[vz(i*10./50)],color='r')
        Q3 = ax.quiver([x(i*10./50)], [y(i*10./50)],[z(i*10./50)], [acx(i*10./50)], [acy(i*10./50)],[acz(i*10./50)],color='g')
        ax.view_init(elev= phi, azim = theta)
        return Q1, Q2, Q3,

    anim = animation.FuncAnimation(fig, animate, init_func=init, frames=50, interval=40, blit=True)
    rc('animation', html='html5')
    return anim

    
anim = interact(makeAnimation, phi= (0, 90,0.05), theta=(0,360, 0.1)) 
anim<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.15729126587148903, 'fraction_numerical': 0.034090034628703345, 'mean_word_length': 3.616696269982238, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 25, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '6', 'dir': 'jupyter-structured-clean-dedup', 'id': '100162', 'license': 'MIT', 'n_tokens_mistral': 5010, 'n_tokens_neox': 4697, 'n_words': 1533, 'path': 'jupyter/parametricVectorEqns.ipynb', 'repo_name': 'LambrechtLab/MoCChA', 'size': '12995'}