有没有更好的方法使用Matplotlib绘制正交坐标轴?

4

你好!

我正在尝试使用matplotlib的quiver函数在三维空间中绘制向量。为了更好地可视化它们,我还想在原点处绘制正交轴。

理想情况下,我希望移动所谓的脊柱,但是根据这个SO post,没有易于解决这个问题的方法。

最后,我将轴作为沿x、y和z方向的三个向量绘制出来(见下面的代码),但是我无法摆脱这是一个糟糕的解决方案……非常感谢任何帮助。

以下是代码:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

f = plt.figure(1)
ax=plt.gca()
soa = np.array([[0, 0, 0, 1, 0, 0],[0, 0, 0, 0, 1, 0],[0, 0, 0, 0, 0, 1]])
X, Y, Z, U, V, W = zip(*soa)
soa2 = np.array([[0,0,0,np.sqrt(2)/2,np.sqrt(2)/2,np.sqrt(2)/2]])
I, J, K, F, G, H = zip(*soa2)

fig = plt.figure()
ax=Axes3D(fig)
ax.quiver(X, Y, Z, U, V, W, color='black')
ax.quiver(I, J, K, F, G, H)
ax.set_xlim([-1, 1])
ax.set_ylim([-1, 1])
ax.set_zlim([-1, 1])
f.show()

以下是由脚本返回的图像:

enter image description here

1个回答

1
我宁愿不使用quiver,因为它不能正确处理float128类型的输入参数XYZUVW。实际上,它会将这些输入静默转换为float,而我们系统中通常是float64。因此,float128输入会导致溢出!
相反,我想使用CT Zhu的简短类Arrow3D(在this wonderful answer中)来代替。它可以无缺陷地处理float128坐标并提供各种箭头样式
在那个帮助下,我开发了这个函数来在图形中心绘制X、Y和Z轴:
import numpy as np
import matplotlib.pyplot as plt

from Arrow3D import Arrow3D


def draw_xyz_axes_at_center(mpl_ax):

    # Compute max_lim based on plotted data
    x_lim = abs(max(mpl_ax.get_xlim(), key=abs))
    y_lim = abs(max(mpl_ax.get_ylim(), key=abs))
    z_lim = abs(max(mpl_ax.get_zlim(), key=abs))
    max_lim = max(x_lim, y_lim, z_lim)

    # Position xyz axes at the center
    mpl_ax.set_xlim(-max_lim, max_lim)
    mpl_ax.set_ylim(-max_lim, max_lim)
    mpl_ax.set_zlim(-max_lim, max_lim)

    # Draw xyz axes
    axes = ['x', 'y', 'z']
    for i, axis in enumerate(axes):
        start_end_pts = np.zeros((3, 2))
        start_end_pts[i] = [-max_lim, max_lim]

        # Draw axis
        xs, ys, zs = start_end_pts[0], start_end_pts[1], start_end_pts[2]

        a = Arrow3D(xs, ys, zs, 
                    mutation_scale=20, arrowstyle='-|>', color='black')
        mpl_ax.add_artist(a)

        # Add label
        end_pt_with_padding = start_end_pts[:, 1] * 1.1

        mpl_ax.text(*end_pt_with_padding,
                    axis,
                    horizontalalignment='center',
                    verticalalignment='center',
                    color='black')

要绘制矢量图形:

def draw_vector(mpl_ax, v):
    xs = [0, v[0]]
    ys = [0, v[1]]
    zs = [0, v[2]]

    a = Arrow3D(xs, ys, zs, 
                mutation_scale=20, arrowstyle='->', color='#1f77b4')
    mpl_ax.add_artist(a)

    # Axes limits automatically include the coordinates of all plotted data
    # but not Arrow3D artists. That's actually why this point is plotted.
    mpl_ax.plot(*v, '.', color='#1f77b4')

让我们使用它们:

ax = plt.figure(figsize=(7, 7)).add_subplot(projection='3d')

draw_vector(ax, np.array([2, 3, 5]))

draw_xyz_axes_at_center(ax)

ax.set_xlabel('x axis')
ax.set_ylabel('y axis')
ax.set_zlabel('z axis')

plt.show()

输出: 输入图像描述此处

顺便说一下,我使用的是Python 3,并且没有在Python 2上进行测试。


感谢您详细的回答,Shahrokh Bah!这正是我在寻找的! - Sheldon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接