要更新常规2D箭袋图,您可以使用.set_UVC()
直接设置x
和y
数据。
与箭袋相当的3D是Axes3D.quiver()
,然而这似乎没有相当于.set_UVC()
。如何更新数据? segments
似乎确实包含来自箭头箭头的数据但是我没有看到输入数据和段如何相关。
我可以删除箭头图然后重新绘制一个新的但是效率低并且会影响性能,我想知道是否有直接设置数据的方法。
如果您查看Line3DCollection
代码,您会发现LineCollection
类中没有太多方法被重载。对你来说重要的是set_segments()
,看起来像这样:
def set_segments(self, segments):
'''
Set 3D segments
'''
self._segments3d = np.asanyarray(segments)
LineCollection.set_segments(self, [])
所以当调用set_segments()
时,这些段实际上存储在self._segments3d
中,并且LineCollection
的set_segments()
方法被调用一个空列表。然后Line3DCollection
在一个重载的draw()
方法中处理它自己的段列表。有两点需要注意:
numpy.meshgrids
定义您的箭头坐标,在_segments3d
中坐标存储在形状(N,2,3)
的数组中,其中N是点的数量,其内容基本上是[[[x0,y0,z0],[u0,v0,w0]],[[x1,y1,z1],[u1,v1,w1]],...]
,所以你可能需要操纵你的数据以适应该格式。_segments3d
。至少对我来说,这个数字不能正确更新 - 你必须通过set_segments()
。但是,如果您只是想改变某些坐标,则可以通过读出_segments3d
来访问以前的值。这里还有一些任意的例子,我为测试我刚解释的所有东西而制作的:
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import axes3d
from matplotlib.animation import FuncAnimation
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
num_frames = 50
theta = np.linspace(0,2*np.pi, 10, endpoint=False)
r = np.arange(1,2.1)
z = np.arange(-2,2.1,1)
def compute_segs(i):
offset = 2*i*np.pi/num_frames
theta2,r2, z2 = np.meshgrid(theta+offset,r,z)
x = r2*np.cos(theta2)
y = r2*np.sin(theta2)
u = x+0.2*np.cos(4*theta2)
v = y
w = z2+0.2*np.sign(z2)*np.sin(4*theta2)
return x,y,z2,u,v,w
segs = compute_segs(0)
cols = ['b' for x in segs[0].ravel()]
cols[0] = 'r'
quivers = ax.quiver(*segs, length=0.1, colors = cols, normalize=True)
ax.set_xlim([-3,3])
ax.set_ylim([-3,3])
ax.set_zlim([-3,3])
def animate(i):
segs = np.array(compute_segs(i)).reshape(6,-1)
new_segs = [[[x,y,z],[u,v,w]] for x,y,z,u,v,w in zip(*segs.tolist())]
quivers.set_segments(new_segs)
return quivers
ani = FuncAnimation(fig, animate, frames = num_frames, interval = 30, blit=False)
ani.save('update_3d_quiver.gif', writer='imagemagick')
plt.show()
......结果如下:
希望这可以帮助。
要详细说明我已接受的ThomasKühn的答案,如果您有网格点和要转换为段的箭数据,则可以使用以下函数。
def quiver_data_to_segments(X, Y, Z, u, v, w, length=1):
segments = (X, Y, Z, X+v*length, Y+u*length, Z+w*length)
segments = np.array(segments).reshape(6,-1)
return [[[x, y, z], [u, v, w]] for x, y, z, u, v, w in zip(*list(segments))]
然后,您可以使用输出更新绘图的片段,这种方式还允许您使用长度来指定箭头的标准化长度,通常最好将此值设置为输入数据的平均值或最大值的倍数(np.sqrt(vv**2 + uu**2 + ww**2)
)。
segments = quiver_data_to_segments(X, Y, Z, uu, vv, ww, length=5)
quiver_plot.set_segments(segments)