首页 > 解决方案 > Python:使用 matplotlib.animation 为两个线条列表设置动画,但一次只显示一组线条

问题描述

试图绘制具有螺旋线和收缩、旋转多边形的追踪曲线,在每个当前点问题=无法同时绘制视线和主线图形在收缩的多边形之间来回滑动(由 SightLine 描述)和主要追踪曲线(MainLines)

当一次单独制作一个动画时,多边形和追踪曲线绘制得很好,但我无法让它们在同一个图形上一起工作。

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

plt.style.use('dark_background')


NumOfPoints = 6
deltaT = 0.005
duration = 50
steps = int(duration / deltaT)
speed = 0.2
num = 0

CurrentXPoints = []
CurrentYPoints = []
DeltaX = np.zeros(NumOfPoints)
DeltaY = np.zeros(NumOfPoints)
MagnitudeDelta = np.zeros(NumOfPoints)
VelocityX = np.zeros(NumOfPoints)
VelocityY = np.zeros(NumOfPoints)



  
#Creates Initial Points by equally spacing the points around a polygon inscribed around circle
for i in range(0,NumOfPoints): 
    x = np.cos(((i/NumOfPoints)*2)*np.pi)
    y = np.sin(((i/NumOfPoints)*2)*np.pi)

    CurrentXPoints.append(x)
    CurrentYPoints.append(y)

AllXPoints = np.array([CurrentXPoints])
AllYPoints = np.array([CurrentYPoints])

#Fills out both AllXPoints and AllYPoints with all points in duration 

for i in range(int(steps)):
    
    for j in range(0,NumOfPoints-1): #Calculates deltaX and deltaY at this timestep
        DeltaX[j] = CurrentXPoints[j+1] - CurrentXPoints[j]
        DeltaY[j] = CurrentYPoints[j+1] - CurrentYPoints[j]
    
    DeltaX[NumOfPoints-1] = CurrentXPoints[0] - CurrentXPoints[NumOfPoints-1]
    DeltaY[NumOfPoints-1] = CurrentYPoints[0] - CurrentYPoints[NumOfPoints-1]
    
    
    
    for j in range(0,NumOfPoints): # calculats new X and Y Points
        MagnitudeDelta[j] = ((DeltaX[j])**2 + (DeltaY[j])**2)**(1/2)
        VelocityX[j] = speed * (DeltaX[j]/MagnitudeDelta[j])
        VelocityY[j] = speed * (DeltaY[j]/MagnitudeDelta[j])
        CurrentXPoints[j] += deltaT * VelocityX[j]
        CurrentYPoints[j] += deltaT * VelocityY[j]

    CurrentXPointsArr = np.array(CurrentXPoints)
    CurrentYPointsArr = np.array(CurrentYPoints)
    
    AllXPoints = np.vstack((AllXPoints,CurrentXPointsArr))
    AllYPoints = np.vstack((AllYPoints,CurrentYPointsArr))



fig = plt.figure(figsize=(5,5))
ax = plt.axes()
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)


MainLines = []
SightLines= []
AllLines = MainLines + SightLines

for i in range(NumOfPoints):
    line, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
    MainLines.append(line)
    SightLines.append(line)
  

 
def UpdateMain(num, AllXPoints, AllYPoints, MainLines):
    
    
    
    for line in MainLines:
    
        position = MainLines.index(line)
        line.set_data([AllXPoints[i][position] for i in range(num)], [AllYPoints[i][position] for i in range(num)])
        
    
    
def UpdateSight(num, AllXPoints, AllYPoints, SightLines):
    
    for line in SightLines:
        position = SightLines.index(line)

        if position < (NumOfPoints-1):
            line.set_data([AllXPoints[num][position],AllXPoints[num][position+1]],
                         [AllYPoints[num][position],AllYPoints[num][position+1]])
        else:
            line.set_data([AllXPoints[num][position],AllXPoints[num][0]],
                         [AllYPoints[num][position],AllYPoints[num][0]])

    
    
            
        
ani1 = animation.FuncAnimation(fig, UpdateMain,steps, fargs=[AllXPoints, AllYPoints, MainLines],
                  interval=1, blit=True)
          
ani2 = animation.FuncAnimation(fig, UpdateSight,steps, fargs=[AllXPoints, AllYPoints, SightLines],
                  interval=1, blit=True)


plt.show()

标签: pythonmatplotlibanimationsimultaneous

解决方案


首先,您应该只使用一个FuncAnimation更新所有艺术家的。您的代码的主要问题是行

for i in range(NumOfPoints):
    line, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
    MainLines.append(line)
    SightLines.append(line)

您正在创建一位艺术家 ( line) 并将其分配给两个不同的列表。如果您为每个列表创建 2 行不同的行,则输出符合预期。

完整的工作代码:

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

plt.style.use('dark_background')


NumOfPoints = 6
deltaT = 0.005
duration = 50
steps = int(duration / deltaT)
speed = 0.2
num = 0

CurrentXPoints = []
CurrentYPoints = []
DeltaX = np.zeros(NumOfPoints)
DeltaY = np.zeros(NumOfPoints)
MagnitudeDelta = np.zeros(NumOfPoints)
VelocityX = np.zeros(NumOfPoints)
VelocityY = np.zeros(NumOfPoints)


def update(num, AllXPoints, AllYPoints, MainLines, SightLines):
    out = []
    out.append(UpdateMain(num, AllXPoints, AllYPoints, MainLines))
    out.append(UpdateSight(num, AllXPoints, AllYPoints, SightLines))
    return out
 
def UpdateMain(num, AllXPoints, AllYPoints, MainLines):    
    for line in MainLines:
        position = MainLines.index(line)
        line.set_data([AllXPoints[i][position] for i in range(num)], [AllYPoints[i][position] for i in range(num)])
    return MainLines
        
    
    
def UpdateSight(num, AllXPoints, AllYPoints, SightLines): 
    for line in SightLines:
        position = SightLines.index(line)

        if position < (NumOfPoints-1):
            line.set_data([AllXPoints[num][position],AllXPoints[num][position+1]],
                         [AllYPoints[num][position],AllYPoints[num][position+1]])
        else:
            line.set_data([AllXPoints[num][position],AllXPoints[num][0]],
                         [AllYPoints[num][position],AllYPoints[num][0]])
    return SightLines

  
#Creates Initial Points by equally spacing the points around a polygon inscribed around circle
for i in range(0,NumOfPoints): 
    x = np.cos(((i/NumOfPoints)*2)*np.pi)
    y = np.sin(((i/NumOfPoints)*2)*np.pi)

    CurrentXPoints.append(x)
    CurrentYPoints.append(y)

AllXPoints = np.array([CurrentXPoints])
AllYPoints = np.array([CurrentYPoints])

#Fills out both AllXPoints and AllYPoints with all points in duration 
for i in range(int(steps)):
    for j in range(0,NumOfPoints-1): #Calculates deltaX and deltaY at this timestep
        DeltaX[j] = CurrentXPoints[j+1] - CurrentXPoints[j]
        DeltaY[j] = CurrentYPoints[j+1] - CurrentYPoints[j]

    DeltaX[NumOfPoints-1] = CurrentXPoints[0] - CurrentXPoints[NumOfPoints-1]
    DeltaY[NumOfPoints-1] = CurrentYPoints[0] - CurrentYPoints[NumOfPoints-1]

    for j in range(0,NumOfPoints): # calculats new X and Y Points
        MagnitudeDelta[j] = ((DeltaX[j])**2 + (DeltaY[j])**2)**(1/2)
        VelocityX[j] = speed * (DeltaX[j]/MagnitudeDelta[j])
        VelocityY[j] = speed * (DeltaY[j]/MagnitudeDelta[j])
        CurrentXPoints[j] += deltaT * VelocityX[j]
        CurrentYPoints[j] += deltaT * VelocityY[j]

    CurrentXPointsArr = np.array(CurrentXPoints)
    CurrentYPointsArr = np.array(CurrentYPoints)
    AllXPoints = np.vstack((AllXPoints,CurrentXPointsArr))
    AllYPoints = np.vstack((AllYPoints,CurrentYPointsArr))

fig = plt.figure(figsize=(5,5))
ax = plt.axes()
ax.set_xlim(-2,2)
ax.set_ylim(-2,2)
ax.get_xaxis().set_visible(False)
ax.get_yaxis().set_visible(False)

MainLines = []
SightLines= []
AllLines = MainLines + SightLines

for i in range(NumOfPoints):
    line1, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
    line2, = ax.plot([AllXPoints[j][i] for j in range(steps)], [AllYPoints[j][i] for j in range(steps)])
    MainLines.append(line1)
    SightLines.append(line2)

ani = animation.FuncAnimation(fig, update, steps, fargs=[AllXPoints, AllYPoints, MainLines, SightLines], interval=1, blit=True)

plt.show()

动画结果显示缩小的六边形和从每个角延伸的螺旋曲线


推荐阅读