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

时间:2019-01-15 00:40:05

标签: python python-2.7 matplotlib

嗨!

我正在尝试使用matplotlib quiver函数以3D方式绘制矢量。为了使它们可视化,我还想绘制以原点为中心的正交轴。

理想情况下,我想移动所谓的棘刺,但根据this 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 个答案:

答案 0 :(得分:1)

我宁愿不使用 quiver,因为它不能正确处理 float128 dtypes 的输入参数 X、{{1 }}、YZUV。事实上,它会默默地将这些输入转换为 float,在我们的系统中通常是 float64。结果,float128 输入导致溢出!

相反,我想在 CT Zhu 中使用 this wonderful answer 的简短课程 W。它与 float128 坐标完美配合,并提供各种箭头样式

在此帮助下,我开发了此函数以在图形中心绘制 X、Y 和 Z 轴:

Arrow3D

绘制矢量:

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')

输出: enter image description here

顺便说一下,我使用了 Python 3 并且没有在 Python 2 上测试它。