问题描述
我正在尝试使用 matplotlib 在 python 中重现
我能够使用 3D quiver 函数生成矢量箭头,但是当我
那么,问题是:如何生成多个不同长度的 3D 箭头?重要的是,我能否以这样一种方式生成它们,以便我可以轻松地针对动画的每一帧进行修改?
到目前为止,这是我的代码,使用不太有希望的 3D quiver 方法:
将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt导入 mpl_toolkits.mplot3d.axes3dax1 = 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)
到
范数 = 1
(一定要更改正确的行.norm"还有一个用法要高几行.)此外,为了让axes3d.py在mpl目录之外时正常运行,我更改了
来自 .导入 art3d从 .导入 proj3d从 .导入axis3d
到
from mpl_toolkits.mplot3d import art3d从 mpl_toolkits.mplot3d 导入 proj3d从 mpl_toolkits.mplot3d 导入axis3d
这是我能够生成的漂亮动画(不确定颜色出了什么问题,在我上传到 SO 之前看起来不错).
以及生成动画的代码:
将 numpy 导入为 np导入 matplotlib.pyplot 作为 plt导入axes3d_hackedax1 = plt.subplot(111,projection='3d')plt.ion()plt.show()t = np.linspace(0,10,40)对于索引,枚举延迟(np.linspace(0,1,20)):y = np.sin(t+delay)z = np.sin(t+delay)如果延迟>0:行.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('图像/帧%03i.gif'%index)plt.draw()plt.ioff()plt.show()
现在,如果我能让这些箭头看起来更漂亮,头部饱满就好.但这是一个单独的问题...
将来,matplotlib 不会根据此 拉取请求.
I am trying to reproduce the left plot of this animation in python using matplotlib.
I am able to generate the vector arrows using the 3D quiver function, but as I read here, it does not seem possible to set the lengths of the arrows. So, my plot does not look quite right:
So, the question is: how do I generate a number of 3D arrows with different lengths? Importantly, can I generate them in such a way so that I can easily modify for each frame of the animation?
Here's my code so far, with the not-so-promising 3D quiver approach:
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()
As Azad suggests, an inelegant, but effective, solution is to simply edit the mpl_toolkits/mplot3d/axes3d.py to remove the normalization. Since I didn't want to mess with my actual matplotlib installation, I simply copied the axes3d.py file to the same directory as my other script and modified the line
norm = math.sqrt(u ** 2 + v ** 2 + w ** 2)
to
norm = 1
(Be sure to change the correct line. There is another use of "norm" a few lines higher.) Also, to get axes3d.py to function correctly when it's outside of the mpl directory, I changed
from . import art3d
from . import proj3d
from . import axis3d
to
from mpl_toolkits.mplot3d import art3d
from mpl_toolkits.mplot3d import proj3d
from mpl_toolkits.mplot3d import axis3d
And here is the nice animation that I was able to generate (not sure what's going wrong with the colors, it looks fine before I uploaded to SO).
And the code to generate the animation:
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()
Now, if I could only get those arrows to look prettier, with nice filled heads. But that's a separate question...
EDIT: In the future, matplotlib will not automatically normalize the arrow lengths in the 3D quiver per this pull request.
这篇关于如何在 matplotlib 中更新 3D 箭头动画的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!