【问题标题】:Arrow animation in PythonPython中的箭头动画
【发布时间】:2016-10-14 02:25:45
【问题描述】:

首先,我刚刚开始学习 Python。在过去的几个小时里,我一直在努力更新箭头属性以便在绘图动画期间更改它们。

在彻底寻找答案后,我检查是否可以通过修改属性“中心”来更改圆形补丁中心,例如circle.center = new_coordinates。但是,我没有找到将这种机制外推到箭头补丁的方法......

目前的代码是:

import numpy as np, math, matplotlib.patches as patches
from matplotlib import pyplot as plt
from matplotlib import animation

# Create figure
fig = plt.figure()    
ax = fig.gca()

# Axes labels and title are established
ax = fig.gca()
ax.set_xlabel('x')
ax.set_ylabel('y')

ax.set_ylim(-2,2)
ax.set_xlim(-2,2)
plt.gca().set_aspect('equal', adjustable='box')

x = np.linspace(-1,1,20) 
y  = np.linspace(-1,1,20) 
dx = np.zeros(len(x))
dy = np.zeros(len(y))

for i in range(len(x)):
    dx[i] = math.sin(x[i])
    dy[i] = math.cos(y[i])
patch = patches.Arrow(x[0], y[0], dx[0], dy[0] )


def init():
    ax.add_patch(patch)
    return patch,

def animate(t):
    patch.update(x[t], y[t], dx[t], dy[t])   # ERROR
    return patch,

anim = animation.FuncAnimation(fig, animate, 
                               init_func=init, 
                               interval=20,
                               blit=False)

plt.show()

在尝试了几个选项后,我认为功能更新可以让我更接近解决方案。但是,我得到了错误:

TypeError: update() takes 2 positional arguments but 5 were given

如果我通过定义如下所示的 animate 函数每一步再添加一个补丁,我会得到所附图像中显示的结果。

def animate(t):
    patch = plt.Arrow(x[t], y[t], dx[t], dy[t] )
    ax.add_patch(patch)
    return patch,

Wrong animation

我尝试添加一个 patch.delete 语句并创建一个新补丁作为更新机制,但这会导致一个空动画...

【问题讨论】:

  • 提示:如果您像您所说的那样是初学者,我建议您先尝试非常更简单的方法,然后再进行此类操作。
  • 你可能是对的......我已经成功实现了线条和散点的 2D 和 3D 动画,我只想更进一步。学习更新动画中的任何随机对象打开了一个充满可能性的世界:P 感谢您的提示!
  • 很高兴我能帮助老兄!

标签: python animation matplotlib


【解决方案1】:

ax.add_patch(patch) 之前添加ax.clear(),但会从图中删除所有元素。

def animate(t):

    ax.clear() 

    patch = plt.Arrow(x[t], y[t], dx[t], dy[t] )
    ax.add_patch(patch)

    return patch,

编辑:删除一个补丁

  • 使用ax.patches.pop(index)

    在您的示例中只有一个补丁,因此您可以使用index=0

      def animate(t):
    
          ax.patches.pop(0) 
    
          patch = plt.Arrow(x[t], y[t], dx[t], dy[t] )
          ax.add_patch(patch)
    
          return patch,
    
  • 使用ax.patches.remove(object)

    它需要global 来获取/设置外部patchArrow

      def animate(t):
    
          global patch
    
          ax.patches.remove(patch) 
    
          patch = plt.Arrow(x[t], y[t], dx[t], dy[t] )
          ax.add_patch(patch)
    
          return patch,
    

顺便说一句:获取您可以与update()一起使用的属性列表

print( patch.properties().keys() )

dict_keys(['aa', 'clip_path', 'patch_transform', 'edgecolor', 'path', 'verts', 'rasterized', 'linestyle', 'transform', 'picker', 'capstyle', 'children', 'antialiased', 'sketch_params', 'contains', 'snap', 'extents', 'figure', 'gid', 'zorder', 'transformed_clip_path_and_affine', 'clip_on', 'data_transform', 'alpha', 'hatch', 'axes', 'lw', 'path_effects', 'visible', 'label', 'ls', 'linewidth', 'agg_filter', 'ec', 'facecolor', 'fc', 'window_extent', 'animated', 'url', 'clip_box', 'joinstyle', 'fill'])

所以你可以使用update 来改变颜色 - facecolor

def animate(t):
    global patch
    
    t %= 20 # get only 0-19 to loop animation and get color t/20 as 0.0-1.0

    ax.patches.remove(patch)

    patch = patches.Arrow(x[t], y[t], dx[t], dy[t])

    patch.update({'facecolor': (t/20,t/20,t/20,1.0)})
    
    ax.add_patch(patch)

    return patch,

【讨论】:

    【解决方案2】:

    我通过模仿patches.Arrow.__init__中的代码发现了这一点:

    import numpy as np
    import matplotlib.patches as patches
    from matplotlib import pyplot as plt
    from matplotlib import animation
    import matplotlib.transforms as mtransforms
    
    # Create figure
    fig, ax = plt.subplots()
    
    # Axes labels and title are established
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    
    ax.set_ylim(-2,2)
    ax.set_xlim(-2,2)
    ax.set_aspect('equal', adjustable='box')
    
    N = 20
    x = np.linspace(-1,1,N) 
    y  = np.linspace(-1,1,N) 
    dx = np.sin(x)
    dy = np.cos(y)
    
    patch = patches.Arrow(x[0], y[0], dx[0], dy[0])
    
    def init():
        ax.add_patch(patch)
        return patch,
    
    def animate(t):
        L = np.hypot(dx[t], dy[t])
    
        if L != 0:
            cx = float(dx[t]) / L
            sx = float(dy[t]) / L
        else:
            # Account for division by zero
            cx, sx = 0, 1
    
        trans1 = mtransforms.Affine2D().scale(L, 1)
        trans2 = mtransforms.Affine2D.from_values(cx, sx, -sx, cx, 0.0, 0.0)
        trans3 = mtransforms.Affine2D().translate(x[t], y[t])
        trans = trans1 + trans2 + trans3
        patch._patch_transform = trans.frozen()
        return patch,
    
    anim = animation.FuncAnimation(fig, animate, 
                                   init_func=init, 
                                   interval=20,
                                   frames=N,
                                   blit=False)
    
    plt.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-09-07
      • 2012-05-23
      • 1970-01-01
      • 2016-01-22
      • 2014-12-26
      • 2019-07-26
      • 2017-07-21
      • 2021-11-23
      相关资源
      最近更新 更多