如何更新matplotlib中的3D箭头动画
How to update 3D arrow animation in matplotlib
我正在尝试使用 matplotlib 在 python 中重现 this animation 的左图。
我可以使用 3D 箭袋功能生成矢量箭头,但我 read here 似乎无法设置箭头的长度。所以,我的情节看起来不太正确:
所以,问题是:如何生成多个不同长度的 3D 箭头?重要的是,我能否以这样一种方式生成它们,以便我可以轻松地为动画的每一帧进行修改?
到目前为止,这是我的代码,使用不太有前途的 3D 箭袋方法:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d
ax1 = plt.subplot(111,projection='3d')
t = np.linspace(0,10,40)
y = np.sin(t)
z = np.sin(t)
line, = ax1.plot(t,y,z,color='r',lw=2)
ax1.quiver(t,y,z, t*0,y,z)
plt.show()
正如 Azad 所建议的,一个不优雅但有效的解决方案是简单地编辑 mpl_toolkits/mplot3d/axes3d.py 以删除规范化。由于我不想弄乱我实际的 matplotlib 安装,我只是将 axes3d.py 文件复制到与我的其他脚本相同的目录并修改了行
norm = math.sqrt(u ** 2 + v ** 2 + w ** 2)
到
norm = 1
(一定要更改正确的行。"norm" 的另一个用途是高几行。)此外,要使 axes3d.py 在 mpl 目录之外时正常运行,我变了
from . import art3d
from . import proj3d
from . import axis3d
到
from mpl_toolkits.mplot3d import art3d
from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.mplot3d import axis3d
这是我能够生成的漂亮动画(不确定颜色出了什么问题,在我上传到 SO 之前它看起来不错)。
以及生成动画的代码:
import numpy as np
import matplotlib.pyplot as plt
import axes3d_hacked
ax1 = plt.subplot(111,projection='3d')
plt.ion()
plt.show()
t = np.linspace(0,10,40)
for index,delay in enumerate(np.linspace(0,1,20)):
y = np.sin(t+delay)
z = np.sin(t+delay)
if delay > 0:
line.remove()
ax1.collections.remove(linecol)
line, = ax1.plot(t,y,z,color='r',lw=2)
linecol = ax1.quiver(t,y,z, t*0,y,z)
plt.savefig('images/Frame%03i.gif'%index)
plt.draw()
plt.ioff()
plt.show()
现在,如果我能让那些箭头看起来更漂亮,并且有漂亮的填充头就好了。但这是一个单独的问题...
编辑:未来,matplotlib 将不会根据此 pull request.
自动归一化 3D 箭袋中的箭头长度
另一个解决方案是在每个箭头上单独调用 ax.quiever
- 每个调用都有自己的 length
属性。这不是很有效,但它会让你继续前进。
并且无需更改 MPL 代码
我正在尝试使用 matplotlib 在 python 中重现 this animation 的左图。
我可以使用 3D 箭袋功能生成矢量箭头,但我 read here 似乎无法设置箭头的长度。所以,我的情节看起来不太正确:
所以,问题是:如何生成多个不同长度的 3D 箭头?重要的是,我能否以这样一种方式生成它们,以便我可以轻松地为动画的每一帧进行修改?
到目前为止,这是我的代码,使用不太有前途的 3D 箭袋方法:
import numpy as np
import matplotlib.pyplot as plt
import mpl_toolkits.mplot3d.axes3d
ax1 = plt.subplot(111,projection='3d')
t = np.linspace(0,10,40)
y = np.sin(t)
z = np.sin(t)
line, = ax1.plot(t,y,z,color='r',lw=2)
ax1.quiver(t,y,z, t*0,y,z)
plt.show()
正如 Azad 所建议的,一个不优雅但有效的解决方案是简单地编辑 mpl_toolkits/mplot3d/axes3d.py 以删除规范化。由于我不想弄乱我实际的 matplotlib 安装,我只是将 axes3d.py 文件复制到与我的其他脚本相同的目录并修改了行
norm = math.sqrt(u ** 2 + v ** 2 + w ** 2)
到
norm = 1
(一定要更改正确的行。"norm" 的另一个用途是高几行。)此外,要使 axes3d.py 在 mpl 目录之外时正常运行,我变了
from . import art3d
from . import proj3d
from . import axis3d
到
from mpl_toolkits.mplot3d import art3d
from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.mplot3d import axis3d
这是我能够生成的漂亮动画(不确定颜色出了什么问题,在我上传到 SO 之前它看起来不错)。
以及生成动画的代码:
import numpy as np
import matplotlib.pyplot as plt
import axes3d_hacked
ax1 = plt.subplot(111,projection='3d')
plt.ion()
plt.show()
t = np.linspace(0,10,40)
for index,delay in enumerate(np.linspace(0,1,20)):
y = np.sin(t+delay)
z = np.sin(t+delay)
if delay > 0:
line.remove()
ax1.collections.remove(linecol)
line, = ax1.plot(t,y,z,color='r',lw=2)
linecol = ax1.quiver(t,y,z, t*0,y,z)
plt.savefig('images/Frame%03i.gif'%index)
plt.draw()
plt.ioff()
plt.show()
现在,如果我能让那些箭头看起来更漂亮,并且有漂亮的填充头就好了。但这是一个单独的问题...
编辑:未来,matplotlib 将不会根据此 pull request.
自动归一化 3D 箭袋中的箭头长度另一个解决方案是在每个箭头上单独调用 ax.quiever
- 每个调用都有自己的 length
属性。这不是很有效,但它会让你继续前进。
并且无需更改 MPL 代码