ZhangZhihui's Blog  

请按如下要求在平面直角坐标系中绘制一个想象中的有质量没有体积的弹性小球自由落体运动的轨迹图:

1. X轴为时间t,单位为秒,初始值为0,范围为0到100

2. Y轴为小球距地面的高度,单位为米,初始值为100,范围为0到100

3. 自由落体的加速度为地球的重力加速度

4. 小球与地面碰撞不消耗能量 

 
 

🐍 物理轨迹绘制代码

import numpy as np
import matplotlib.pyplot as plt

# ==================== 1. 物理参数设置 ====================
h0 = 100.0       # 初始高度 (米)
g = 9.81         # 地球重力加速度 (米/秒^2)
t_max = 60.0    # 模拟总时间 (秒)
dt = 0.01        # 时间步长 (秒)

# 计算单次下落/弹起所需的时间
t_bounce = np.sqrt(2 * h0 / g)

# ==================== 2. 计算轨迹数据 ====================
t_array = np.arange(0, t_max + dt, dt)
y_array = np.zeros_like(t_array)

for i, t in enumerate(t_array):
    t_in_cycle = t % (2 * t_bounce)
    if t_in_cycle <= t_bounce:
        y = h0 - 0.5 * g * t_in_cycle**2
    else:
        t_rising = t_in_cycle - t_bounce
        v_max = g * t_bounce
        y = v_max * t_rising - 0.5 * g * t_rising**2
        
    y_array[i] = max(y, 0.0)

# ==================== 3. 计算关键时间节点 ====================
# A. 计算所有碰撞点的时间 t (落地点)
bounce_times = []
current_bounce = t_bounce
while current_bounce <= t_max:
    bounce_times.append(current_bounce)
    current_bounce += 2 * t_bounce

# B. 计算所有最高点的时间 t (顶点)
# 第一个最高点在 0 秒,之后每隔 2 * t_bounce 达到一次最高点
peak_times = [0.0]
current_peak = 2 * t_bounce
while current_peak <= t_max:
    peak_times.append(current_peak)
    current_peak += 2 * t_bounce

# ==================== 4. 绘制平面直角坐标系 ====================
fig, ax = plt.subplots(figsize=(15, 7))

# 绘制小球运动轨迹曲线
ax.plot(t_array, y_array, label='Ball Trajectory', color='#1f77b4', linewidth=2)

# 绘制碰撞点的小红点
for t_b in bounce_times:
    ax.plot(t_b, 0, 'ro', markersize=5, zorder=3)

# ==================== 5. 标注顶点时间(显示在顶点上方) ====================
for t_p in peak_times:
    # 在 Y=100 的轨迹顶点处绘制一个小绿点
    ax.plot(t_p, h0, 'go', markersize=4, zorder=3)
    
    # 在顶点上方(Y = 101.5)标注时间
    ax.text(t_p, h0 + 1.5, f'{t_p:.2f}s',
            ha='center',          # 水平居中
            va='bottom',          # 垂直靠下对齐(文字在坐标点上方延伸)
            fontsize=9,
            color='green',        # 绿色字体以示区分
            fontweight='bold',
            bbox=dict(facecolor='white', alpha=0.7, edgecolor='none', pad=0.5))

# ==================== 6. 标注碰撞时间(注入 X 轴下方) ====================
default_ticks = list(np.arange(0, t_max + 1, 20))
all_ticks = default_ticks + bounce_times
all_ticks.sort()

labels = []
for tick in all_ticks:
    if tick in bounce_times:
        labels.append(f'{tick:.3f}s')
    else:
        labels.append(f'{int(tick)}')

ax.set_xticks(all_ticks)
ax.set_xticklabels(labels)

# 动态微调 X 轴标签颜色
for label, tick in zip(ax.get_xticklabels(), all_ticks):
    if tick in bounce_times:
        label.set_color('red')
        label.set_weight('bold')
        label.set_fontsize(9)
    else:
        label.set_color('black')
        label.set_fontsize(10)

# ==================== 7. 限制坐标轴范围(确保 X 轴不动) ====================
ax.set_xlim(0, t_max)
ax.set_ylim(0, 110) # 稍微加高到 110,给顶部的绿色文字留出充足的空间

ax.set_xlabel('Time t (seconds)', fontsize=12, labelpad=10)
ax.set_ylabel('Height Y (meters)', fontsize=12)
#ax.set_title('Elastic Ball Trajectory with Peak (Green) and Collision (Red) Labels', fontsize=14)

ax.grid(True, linestyle='--', alpha=0.4)
ax.legend(loc='upper right')

plt.show()

 

1

 

Figure_1

 

posted on 2026-06-06 13:40  ZhangZhihuiAAA  阅读(4)  评论(0)    收藏  举报