gpt4 book ai didi

python - 动画圆圈内的线条 - matplotlib

转载 作者:行者123 更新时间:2023-12-04 08:47:45 30 4
gpt4 key购买 nike

我正在尝试使用 matplotlib 为线条设置动画。我可以为圆和一些散点设置动画,但我正在尝试使用不断变化的角度添加线条。使用下面,我确定 X2 的方向, Y2在每个时间点确定方向。然后我想绘制显示这个方向的线。他们基本上将圆圈分成 4 个相等的部分。我在下面分别插入了每一帧。我输入了一个指南针作为引用。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation

fig, ax = plt.subplots(figsize = (8,8))
ax.set_xlim(-20,20)
ax.set_ylim(-20,20)
ax.grid(False)

df = pd.DataFrame({
'Time' : [1,1,1,1,2,2,2,2,3,3,3,3],
'id' : ['A','B','C','D','A','B','C','D','A','B','C','D'],
'X1' : [1,8,0,-5,1,1,-6,0,1,8,0,-5],
'Y1' : [-5,2,-5,2,5,-5,-2,2,-5,2,-5,2],
'X2' : [0,0,0,0,-1,-1,-1,-1,0,0,0,0],
'Y2' : [0,0,0,0,1,1,1,1,1,1,1,1],
'Rotation' : [0,0,0,0,-0.78,-0.78,-0.78,-0.78,1.57,1.57,1.57,1.57],
'Angle' : [0,0,0,0,-45,-45,-45,-45,90,90,90,90],
})

points_x = np.array(df.groupby(['Time'])['X1'].apply(list))
points_y = np.array(df.groupby(['Time'])['Y1'].apply(list))

# scatter points
points = ax.scatter(points_x[2], points_y[2], c = 'blue', marker = '*')

moving_x = np.array(df.groupby(['Time'])['X2'].apply(list))
moving_y = np.array(df.groupby(['Time'])['Y2'].apply(list))

# scatter moving
moving_point = ax.scatter(moving_x[2], moving_y[2], c = 'black', marker = 'x')

# Array of immediate congestion radius coordinates
radius = df.drop_duplicates(subset = ['Time','X2', 'Y2'])[['X2', 'Y2']].values

# Plot immediate congestion radius
circle = plt.Circle(radius[2], 10, color = 'black', fill = False)

# Add radius to plot
ax.add_patch(circle)

t = df['Angle'][0]
line1, = ax.plot([0, 0],[0,t], color = 'b', linewidth = 1)

def animate(i) :

circle.center = (radius[i,0], radius[i,1])

line1.set_data([i, i],[0,t])

points.set_offsets(np.c_[points_x[0+i], points_y[0+i]])
moving_point.set_offsets(np.c_[moving_x[0+i], moving_y[0+i]])


ani = animation.FuncAnimation(fig, animate, np.arange(0,2), blit = False)
如果我单独拆分帧,我希望它们显示以下内容:
第 1 帧:
enter image description here
第 2 帧:
enter image description here
第 3 帧:
enter image description here
编辑2:
enter image description here

最佳答案

为了处理您帖子中玩具数据集以外的数据集,我将创建动画的所有内容都放入函数 animate 中。 .由于我不熟悉您正在使用的数据集(例如我不知道 Rotation 做什么),下面的脚本是我能做的最好的。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from matplotlib import animation

df = pd.DataFrame({
'Time' : [1,1,1,1,2,2,2,2,3,3,3,3],
'id' : ['A','B','C','D','A','B','C','D','A','B','C','D'],
'X1' : [1,8,0,-5,1,1,-6,0,1,8,0,-5],
'Y1' : [-5,2,-5,2,5,-5,-2,2,-5,2,-5,2],
'X2' : [0,0,0,0,-1,-1,-1,-1,0,0,0,0],
'Y2' : [0,0,0,0,1,1,1,1,1,1,1,1],
'Rotation' : [0,0,0,0,-0.78,-0.78,-0.78,-0.78,1.57,1.57,1.57,1.57],
'Angle' : [0,0,0,0,-45,-45,-45,-45,90,90,90,90],
})

# the scattered points in the compass
points_x = np.array(df.groupby(['Time'])['X1'].apply(list))
points_y = np.array(df.groupby(['Time'])['Y1'].apply(list))

# the center of the compass
moving_x = np.array(df.groupby(['Time'])['X2'].apply(list))
moving_y = np.array(df.groupby(['Time'])['Y2'].apply(list))

radius = df.drop_duplicates(subset = ['Time','X2', 'Y2'])[['X2', 'Y2']].values
angles = df['Angle'].unique()

rot_mat = lambda theta:np.array([
[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]
])

fig, ax = plt.subplots(figsize = (8,8))

def animate(i) :

ax.clear()
ax.set_xlim(-20,20)
ax.set_ylim(-20,20)

points = ax.scatter(points_x[i]+radius[i][0], points_y[i]+radius[i][1], c = 'blue', marker = '*')
moving_point = ax.scatter(moving_x[i],moving_y[i], c = 'black', marker = 'x')

circle = plt.Circle(radius[i], 10, color = 'black', fill = False)
ax.add_patch(circle)

ends_one = np.array([[-7.07106781,7.07106781],[7.07106781,-7.07106781]])
ends_two = np.array([[-7.07106781,-7.07106781],[7.07106781,7.07106781]])
ends_one = ends_one @ rot_mat(angles[i]) + radius[i]
ends_two = ends_two @ rot_mat(angles[i]) + radius[i]
line1, = ax.plot([], [], ls='--', color='black',lw=1, zorder=10,animated=True)
line2, = ax.plot([], [], ls='--', color='black',lw=1, zorder=10,animated=True)
line1.set_data([ends_one[0][0],ends_one[1][0]],[ends_one[0][1],ends_one[1][1]])
line2.set_data([ends_two[0][0],ends_two[1][0]],[ends_two[0][1],ends_two[1][1]])

tags = ['N','E','S','W']
tag_pos = np.array([[0,8.5],[8.5,0],[0,-8.5],[-8.5,0]])
tag_pos = tag_pos @ rot_mat(angles[i])
for tag,pos in zip(tags,tag_pos):
ax.annotate(tag,xy=pos+radius[i], xycoords='data',
fontsize=10,horizontalalignment='right', verticalalignment='bottom')

ani = animation.FuncAnimation(fig, animate, np.arange(0,3), blit = False)
ani.save('test.gif', writer='pillow', fps=3)
如您所见,坐标可以迭代地传递给函数 animate生成指南针的框架。运行这个脚本后,你会得到一个 gif文件 test.gif , 可以预览
test.gif

删除过去帧的文本
有两种方法可以做到这一点
1.如果你正在使用一个函数来创建动画
ax.clear()在函数的开头,例如
import matplotlib.pyplot as plt
from matplotlib import animation

rot_mat = lambda theta:np.array([
[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]
])

fig, ax = plt.subplots(figsize = (8,8))

centers = np.linspace(1,36,36).reshape(18,2)*0.2
angles = np.linspace(45,90,18)

def animate(i) :

ax.clear()
ax.set_xlim(-20,20)
ax.set_ylim(-20,20)

circle = plt.Circle(centers[i], 10, color = 'black', fill = True)
circle.set_facecolor('violet')
ax.add_patch(circle)

tags = ['N','E','S','W']
tag_pos = np.array([[0,8.5],[8.5,0],[0,-8.5],[-8.5,0]])
tag_pos = tag_pos @ rot_mat(angles[i])
for tag,pos in zip(tags,tag_pos):
ax.annotate(tag,xy=pos+centers[i], xycoords='data',
fontsize=10,horizontalalignment='right', verticalalignment='bottom')

ani = animation.FuncAnimation(fig, animate, np.arange(0,18), blit = False)
ani.save('test.gif', writer='pillow', fps=18)
这将创建一个 gif像这样
use a function to create
2. 如果您没有使用函数创建动画
您需要手动删除文本,例如
import matplotlib.pyplot as plt
from matplotlib import animation

rot_mat = lambda theta:np.array([
[np.cos(np.deg2rad(theta)),-np.sin(np.deg2rad(theta))],
[np.sin(np.deg2rad(theta)),np.cos(np.deg2rad(theta))]
])

centers = np.linspace(1,36,36).reshape(18,2)*0.2
angles = np.linspace(45,90,18)

fig, ax = plt.subplots(figsize = (8,8))
ax.set_xlim(-20,20)
ax.set_ylim(-20,20)

circle = plt.Circle(centers[0], 10, color = 'black', fill = True)
circle.set_facecolor('violet')
ax.add_patch(circle)

annotates = []
tags = ['N','E','S','W']
tag_pos = np.array([[0,8.5],[8.5,0],[0,-8.5],[-8.5,0]])
tag_pos = tag_pos @ rot_mat(angles[0])
for tag,pos in zip(tags,tag_pos):
ann = ax.annotate(tag,xy=pos+centers[0], xycoords='data',
fontsize=10,horizontalalignment='right', verticalalignment='bottom')
annotates.append(ann)

for i in range(18):

circle.center = centers[i]
# remove the previous text
for item in annotates: item.remove()
annotates = []

tag_pos = tag_pos @ rot_mat(angles[i])
for tag,pos in zip(tags,tag_pos):
ann = ax.annotate(tag,xy=pos+centers[i], xycoords='data',
fontsize=10,horizontalalignment='right', verticalalignment='bottom')
annotates.append(ann)

ani = animation.FuncAnimation(fig, animate, np.arange(0,18), blit = False)
ani.save('test.gif', writer='pillow', fps=18)
如您所见,使用这行代码 for item in annotates: item.remove() ,删除前一帧的文本。因此,通过运行此脚本,您还将获得
the new one

关于python - 动画圆圈内的线条 - matplotlib,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64223697/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com