You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Matplotlib动画绘图中为运动点添加环绕圆形?

解决Matplotlib动画中为运动点添加环绕圆形的问题

你的代码存在两个关键问题:

  • 每次执行animate函数都新建圆形patch并添加到轴上,导致旧的圆形不会被清除,动画会越来越卡且画面混乱
  • plt.Circle((xdata, ydata), 2)中的xdata和ydata是数组,而Circle构造函数只接受单个坐标对,不能直接传入数组

正确的做法是提前初始化所有需要的圆形patch,在动画帧更新时只修改它们的位置,而不是每次创建新的patch。

修正后的最小可复现示例

import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation, PillowWriter

# 模拟变量
sim_time = 4       # 总模拟时间
dt = 0.5            # 时间步长
t = np.arange(0, sim_time, dt)
T = len(t)          # 帧数

fig, ax = plt.subplots()
xlimit, ylimit = [-1, 26], [-1, 16]
ax.set_xlim(xlimit)
ax.set_ylim(ylimit)

# 初始化点和圆形
num_points = 3
points, = ax.plot([], [], 'o')
# 提前创建所有圆形patch,初始位置设为不可见
circles = [plt.Circle((0, 0), 2, color='r', fill=False, visible=False) for _ in range(num_points)]
for circle in circles:
    ax.add_patch(circle)

def init():
    points.set_data([], [])
    for circle in circles:
        circle.set_visible(False)
    return points, *circles

def animate(frame):
    xdata = np.random.rand(num_points)*10
    ydata = np.random.rand(num_points)*10
    
    # 更新点的位置
    points.set_data(xdata, ydata)
    
    # 更新每个圆形的位置并设置可见
    for x, y, circle in zip(xdata, ydata, circles):
        circle.set_center((x, y))
        circle.set_visible(True)
    
    return points, *circles

anim = FuncAnimation(fig, animate,
                     init_func=init,
                     frames=T,
                     interval=20,
                     blit=True)

writergif = PillowWriter(fps=24)
anim.save('pedestrians.gif', writer=writergif)

原代码的修正版本

针对你提供的原始代码,修改逻辑一致:提前初始化对应数量的圆形patch,在animate中更新位置即可。

import matplotlib.pyplot as plt
from launcher import sol, T, dt
from matplotlib.animation import FuncAnimation, PillowWriter
from create import p, N, walls_x, walls_y

# 转换sol.y为可绘图数组
def sol_convert(sol):
    x = sol.y[0::4,:]                   # 每个点有4个值(x,y,vx,vy)
    y = sol.y[1::4,:]
    vx = sol.y[2::4,:]
    vy = sol.y[3::4,:]
    return x, y, vx ,vy

r_x, r_y, v_x, v_y = sol_convert(sol)

fig, ax = plt.subplots()
xlimit, ylimit = [-1,26], [-1,16]
ax.set_xlim(xlimit)
ax.set_ylim(ylimit)

# 绘制墙壁
for i in range(len(walls_x)):
    plt.plot(walls_x[i], walls_y[i], 'k', linestyle="solid")

# 初始化点和圆形
ped, = ax.plot([], [], 'o')
# 根据点的数量N创建圆形patch
circles = [plt.Circle((0, 0), 2, color='r', fill=False, visible=False) for _ in range(N)]
for circle in circles:
    ax.add_patch(circle)

def init():
    ped.set_data([], [])
    for circle in circles:
        circle.set_visible(False)
    return ped, *circles

def animate(frame):
    xdata = r_x[:, frame]
    ydata = r_y[:, frame]
    
    # 更新点的位置
    ped.set_data(xdata, ydata)
    
    # 更新每个圆形的位置
    for x, y, circle in zip(xdata, ydata, circles):
        circle.set_center((x, y))
        circle.set_visible(True)
    
    return ped, *circles

anim = FuncAnimation(fig, animate,
                     init_func=init,
                     frames=T,
                     interval=20,
                     blit=True)

writergif = PillowWriter(fps=24)
anim.save('pedestrians.gif', writer=writergif)

关键修改说明

  1. 提前初始化圆形patch:在动画开始前创建所有需要的圆形,避免重复创建导致的性能问题和画面混乱
  2. 在animate中更新位置:使用set_center()方法修改圆形的中心坐标,而不是新建patch
  3. blit模式支持:返回值要包含所有需要更新的元素(点+所有圆形),确保blit功能正常工作
  4. 初始可见性设置:在init函数中设置圆形不可见,避免初始帧出现多余图形

内容的提问来源于stack exchange,提问作者ischokking

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 16:16:06