斜抛运动
绘制物体以一定角度抛出后的抛物线轨迹,展示水平与垂直方向的分运动。
import numpy as np import matplotlib.pyplot as plt from matplotlib.animation import FuncAnimation # 设置中文字体 plt.rcParams["font.family"] = ["SimHei"] plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题 class ProjectileMotion: def __init__(self, v0=10, angle=45, g=9.8): """ 初始化斜抛运动参数 参数: v0: 初始速度 (m/s) angle: 抛射角度 (度) g: 重力加速度 (m/s^2) """ self.v0 = v0 self.angle = angle self.g = g self.angle_rad = np.radians(angle) # 计算分速度 self.v0x = v0 * np.cos(self.angle_rad) self.v0y = v0 * np.sin(self.angle_rad) # 计算飞行时间、最大高度和射程 self.time_of_flight = 2 * self.v0y / g self.max_height = (self.v0y ** 2) / (2 * g) self.range = self.v0x * self.time_of_flight # 创建图形和轴 self.fig = plt.figure(figsize=(15, 5)) self.ax1 = self.fig.add_subplot(131) # 轨迹图 self.ax2 = self.fig.add_subplot(132) # 水平分运动 self.ax3 = self.fig.add_subplot(133) # 垂直分运动 # 设置轴属性 self.setup_axes() # 初始化线条和点 self.trajectory_line, = self.ax1.plot([], [], 'b-', lw=2) self.point, = self.ax1.plot([], [], 'ro', markersize=8) self.x_line, = self.ax2.plot([], [], 'g-', lw=2) self.x_point, = self.ax2.plot([], [], 'ro', markersize=8) self.y_line, = self.ax3.plot([], [], 'm-', lw=2) self.y_point, = self.ax3.plot([], [], 'ro', markersize=8) # 初始化时间文本 self.time_text = self.ax1.text(0.02, 0.95, '', transform=self.ax1.transAxes) # 生成时间点 self.t = np.linspace(0, self.time_of_flight, 100) # 计算轨迹 self.x = self.v0x * self.t self.y = self.v0y * self.t - 0.5 * self.g * self.t ** 2 def setup_axes(self): """设置图形的轴属性""" # 轨迹图 self.ax1.set_xlim(0, self.range * 1.1) self.ax1.set_ylim(0, self.max_height * 1.1) self.ax1.set_xlabel('水平距离 (m)') self.ax1.set_ylabel('垂直距离 (m)') self.ax1.set_title('斜抛运动轨迹') self.ax1.grid(True) # 水平分运动图 self.ax2.set_xlim(0, self.time_of_flight) self.ax2.set_ylim(0, self.range * 1.1) self.ax2.set_xlabel('时间 (s)') self.ax2.set_ylabel('水平距离 (m)') self.ax2.set_title('水平分运动') self.ax2.grid(True) # 垂直分运动图 self.ax3.set_xlim(0, self.time_of_flight) self.ax3.set_ylim(0, self.max_height * 1.1) self.ax3.set_xlabel('时间 (s)') self.ax3.set_ylabel('垂直距离 (m)') self.ax3.set_title('垂直分运动') self.ax3.grid(True) # 调整布局 plt.tight_layout() def init(self): """初始化动画""" self.trajectory_line.set_data([], []) self.point.set_data([], []) self.x_line.set_data([], []) self.x_point.set_data([], []) self.y_line.set_data([], []) self.y_point.set_data([], []) self.time_text.set_text('') return (self.trajectory_line, self.point, self.x_line, self.x_point, self.y_line, self.y_point, self.time_text) def update(self, frame): """更新动画帧""" # 更新轨迹 self.trajectory_line.set_data(self.x[:frame], self.y[:frame]) self.point.set_data([self.x[frame]], [self.y[frame]]) # 更新水平分运动 self.x_line.set_data(self.t[:frame], self.x[:frame]) self.x_point.set_data([self.t[frame]], [self.x[frame]]) # 更新垂直分运动 self.y_line.set_data(self.t[:frame], self.y[:frame]) self.y_point.set_data([self.t[frame]], [self.y[frame]]) # 更新时间文本 self.time_text.set_text(f'时间: {self.t[frame]:.2f}s') return (self.trajectory_line, self.point, self.x_line, self.x_point, self.y_line, self.y_point, self.time_text) def animate(self): """运行动画""" anim = FuncAnimation( self.fig, self.update, frames=len(self.t), init_func=self.init, blit=True, interval=50 ) plt.show() return anim # 运行模拟 if __name__ == "__main__": # 创建斜抛运动实例 (初始速度10m/s,抛射角度45度,重力加速度9.8m/s^2) pm = ProjectileMotion(v0=15, angle=60) # 显示动画 pm.animate()