如何在NumPy/Matplotlib中实现多参数函数绘图与交互控件?
没问题!我帮你把这三个需求的实现代码整理好了,每个部分都有详细说明,直接就能跑起来~
1. 单画布绘制4组参数的轨迹(不同颜色)
咱们先定义一个计算抛体运动轨迹的函数(忽略空气阻力,只考虑重力),然后准备4组不同的初速度v0和发射角度theta,在同一个画布上用不同颜色绘制每条轨迹,再加上图例方便区分:
import numpy as np import matplotlib.pyplot as plt %matplotlib inline # 定义重力加速度 g = 9.8 def calculate_trajectory(v0, theta): # 角度转弧度 theta_rad = np.deg2rad(theta) # 计算运动总时间(直到落地) t_total = 2 * v0 * np.sin(theta_rad) / g # 生成时间点 t = np.linspace(0, t_total, 100) # 计算x和y坐标 x = v0 * np.cos(theta_rad) * t y = v0 * np.sin(theta_rad) * t - 0.5 * g * t**2 return x, y # 4组不同的参数:(v0, theta) params = [ (10, 30), (15, 45), (20, 60), (25, 15) ] # 对应4种颜色 colors = ['red', 'blue', 'green', 'orange'] # 创建画布 plt.figure(figsize=(8, 6)) # 循环绘制每组轨迹 for (v0, theta), color in zip(params, colors): x, y = calculate_trajectory(v0, theta) plt.plot(x, y, color=color, label=f'v0={v0}m/s, theta={theta}°') # 添加图例和标签 plt.xlabel('水平距离 (m)') plt.ylabel('高度 (m)') plt.title('不同初速度和角度的抛体运动轨迹(单画布)') plt.legend() plt.grid(True) plt.show()
2. 4个画布方形排列绘制各自轨迹
这次我们用plt.subplots(2,2)创建2×2的子图网格,把每组参数的轨迹分别画在对应的子图里,每个子图都标注自己的参数组合,看起来更清晰:
import numpy as np import matplotlib.pyplot as plt %matplotlib inline g = 9.8 def calculate_trajectory(v0, theta): theta_rad = np.deg2rad(theta) t_total = 2 * v0 * np.sin(theta_rad) / g t = np.linspace(0, t_total, 100) x = v0 * np.cos(theta_rad) * t y = v0 * np.sin(theta_rad) * t - 0.5 * g * t**2 return x, y params = [ (10, 30), (15, 45), (20, 60), (25, 15) ] # 创建2x2的子图网格 fig, axes = plt.subplots(2, 2, figsize=(10, 8)) axes = axes.flatten() # 把二维数组转成一维,方便循环 for ax, (v0, theta) in zip(axes, params): x, y = calculate_trajectory(v0, theta) ax.plot(x, y, color='purple') ax.set_title(f'v0={v0}m/s, theta={theta}°') ax.set_xlabel('水平距离 (m)') ax.set_ylabel('高度 (m)') ax.grid(True) # 调整子图间距,避免标题和标签重叠 plt.tight_layout() plt.show()
3. 鼠标交互调节v0和theta的控件
这里用到matplotlib.widgets.Slider创建两个滑块,分别控制初速度和发射角度,拖动滑块就能实时更新轨迹。注意要把绘图模式改成%matplotlib notebook(如果是Jupyter环境),这样才能支持交互:
import numpy as np import matplotlib.pyplot as plt from matplotlib.widgets import Slider %matplotlib notebook # 交互模式,inline无法交互 g = 9.8 def calculate_trajectory(v0, theta): theta_rad = np.deg2rad(theta) # 处理角度为0的情况,避免除零错误 t_total = 2 * v0 * np.sin(theta_rad) / g if np.sin(theta_rad) != 0 else 0 t = np.linspace(0, t_total, 100) x = v0 * np.cos(theta_rad) * t y = v0 * np.sin(theta_rad) * t - 0.5 * g * t**2 return x, y # 创建画布和轨迹轴,留出滑块位置 fig, ax = plt.subplots(figsize=(8, 6)) plt.subplots_adjust(left=0.1, bottom=0.25) # 初始参数 v0_init = 15 theta_init = 45 x, y = calculate_trajectory(v0_init, theta_init) line, = ax.plot(x, y, color='darkred') # 设置轴标签和标题 ax.set_xlabel('水平距离 (m)') ax.set_ylabel('高度 (m)') ax.set_title('交互式抛体运动轨迹调节') ax.grid(True) ax.set_xlim(0, 50) # 固定x轴范围,避免滑块拖动时轴频繁变化 ax.set_ylim(0, 20) # 创建滑块的位置和样式 ax_v0 = plt.axes([0.1, 0.1, 0.8, 0.03]) ax_theta = plt.axes([0.1, 0.05, 0.8, 0.03]) # 创建滑块:v0范围5-30m/s,theta范围0-90° slider_v0 = Slider(ax=ax_v0, label='初速度 v0 (m/s)', valmin=5, valmax=30, valinit=v0_init) slider_theta = Slider(ax=ax_theta, label='发射角度 theta (°)', valmin=0, valmax=90, valinit=theta_init) # 定义更新函数,滑块拖动时实时更新轨迹 def update(val): v0 = slider_v0.val theta = slider_theta.val x_new, y_new = calculate_trajectory(v0, theta) line.set_data(x_new, y_new) fig.canvas.draw_idle() # 绑定滑块的更新事件 slider_v0.on_changed(update) slider_theta.on_changed(update) plt.show()
内容的提问来源于stack exchange,提问作者ZelelB
相关产品推荐
相关产品推荐

