如何在 matplotlib 图形上制作动画
How to animate on matplotlib graph
我有一个作业需要将 3D 立方体投影到 2D 笛卡尔平面,我已经绘制了顶点,但仍需要以某种方式对其进行动画处理。
我试过使用 FuncAnimation(),但不知道它是如何工作的。我对 python 还是个新手,所以请放轻松,谢谢。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
A = np.array([-0.5,-0.5,-0.5])
B = np.array([0.5,-0.5,-0.5])
C = np.array([0.5,0.5,-0.5])
D = np.array([-0.5,0.5,-0.5])
E = np.array([-0.5,-0.5,0.5])
F = np.array([0.5,-0.5,0.5])
G = np.array([0.5,0.5,0.5])
H = np.array([-0.5,0.5,0.5])
load = np.array([A,B,C,D,E,F,G,H])
print(load)
fig = plt.figure()
ax = plt.axes(xlim =(-1,1),ylim =(-1,1))
# Declared to allow for x and y axis only
projection = np.array([ [1,0,0], [0,1,0] ])
xdata,ydata = [],[]
plt.title("Render 3D Cube in 2D Space")
for x in load:
for angle in range(360):
rotationY = np.array([ [np.cos(angle),0,np.sin(angle)],
[0,1,0],
[-np.sin(angle),0,np.cos(angle)] ])
rotationX = np.array([ [1,0,0],
[0,np.cos(angle),-np.sin(angle)],
[0,np.sin(angle),np.cos(angle)] ])
# Drawing each points
rotated = np.dot(rotationY,x)
rotated = np.dot(rotationX,rotated)
projected2d = np.dot(projection,rotated)
#projected2d = np.dot(projection,x) -With no rotations
line = ax.plot(projected2d[0],projected2d[1],c = "blue",marker = "o")
def animate(i):
x0,y0 = i
xdata.append(x0)
ydata.append(y0)
line.set_data(xdata,ydata)
return line
anim = FuncAnimation(fig,animate,interval =200,frames = 30)
plt.grid()
#plt.draw()
plt.show()
FuncAnimation
构造函数采用可调用函数(在您的情况下为 animate
),该函数获取当前帧编号作为参数(此处为 i
)并更新绘图。这意味着,您应该将所有中间点存储在一个数组 (frames
) 中,然后再访问它们(您也可以动态计算投影,但我不建议这样做)。然后动画将循环遍历帧并将函数应用于每一帧。
此外,您应该使用弧度(从 0 到 2π 的角度)进行旋转。
这是一个应该有效的版本:
# list of the angles in radians
angles = np.linspace(0, 2*np.pi, 360)
# storage of single frames - one value per point and angle.
frames = np.zeros((len(load),len(angles),2))
# loops through all points and angles to store for later usage.
for i, x in enumerate(load):
for j, angle in enumerate(angles):
rotationY = np.array([[np.cos(angle),0,np.sin(angle)],
[0,1,0],
[-np.sin(angle),0,np.cos(angle)] ])
rotationX = np.array([ [1,0,0],
[0,np.cos(angle),-np.sin(angle)],
[0,np.sin(angle),np.cos(angle)] ])
rotated = np.dot(rotationY, x)
rotated = np.dot(rotationX, rotated)
projected2d = np.dot(projection, rotated)
# store the point.
frames[i,j,:] = projected2d
# draws the initial point.
line, = ax.plot(frames[:,0,0], frames[:,0,1], c="blue", marker="o", ls='')
# defines what happens at frame 'i' - you want to update with the current
# frame that we have stored before.
def animate(i):
line.set_data(frames[:,i,0], frames[:,i,1])
return line # not really necessary, but optional for blit algorithm
# the number of frames is the number of angles that we wanted.
anim = FuncAnimation(fig, animate, interval=200, frames=len(angles))
我有一个作业需要将 3D 立方体投影到 2D 笛卡尔平面,我已经绘制了顶点,但仍需要以某种方式对其进行动画处理。
我试过使用 FuncAnimation(),但不知道它是如何工作的。我对 python 还是个新手,所以请放轻松,谢谢。
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
A = np.array([-0.5,-0.5,-0.5])
B = np.array([0.5,-0.5,-0.5])
C = np.array([0.5,0.5,-0.5])
D = np.array([-0.5,0.5,-0.5])
E = np.array([-0.5,-0.5,0.5])
F = np.array([0.5,-0.5,0.5])
G = np.array([0.5,0.5,0.5])
H = np.array([-0.5,0.5,0.5])
load = np.array([A,B,C,D,E,F,G,H])
print(load)
fig = plt.figure()
ax = plt.axes(xlim =(-1,1),ylim =(-1,1))
# Declared to allow for x and y axis only
projection = np.array([ [1,0,0], [0,1,0] ])
xdata,ydata = [],[]
plt.title("Render 3D Cube in 2D Space")
for x in load:
for angle in range(360):
rotationY = np.array([ [np.cos(angle),0,np.sin(angle)],
[0,1,0],
[-np.sin(angle),0,np.cos(angle)] ])
rotationX = np.array([ [1,0,0],
[0,np.cos(angle),-np.sin(angle)],
[0,np.sin(angle),np.cos(angle)] ])
# Drawing each points
rotated = np.dot(rotationY,x)
rotated = np.dot(rotationX,rotated)
projected2d = np.dot(projection,rotated)
#projected2d = np.dot(projection,x) -With no rotations
line = ax.plot(projected2d[0],projected2d[1],c = "blue",marker = "o")
def animate(i):
x0,y0 = i
xdata.append(x0)
ydata.append(y0)
line.set_data(xdata,ydata)
return line
anim = FuncAnimation(fig,animate,interval =200,frames = 30)
plt.grid()
#plt.draw()
plt.show()
FuncAnimation
构造函数采用可调用函数(在您的情况下为 animate
),该函数获取当前帧编号作为参数(此处为 i
)并更新绘图。这意味着,您应该将所有中间点存储在一个数组 (frames
) 中,然后再访问它们(您也可以动态计算投影,但我不建议这样做)。然后动画将循环遍历帧并将函数应用于每一帧。
此外,您应该使用弧度(从 0 到 2π 的角度)进行旋转。
这是一个应该有效的版本:
# list of the angles in radians
angles = np.linspace(0, 2*np.pi, 360)
# storage of single frames - one value per point and angle.
frames = np.zeros((len(load),len(angles),2))
# loops through all points and angles to store for later usage.
for i, x in enumerate(load):
for j, angle in enumerate(angles):
rotationY = np.array([[np.cos(angle),0,np.sin(angle)],
[0,1,0],
[-np.sin(angle),0,np.cos(angle)] ])
rotationX = np.array([ [1,0,0],
[0,np.cos(angle),-np.sin(angle)],
[0,np.sin(angle),np.cos(angle)] ])
rotated = np.dot(rotationY, x)
rotated = np.dot(rotationX, rotated)
projected2d = np.dot(projection, rotated)
# store the point.
frames[i,j,:] = projected2d
# draws the initial point.
line, = ax.plot(frames[:,0,0], frames[:,0,1], c="blue", marker="o", ls='')
# defines what happens at frame 'i' - you want to update with the current
# frame that we have stored before.
def animate(i):
line.set_data(frames[:,i,0], frames[:,i,1])
return line # not really necessary, but optional for blit algorithm
# the number of frames is the number of angles that we wanted.
anim = FuncAnimation(fig, animate, interval=200, frames=len(angles))