Download apps/code/trajectory.py from spiruel/satschool: direct link, hf CLI and curl.
- Browser
- Download file 4.06 kB
-
https://huggingface.co/spaces/spiruel/satschool/resolve/main/apps/code/trajectory.py
- Command line
-
hf download hf://spaces/spiruel/satschool/apps/code/trajectory.py
-
curl -L -o trajectory.py https://huggingface.co/spaces/spiruel/satschool/resolve/main/apps/code/trajectory.py
4.06 kB
| from matplotlib import pyplot as plt | |
| from matplotlib.offsetbox import OffsetImage, AnnotationBbox | |
| import numpy as np | |
| def motion(v0, theta, t, g=9.81, x0=0, y0=0): | |
| """ | |
| Computes the trajectory of a projectile, given the initial velocity (v0), | |
| launch angle (theta), and time (t). | |
| """ | |
| x = v0*np.cos(theta)*t | |
| y = v0*np.sin(theta)*t - 0.5 * g * t**2 | |
| return x, y | |
| def get_time(v0, theta, g=9.81, x0=0, y0=0): | |
| """ | |
| Computes the time of flight of a projectile, given the initial velocity (v0), | |
| launch angle (theta), and distance (t). | |
| """ | |
| # Get the time to get back to the ground | |
| # y = v0*np.sin(theta)*t - 0.5 * g * t**2 -> solve for y=0, t!=0 | |
| t_max = 2*v0*np.sin(theta)/g | |
| # Create a time array | |
| t = np.linspace(0, t_max, 100) # 0.1 is the time step | |
| return t | |
| def get_trajectory(v0, theta_deg, g=9.81, gravity_label="", x0=0, y0=0): | |
| """ | |
| Computes the trajectory of a projectile, given the initial velocity (v0), | |
| launch angle (theta, in degrees). It creates a vector with times, and from that a | |
| trajectory. | |
| """ | |
| # Convert theta | |
| theta_rad = theta_deg * np.pi / 180 | |
| # Get the time to get back to the ground | |
| t = get_time(v0, theta_rad, g=g, x0=x0, y0=y0) | |
| # Get the trajectory for the times | |
| x, y = motion(v0, theta_rad, t, g=g, x0=x0, y0=y0) | |
| # Get a legend for the trajectory | |
| legend = f"$v_0$={v0}, $\\theta$={theta_deg:.2f}, g={g} ({gravity_label})" | |
| # Get the color | |
| color_dict = {'Earth':"green", 'Moon':"gray", 'Mars':"red", 'Jupiter':"black"} | |
| color = color_dict[gravity_label] | |
| # Create a dictionary with the trajectory | |
| trajectory_dict = {"x": x, "y": y, "legend": legend, "color": color, "v0": v0, "theta_deg": theta_deg} | |
| return trajectory_dict | |
| def plot_emoji(emoji_path, ax, x, y, zoom=0.35): | |
| """ | |
| Plots an emoji on a figure. | |
| Based on: | |
| https://www.geeksforgeeks.org/emojis-as-markers-in-matplotlib/ | |
| """ | |
| # reading the image | |
| image = plt.imread(emoji_path) | |
| # OffsetBox | |
| image_box = OffsetImage(image, zoom=zoom) | |
| # Drawing the image | |
| ab = AnnotationBbox(image_box, (x, y), frameon=False) | |
| ax.add_artist(ab) | |
| return | |
| def fig_from_list(trajectory_list, pig_position=[]): | |
| """ | |
| Plots the trajectory of a projectile, given computed trajectories. | |
| It optionally plots the pig position. | |
| """ | |
| fig = plt.figure(figsize=(16,12)) | |
| ax = plt.subplot(111) | |
| legend = [] | |
| xmax_list = [] | |
| # Linestyles | |
| linestyles = ['-', '--', '-.', ':'] | |
| # Iterate and plot | |
| for i, trajectory in enumerate(trajectory_list): | |
| plt.plot(trajectory["x"], trajectory["y"], | |
| color = trajectory["color"], | |
| linestyle=linestyles[i%len(linestyles)]) | |
| legend.append(trajectory["legend"]) | |
| xmax_list.append(np.max(trajectory["x"])) | |
| plt.xlabel('x - horizonal distance in meters', fontsize=20) | |
| plt.ylabel('y - vertical distance in meters', fontsize=20) | |
| # Adding the pig and birds, if needed | |
| if len(pig_position) > 0: | |
| plot_emoji("apps/images/pig.png", ax, pig_position[0], pig_position[1]) | |
| xmax_list.append(pig_position[0]) | |
| for trajectory in trajectory_list: | |
| plot_emoji("apps/images/bird.png", ax, trajectory["x"][-1], trajectory["y"][-1]) | |
| # legend, only if any trajectory | |
| plt.legend(legend, fontsize=20, loc='upper center') | |
| # xmax_list and ymax calculations | |
| if len(xmax_list) > 0: | |
| xmax = max(xmax_list) | |
| plt.xlim(-xmax*0.05, xmax*1.05) | |
| plt.ylim(-xmax*0.05, xmax*1.05) # Same limits for x and y | |
| return fig | |
| def check_solution(pig_position, trajectory_list): | |
| """ | |
| Checks if the pig is in the trajectory of the projectile. | |
| """ | |
| x_tol, y_tol = 1.0, 1.0 | |
| # Iterate and check | |
| for trajectory in trajectory_list: | |
| x = trajectory["x"][-1] | |
| y = trajectory["y"][-1] | |
| if abs(pig_position[0] - x) < x_tol and abs(pig_position[1] - y) < y_tol: | |
| return True | |
| return False |