使用 matplotlib.animation.FuncAnimate 的具有周期性边界的多车道高速公路动画
Animation of a multiple-lane highway with periodic boundary using matplotlib.animation.FuncAnimate
下面是一个完全有效的代码,它为具有周期性边界的单车道道路设置动画。现在我想为两条甚至更多条车道设置动画。我有一个工作代码,其中位置向量现在是一个矩阵,每一列代表一条车道。由此,我可以创建另一个 theta 矢量,我希望它显示在动画中第一个矢量之外(通过将半径设置得大一点)。我试图将矩阵(theta 和 r)放在 ax.scatter(theta, r, c=color) 中,但这不起作用。有没有人对如何解决这个问题有建议?除了 matplotlib 的动画,我还可以使用其他东西,但由于它可以很好地解决单车道问题,所以对我来说是最简单的。
总结一下。如何同时为两个或多个矢量设置动画?例如,如果我有 r1、r2 和 theta1、theta2,并且每次都想 'plot' 它们,而不是像代码中那样只有 r 和 theta。
非常感谢您的帮助。
import numpy as np
from numpy.random import random as rnd
import matplotlib.pyplot as plt
from matplotlib import animation
roadlength = 50
numcars = 10
numframes = 1000 #Time
v_max = 5
p = 0.5
positions = np.zeros(numcars)
velocities = np.zeros(numcars)
theta = np.zeros(numcars)
color = np.linspace(0,numcars-1,numcars)
#Initiate r so roadlength = circumference of one lap
r = []
for i in range(numcars):
r.append(roadlength/(2*np.pi))
#Initiate positions so the cars are spread out over the road
for i in range(1,numcars):
positions[i] = positions[i-1] + (roadlength/numcars)
#Create figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.axis('off')
#Update positions, animate function runs framenr times
def animate(framenr):
positions_tmp = np.array(positions, copy=True)
#Update position and velocity for each car
for i in range(numcars):
#Increase velocity if below max
if velocities[i] < v_max:
velocities[i] += 1
#Decrease velocity if car in front is close
d = positions_tmp[(i+1)%numcars] - positions_tmp[i]
if d <= 0:
d += roadlength
if velocities[i] >= d:
velocities[i] = d-1
#Decrease velocity randomly
if velocities[i] > 0:
if rnd() < p:
velocities[i] -= 1
positions[i] = positions_tmp[i] + velocities[i]
theta[i] = positions[i]*2*np.pi/roadlength
return ax.scatter(theta, r, c=color),
# Call the animator, blit=True means only re-draw parts that have changed
anim = animation.FuncAnimation(fig, animate, frames=numframes, interval=100, blit=True, repeat=False)
plt.show()
FuncAnimation()
期望 animate()
函数能够 return 一组在每一帧都更新的艺术家。如果您需要为多个 "plots"(或艺术家,或其他)制作动画,只需存储每个绘图的结果,以及 return 所有变量的列表
此外,您的代码在 animate
函数中重复调用 ax.scatter()
,这导致每次都绘制新点,并且绘制框架所需的时间会随着时间的推移而增加。我不知道那是否真的是你真正想做的。动画的最佳做法是在动画开始之前创建艺术家,然后在 animate()
函数中更新他们的属性,而不是创建新的。
import numpy as np
from numpy.random import random as rnd
import matplotlib.pyplot as plt
from matplotlib import animation
roadlength = 50
numcars = 10
numframes = 1000 #Time
v_max = 5
p = 0.5
positions = np.zeros(numcars)
velocities = np.zeros(numcars)
theta = np.zeros(numcars)
color = np.linspace(0,numcars-1,numcars)
#Initiate r so roadlength = circumference of one lap
r = roadlength/(2*np.pi)
#Initiate positions so the cars are spread out over the road
for i in range(1,numcars):
positions[i] = positions[i-1] + (roadlength/numcars)
#Create figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.axis('off')
plot1 = ax.scatter(theta, [r]*numcars, c=color)
plot2 = ax.scatter(theta, [r+1]*numcars, c=color)
ax.set_ylim(0,r+2)
#Update positions, animate function runs framenr times
def animate(framenr):
positions_tmp = np.array(positions, copy=True)
#Update position and velocity for each car
for i in range(numcars):
#Increase velocity if below max
if velocities[i] < v_max:
velocities[i] += 1
#Decrease velocity if car in front is close
d = positions_tmp[(i+1)%numcars] - positions_tmp[i]
if d <= 0:
d += roadlength
if velocities[i] >= d:
velocities[i] = d-1
#Decrease velocity randomly
if velocities[i] > 0:
if rnd() < p:
velocities[i] -= 1
positions[i] = positions_tmp[i] + velocities[i]
theta[i] = positions[i]*2*np.pi/roadlength
plot1.set_offsets(np.c_[theta, [r]*numcars])
plot2.set_offsets(np.c_[theta, [r+1]*numcars])
return [plot1, plot2]
# Call the animator, blit=True means only re-draw parts that have changed
anim = animation.FuncAnimation(fig, animate, frames=numframes, interval=100, blit=True, repeat=True)
plt.show()
下面是一个完全有效的代码,它为具有周期性边界的单车道道路设置动画。现在我想为两条甚至更多条车道设置动画。我有一个工作代码,其中位置向量现在是一个矩阵,每一列代表一条车道。由此,我可以创建另一个 theta 矢量,我希望它显示在动画中第一个矢量之外(通过将半径设置得大一点)。我试图将矩阵(theta 和 r)放在 ax.scatter(theta, r, c=color) 中,但这不起作用。有没有人对如何解决这个问题有建议?除了 matplotlib 的动画,我还可以使用其他东西,但由于它可以很好地解决单车道问题,所以对我来说是最简单的。
总结一下。如何同时为两个或多个矢量设置动画?例如,如果我有 r1、r2 和 theta1、theta2,并且每次都想 'plot' 它们,而不是像代码中那样只有 r 和 theta。
非常感谢您的帮助。
import numpy as np
from numpy.random import random as rnd
import matplotlib.pyplot as plt
from matplotlib import animation
roadlength = 50
numcars = 10
numframes = 1000 #Time
v_max = 5
p = 0.5
positions = np.zeros(numcars)
velocities = np.zeros(numcars)
theta = np.zeros(numcars)
color = np.linspace(0,numcars-1,numcars)
#Initiate r so roadlength = circumference of one lap
r = []
for i in range(numcars):
r.append(roadlength/(2*np.pi))
#Initiate positions so the cars are spread out over the road
for i in range(1,numcars):
positions[i] = positions[i-1] + (roadlength/numcars)
#Create figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.axis('off')
#Update positions, animate function runs framenr times
def animate(framenr):
positions_tmp = np.array(positions, copy=True)
#Update position and velocity for each car
for i in range(numcars):
#Increase velocity if below max
if velocities[i] < v_max:
velocities[i] += 1
#Decrease velocity if car in front is close
d = positions_tmp[(i+1)%numcars] - positions_tmp[i]
if d <= 0:
d += roadlength
if velocities[i] >= d:
velocities[i] = d-1
#Decrease velocity randomly
if velocities[i] > 0:
if rnd() < p:
velocities[i] -= 1
positions[i] = positions_tmp[i] + velocities[i]
theta[i] = positions[i]*2*np.pi/roadlength
return ax.scatter(theta, r, c=color),
# Call the animator, blit=True means only re-draw parts that have changed
anim = animation.FuncAnimation(fig, animate, frames=numframes, interval=100, blit=True, repeat=False)
plt.show()
FuncAnimation()
期望 animate()
函数能够 return 一组在每一帧都更新的艺术家。如果您需要为多个 "plots"(或艺术家,或其他)制作动画,只需存储每个绘图的结果,以及 return 所有变量的列表
此外,您的代码在 animate
函数中重复调用 ax.scatter()
,这导致每次都绘制新点,并且绘制框架所需的时间会随着时间的推移而增加。我不知道那是否真的是你真正想做的。动画的最佳做法是在动画开始之前创建艺术家,然后在 animate()
函数中更新他们的属性,而不是创建新的。
import numpy as np
from numpy.random import random as rnd
import matplotlib.pyplot as plt
from matplotlib import animation
roadlength = 50
numcars = 10
numframes = 1000 #Time
v_max = 5
p = 0.5
positions = np.zeros(numcars)
velocities = np.zeros(numcars)
theta = np.zeros(numcars)
color = np.linspace(0,numcars-1,numcars)
#Initiate r so roadlength = circumference of one lap
r = roadlength/(2*np.pi)
#Initiate positions so the cars are spread out over the road
for i in range(1,numcars):
positions[i] = positions[i-1] + (roadlength/numcars)
#Create figure
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')
ax.axis('off')
plot1 = ax.scatter(theta, [r]*numcars, c=color)
plot2 = ax.scatter(theta, [r+1]*numcars, c=color)
ax.set_ylim(0,r+2)
#Update positions, animate function runs framenr times
def animate(framenr):
positions_tmp = np.array(positions, copy=True)
#Update position and velocity for each car
for i in range(numcars):
#Increase velocity if below max
if velocities[i] < v_max:
velocities[i] += 1
#Decrease velocity if car in front is close
d = positions_tmp[(i+1)%numcars] - positions_tmp[i]
if d <= 0:
d += roadlength
if velocities[i] >= d:
velocities[i] = d-1
#Decrease velocity randomly
if velocities[i] > 0:
if rnd() < p:
velocities[i] -= 1
positions[i] = positions_tmp[i] + velocities[i]
theta[i] = positions[i]*2*np.pi/roadlength
plot1.set_offsets(np.c_[theta, [r]*numcars])
plot2.set_offsets(np.c_[theta, [r+1]*numcars])
return [plot1, plot2]
# Call the animator, blit=True means only re-draw parts that have changed
anim = animation.FuncAnimation(fig, animate, frames=numframes, interval=100, blit=True, repeat=True)
plt.show()