【问题标题】:Animate Delaunay triangulation - Python动画 Delaunay 三角剖分 - Python
【发布时间】:2021-02-14 18:19:15
【问题描述】:

是否可以使用 Matplotlib 为 Delaunay 三角剖分设置动画?以下绘制按ItemTime 分组的顶点。我希望对此进行动画处理,而不是绘制每次迭代。

我的时间点也可能没有足够的点来充分绘制三角测量。对于这些时间点,我只是希望度过那个时期并进入下一个时间点。

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from scipy.spatial import Delaunay
import matplotlib.animation as animation
import matplotlib.gridspec as gridspec

# data frame containing time points without adequate points (3)
#df = pd.DataFrame({
#    'Time' : [1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3],  
#    'Item' : ['A','B','A','B','A','B','A','A','B','A','B','A','B','B','A','B'],                  
#    'X' : [5, 5, 6, 6, 4, 3, 3, 4, 4, 3, 2, 5, 4, 5, 1, 2], 
#    'Y' : [5, 6, 6, 5, 5, 6, 5, 6, 3, 1, 4, 6, 7, 4, 5, 6],                         
#        })

fig = plt.figure(figsize = (8,10))

grid = gridspec.GridSpec(1, 2)
gridsize = (1, 2)

ax = plt.subplot2grid(gridsize, (0, 0))
ax2 = plt.subplot2grid(gridsize, (0, 1))

A_coord = df.loc[df['Item'] == 'A']
B_coord = df.loc[df['Item'] == 'B']

def make_points(x):
    return np.array(list(zip(x['X'], x['Y'])))

A_points = A_coord.groupby(['Time']).apply(make_points)
B_points = B_coord.groupby(['Time']).apply(make_points)

for p in A_points:
    tri = Delaunay(p)
    a_del = ax.triplot(*p.T, tri.simplices, color = 'orange')

for p in B_points:
    tri = Delaunay(p)
    b_del = ax.triplot(*p.T, tri.simplices, color = 'purple')

#def animate(i) :

    #a_del.set_data#()
    #b_del.set_data#()    

#ani = animation.FuncAnimation(fig, animate, blit = False)

编辑 2:

我希望在绘制其他对象时保持图形和轴稳定。因此,我只想为三角剖分的变化设置动画。

df = pd.DataFrame({
    'Time' : [1,1,1,1,1,1,1,2,2,2,2,2,2,2],  
    'Item' : ['A','B','A','B','A','B','A','A','B','A','B','A','B','B'],                  
    'X' : [5, 5, 6, 6, 4, 3, 3, 4, 4, 3, 2, 5, 4, 5], 
    'Y' : [5, 6, 6, 5, 5, 6, 5, 6, 3, 1, 4, 6, 7, 4],                         
        })


A_coord = df.loc[df['Item'] == 'A']
B_coord = df.loc[df['Item'] == 'B']

def make_points(x):
    return np.array(list(zip(x['X'], x['Y'])))

A_points = A_coord.groupby(['Time']).apply(make_points)
B_points = B_coord.groupby(['Time']).apply(make_points)

A_points = A_points.values
B_points = B_points.values

fig = plt.figure(figsize = (8,10))

grid = gridspec.GridSpec(2, 2)
gridsize = (2, 2)

ax = plt.subplot2grid(gridsize, (0, 0), colspan = 2)
ax.set_xlim(0, 20)
ax.set_ylim(0, 20)

ax2 = plt.subplot2grid(gridsize, (1, 0))
ax3 = plt.subplot2grid(gridsize, (1, 1))

fig, ax = plt.subplots(nrows=1, ncols=2, figsize=(12,8))

def one_frame(i):

    ax[0].clear();ax[1].clear()

    try:
        a_points = np.unique(A_points[i],axis=0)
        tri_a = Delaunay(a_points)
        ax[0].triplot(*a_points.T, tri_a.simplices, color = 'orange')
    except Exception:
        pass

    try:
        b_points = np.unique(B_points[i],axis=0)
        tri_b = Delaunay(b_points)
        ax[1].triplot(*b_points.T, tri_b.simplices, color = 'purple')
    except Exception:
        pass


ani = animation.FuncAnimation(fig,one_frame, blit = False)

【问题讨论】:

    标签: python pandas matplotlib delaunay matplotlib-animation


    【解决方案1】:

    可能的朋友,试试这个代码

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.spatial import Delaunay
    import matplotlib.animation as animation
    
    # data frame containing time points without adequate points (3)
    df = pd.DataFrame({
       'Time' : [1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3],  
       'Item' : ['A','B','A','B','A','B','A','A','B','A','B','A','B','B','A','B'],                  
       'X' : [5, 5, 6, 6, 4, 3, 3, 4, 4, 3, 2, 5, 4, 5, 1, 2], 
       'Y' : [5, 6, 6, 5, 5, 6, 5, 6, 3, 1, 4, 6, 7, 4, 5, 6],                         
           })
    A_coord = df.loc[df['Item'] == 'A']
    B_coord = df.loc[df['Item'] == 'B']
    
    def make_points(x):
        return np.array(list(zip(x['X'], x['Y'])))
    
    A_points = A_coord.groupby(['Time']).apply(make_points)
    B_points = B_coord.groupby(['Time']).apply(make_points)
    
    A_points = A_points.values
    B_points = B_points.values
    
    fig, ax = plt.subplots(nrows=1,ncols=2,figsize=(12,8))
    
    def one_frame(i):
        
        ax[0].clear();ax[1].clear()
        
        try:
            a_points = np.unique(A_points[i],axis=0)
            tri_a = Delaunay(a_points)
            ax[0].triplot(*a_points.T, tri_a.simplices, color = 'orange')
        except Exception as e:
            print("frame %i, point a can't print because of \n%s" % (i,e))
        
        try:
            b_points = np.unique(B_points[i],axis=0)
            tri_b = Delaunay(b_points)
            ax[1].triplot(*b_points.T, tri_b.simplices, color = 'purple')
        except Exception as e:
            print("frame %i, point b can't print because of \n%s" % (i,e))
    
    ani = animation.FuncAnimation(fig,one_frame,range(3), blit = False)
    ani.save('test.gif', writer='pillow', fps=1)
    

    输出是


    更新

    可以保留figax,思路是把每帧开头最后一帧的三角形(Line2D对象)去掉

    for item in triangles_a:
        try:
            item.remove()
        except Exception as e:
            continue 
    for item in triangles_b:
        try:
            item.remove()
        except Exception as e:
            continue
    

    删除三角形不会影响figax 的其他部分。 例如,在下面的示例中,两个圆圈在动画期间不会受到影响。

    import pandas as pd
    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.spatial import Delaunay
    import matplotlib.animation as animation
    
    # data frame containing time points without adequate points (3)
    df = pd.DataFrame({
       'Time' : [1,1,1,1,1,1,1,2,2,2,2,2,2,2,3,3],  
       'Item' : ['A','B','A','B','A','B','A','A','B','A','B','A','B','B','A','B'],                  
       'X' : [5, 5, 6, 6, 4, 3, 3, 4, 4, 3, 2, 5, 4, 5, 1, 2], 
       'Y' : [5, 6, 6, 5, 5, 6, 5, 6, 3, 1, 4, 6, 7, 4, 5, 6],                         
           })
    A_coord = df.loc[df['Item'] == 'A']
    B_coord = df.loc[df['Item'] == 'B']
    
    def make_points(x):
        return np.array(list(zip(x['X'], x['Y'])))
    
    A_points = A_coord.groupby(['Time']).apply(make_points)
    B_points = B_coord.groupby(['Time']).apply(make_points)
    
    A_points = A_points.values
    B_points = B_points.values
    
    fig = plt.figure(figsize = (8,10))
    grid = gridspec.GridSpec(2, 2)
    gridsize = (2, 2)
    
    ax0 = plt.subplot2grid(gridsize, (0, 0), colspan = 2)
    ax1 = plt.subplot2grid(gridsize, (1, 0), colspan = 1)
    ax2 = plt.subplot2grid(gridsize, (1, 1), colspan = 1)
    
    ax1.set_xlim(0,8);ax1.set_ylim(0,8)
    ax2.set_xlim(0,8);ax2.set_ylim(0,8)
        
    # things that won't be affected 
    circle_0 = plt.Circle((4,4), 2, color='violet',fill=False)
    ax1.add_artist(circle_0)
    
    circle_1 = plt.Circle((5,4), 2, color='deepskyblue',fill=False)
    ax2.add_artist(circle_1)
        
    triangles_a,triangles_b = [],[]
    def one_frame(i):
        
        global triangles_a,triangles_b
        for item in triangles_a:
            try:
                item.remove()
            except Exception as e:
                continue 
        for item in triangles_b:
            try:
                item.remove()
            except Exception as e:
                continue
        
        try:
            a_points = np.unique(A_points[i],axis=0)
            tri_a = Delaunay(a_points)
            obj_a = ax1.triplot(*a_points.T, tri_a.simplices, color = 'orange')
            triangles_a.extend(obj_a)
        except Exception as e:
            print("frame %i, point a can't print because of \n%s" % (i,e))
        
        try:
            b_points = np.unique(B_points[i],axis=0)
            tri_b = Delaunay(b_points)
            obj_b = ax2.triplot(*b_points.T, tri_b.simplices, color = 'purple')
            triangles_b.extend(obj_b)
        except Exception as e:
            print("frame %i, point b can't print because of \n%s" % (i,e))
    
    ani = animation.FuncAnimation(fig,one_frame,range(3), blit = False)
    ani.save('test.gif', writer='pillow', fps=1)
    

    输出

    【讨论】:

    • 谢谢@meTchaikovsky。你帮了我不少忙!与上一个类似,是否可以保持无花果、斧头固定并仅绘制三角剖分的变化?
    • 不客气@jonboy,我也赚了很多代表! :D。也可以,看看我更新的帖子。
    • 谢谢。我仍然希望事先保持这个数字不变。我稍微操纵了图形和轴,然后更新了更改。我的实际网格更复杂。我已经调整了问题以强调这一点。我可能不得不问一个单独的问题。对此感到抱歉
    • @jonboy 不客气,我不明白,在我更新的帖子中,figax 是固定的,只有最后一帧的三角形会在开头删除每一帧。去掉三角形不会影响figax的其他部分。
    • @jonboy 使用gridspec 和使用ax 一样,查看我更新的帖子,我在那里使用gridspec
    猜你喜欢
    • 2019-04-18
    • 2015-01-07
    • 2021-05-14
    • 2013-05-12
    • 1970-01-01
    • 2016-02-08
    • 2014-01-21
    • 2020-05-06
    • 2019-09-28
    相关资源
    最近更新 更多