【问题标题】:Is there a better way to plot orthogonal axes using Matplotlib?有没有更好的方法来使用 Matplotlib 绘制正交轴?
【发布时间】:2019-06-09 00:20:35
【问题描述】:

喂!

我正在尝试使用 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()

这是此脚本返回的图像:

【问题讨论】:

    标签: python python-2.7 matplotlib


    【解决方案1】:

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

    相反,我想在this wonderful answer 中使用CT Zhu 的简短类Arrow3D。它与 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!这正是我想要的!
    猜你喜欢
    • 2015-04-07
    • 2014-06-28
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 2012-12-05
    相关资源
    最近更新 更多