使用matplotlib

时间:2016-08-22 18:06:54

标签: python animation matplotlib

我用matplotlib和python制作动画,动画如下:        Animation

我想要做的是用更多动画扩展这个情节,我想完成下一个数字: enter image description here

主要的想法是这样的: 绿色圆圈分为2个,共有8组(这就是为什么是8轴)。当任何蓝色圆圈通过绿色圆圈时,在相应的轴上绘制相应时间内的垂直线。我不知道如何制作这个。欢迎任何想法:) 映入眼帘! 代码:

circ = np.linspace(0,360,360)
circ*=2*np.pi/360
ra = np.empty(360)
wheel_position=[]
ra.fill(28120/2)
r=np.full((1,10*2),28120/2)
Ru=180-np.array([24,63,102,141,181.5,219,258,297,336,360])
Ru_pos=[]
rtm_pos= np.array([22.5,67.5,112.5,157.5,202.5,247.5,292.5,337.5])
rw=np.empty(16)
rw.fill(28120/2)
for i in rtm_pos:
    wheel_position.append([i-2.3,i+2.3])    
wheel_position=np.array(wheel_position)
wheel_position=2*np.pi/360*np.ravel(wheel_position)


for i in Ru:
    Ru_pos.append([i-0.51,i+0.51])
Ru_pos=np.ravel(Ru_pos)
Ru_pos=2*np.pi/360*Ru_pos
def simData():
    t_max=360
    theta0=Ru_pos
    theta=np.array([0,0])
    t=0
    dt=0.5
    vel=2*np.pi/360

    while t<t_max:
        theta=theta0+vel*t
        t=t+dt
        yield theta, t

def simPoints(simData):
    theta, t = simData[0], simData[1]
    time_text.set_text(time_template%(t))
    line.set_data(theta,r)

fig = plt.figure()
ax1.set_rmax(28120/2+1550)
ax1.grid(True)
ax1 = fig.add_subplot(121, projection='polar')
line, = ax1.plot([], [], 'bo', ms=3, zorder=2)
time_template = 'Time = %.1f s'   
time_text = ax1.text(0.05, 0.9, '', transform=ax.transAxes)
ax1.set_ylim(0, 28120/2+5000)
ax1.plot(circ,ra, color='r', linestyle='-',zorder=1,lw=1)
ax1.plot(wheel_position,rw,'bo',ms=4.6,zorder=3,color='g')
ani = animation.FuncAnimation(fig, simPoints, simData, blit=False,\
     interval=1, repeat=True)
plt.show()

1 个答案:

答案 0 :(得分:1)

主要更改将插入原始animation.FuncAnimation之前和之前plt.show()

import matplotlib.pyplot as plt
import matplotlib.animation as animation
import numpy as np

circ = np.linspace(0,360,360)
circ *= 2*np.pi/360
ra = np.empty(360)
wheel_position=[]
ra.fill(28120/2)
r = np.full((1,10*2),28120/2)
Ru = 180 - np.array([24,63,102,141,181.5,219,258,297,336,360])
Ru_pos = []
rtm_pos = np.array([22.5,67.5,112.5,157.5,202.5,247.5,292.5,337.5])
rw = np.empty(16)
rw.fill(28120/2)
for i in rtm_pos:
    wheel_position.append([i-2.3,i+2.3])    
wheel_position=np.array(wheel_position)
wheel_position=2*np.pi/360*np.ravel(wheel_position)

for i in Ru:
    Ru_pos.append([i-0.51,i+0.51])

Ru_pos = np.ravel(Ru_pos)
Ru_pos = 2*np.pi/360*Ru_pos

def simData():
    t_max = 360
    theta0 = Ru_pos
    theta = np.array([0,0])
    t = 0
    dt = 0.5
    vel = 2*np.pi/360

    while t<t_max:
        theta=theta0+vel*t
        t=t+dt
        yield theta, t

# renamed parameter to avoid confusion with the function
def simPoints(data):
    theta, t = data[0], data[1]
    time_text.set_text(time_template%(t))
    line.set_data(theta,r)

# Number of subplots needed for green pairs
nplots = int(len(wheel_position)/2)

fig = plt.figure()
ax1 = plt.subplot2grid((nplots,2),(0,0), rowspan=nplots, projection='polar')
ax1.set_rmax(28120/2+1550)
ax1.grid(True)
line, = ax1.plot([], [], 'bo', ms=3, zorder=2)
time_template = 'Time = %.1f s'   
time_text = ax1.text(0.05, 0.9, '', transform=ax1.transAxes)
ax1.set_ylim(0, 28120/2+5000)

# red circle
ax1.plot(circ,ra, color='r', linestyle='-',zorder=1,lw=1)

# green dots
green_line, = ax1.plot(wheel_position,rw,'bo',ms=4.6,zorder=3,color='g')
green_dots = green_line.get_data()[0]
green_dots = np.reshape(green_dots, (int(len(green_dots)/2),2))

ani1 = animation.FuncAnimation(fig, simPoints, simData, blit=False,\
     interval=1, repeat=True)

# Used to check if we should mark an intersection for a given tick
# Update this with your preferred distance function
def check_intersect(pt1, pt2, tolerance=0.05):
    return np.linalg.norm(pt1-pt2) < tolerance

def greenFunc(*args):
    t = args[0]

    affected_plots = []
    for n in range(nplots):
        ax = green_plots[n]

        blue_dots = line.get_data()[0]
        if len(blue_dots) < 2: # still initializing
            return ax,

        blue_dots = np.reshape(blue_dots, (int(len(blue_dots)/2),2))

        is_intersect = False
        for dot in blue_dots:
            if check_intersect(dot, green_dots[n]):
                is_intersect = True

        if is_intersect:
            ax.plot([t,t], [-1,1], color='k')
            affected_plots.append(ax)

    return affected_plots

# Create the 8 subplots
green_plots = []
for i in range(nplots):
    if i == 0:
        ax = plt.subplot2grid((nplots,2),(i,1))
    else:
        ax = plt.subplot2grid((nplots,2),(i,1), sharex=green_plots[0], sharey=green_plots[0])

    # Hide x labels on all but last
    if i < nplots-1:
        plt.setp(ax.get_xticklabels(), visible=False)

    green_plots.append(ax)

# Add animation for intersections with green circles
ani = animation.FuncAnimation(fig, greenFunc, \
    blit=False, interval=1, repeat=True)

plt.show()

这引入了两个新功能:

  • check_intersect根据给定公差范围内的欧几里德距离决定是否应将两个点计为交叉(从而绘制一条线)。公差是必要的,因为位置是以离散的间隔计算的(尝试零容差 - 它永远不会是完全匹配)。您可能希望根据需要调整等式和公差。

  • greenFunc(我知道,有创意)循环遍历所有子图并检查是否画线。

其余的只是创建子图并添加一个调用greenFunc的动画。

让它运行一段时间后,我得到了结果:

Resulting plot

更改标签大小和位置留给读者练习;)