绘制物体以一定角度抛出后的抛物线轨迹

斜抛运动
绘制物体以一定角度抛出后的抛物线轨迹,展示水平与垂直方向的分运动。

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()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值