我正在寻找一种用python绘制一些(O(1))3D箭头的方法,这些箭头是"正确的3D",我的意思是Mathematica产生的东西,即箭杆看起来像一根管子。
我在matplotlib文档中找不到任何内容,但肯定有办法吗?
答案 0 :(得分:2)
您可以从2D中定义的某个路径创建旋转实体以创建3D箭头。以下代码将其包装到一个函数中,该函数允许指定一些箭头参数。这允许创建要使用的路径。然后围绕z轴旋转,创建3D箭头。为了允许箭头在空间中的任意取向,可以围绕x轴旋转完整箭头,然后绕z轴旋转(theta_x
,theta_z
)。最后,使用plot_surface
绘制箭头。请注意,箭头所在的轴应具有相同的宽高比,这样箭头不会倾斜。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def arrow3d(ax, length=1, width=0.05, head=0.2, headwidth=2,
theta_x=0, theta_z=0, offset=(0,0,0), **kw):
w = width
h = head
hw = headwidth
theta_x = np.deg2rad(theta_x)
theta_z = np.deg2rad(theta_z)
a = [[0,0],[w,0],[w,(1-h)*length],[hw*w,(1-h)*length],[0,length]]
a = np.array(a)
r, theta = np.meshgrid(a[:,0], np.linspace(0,2*np.pi,30))
z = np.tile(a[:,1],r.shape[0]).reshape(r.shape)
x = r*np.sin(theta)
y = r*np.cos(theta)
rot_x = np.array([[1,0,0],[0,np.cos(theta_x),-np.sin(theta_x) ],
[0,np.sin(theta_x) ,np.cos(theta_x) ]])
rot_z = np.array([[np.cos(theta_z),-np.sin(theta_z),0 ],
[np.sin(theta_z) ,np.cos(theta_z),0 ],[0,0,1]])
b1 = np.dot(rot_x, np.c_[x.flatten(),y.flatten(),z.flatten()].T)
b2 = np.dot(rot_z, b1)
b2 = b2.T+np.array(offset)
x = b2[:,0].reshape(r.shape);
y = b2[:,1].reshape(r.shape);
z = b2[:,2].reshape(r.shape);
ax.plot_surface(x,y,z, **kw)
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
arrow3d(ax)
arrow3d(ax, length=2, width=0.02, head=0.1, headwidth=1.5, offset=[1,1,0],
theta_x=40, color="crimson")
arrow3d(ax, length=1.4, width=0.03, head=0.15, headwidth=1.8, offset=[1,0.1,0],
theta_x=-60, theta_z = 60, color="limegreen")
ax.set_xlim(0,1)
ax.set_ylim(0,1)
ax.set_zlim(0,1)
plt.show()