更改 3D 绘图 (Matplotlib) 的垂直 (z) 轴的位置? [英] Changing position of vertical (z) axis of 3D plot (Matplotlib)?

查看:106
本文介绍了更改 3D 绘图 (Matplotlib) 的垂直 (z) 轴的位置?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 Python 中的 Matplotlib 绘制一些 3D 曲面图,并注意到一个令人讨厌的现象.根据我设置视点(相机位置)的方式,垂直 (z) 轴在左侧和右侧之间移动.以下是两个示例:示例 1,轴左示例 2,轴右.第一个例子有 ax.view_init(25,-135) 而第二个例子有 ax.view_init(25,-45).

I'm doing some 3D surface plots using Matplotlib in Python and have noticed an annoying phenomenon. Depending on how I set the viewpoint (camera location), the vertical (z) axis moves between the left and right side. Here are two examples: Example 1, Axis left, Example 2, Axis right. The first example has ax.view_init(25,-135) while the second has ax.view_init(25,-45).

我希望保持相同的观点(查看数据的最佳方式).有没有办法强制轴向一侧或另一侧?

I would like to keep the viewpoints the same (best way to view the data). Is there any way to force the axis to one side or the other?

推荐答案

我需要类似的东西:在两侧绘制 zaxis.感谢@crayzeewulf 的回答,我开始遵循以下解决方法(左侧、右侧或两侧):

I needed something similar: drawing the zaxis on both sides. Thanks to the answer by @crayzeewulf I came to following workaround (for left, righ, or both sides):

首先根据需要绘制 3d,然后在调用 show() 之前用一个简单地覆盖 draw()<的 Wrapper 类包装 Axes3D/code> 方法.

First plot your 3d as you need, then before you call show() wrap the Axes3D with a Wrapper class that simply overrides the draw() method.

Wrapper Class 调用只是简单地将一些特征的可见性设置为 False,它绘制自身并最终绘制带有修改后的 PLANES 的 zaxis.这个 Wrapper 类允许您在左侧、右侧或两侧绘制 zaxis.

The Wrapper Class calls simply sets the visibility of some features to False, it draws itself and finally draws the zaxis with modified PLANES. This Wrapper Class allows you to draw the zaxis on the left, on the rigth or on both sides.

import matplotlib
matplotlib.use('QT4Agg')
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import axes3d

class MyAxes3D(axes3d.Axes3D):

    def __init__(self, baseObject, sides_to_draw):
        self.__class__ = type(baseObject.__class__.__name__,
                              (self.__class__, baseObject.__class__),
                              {})
        self.__dict__ = baseObject.__dict__
        self.sides_to_draw = list(sides_to_draw)
        self.mouse_init()

    def set_some_features_visibility(self, visible):
        for t in self.w_zaxis.get_ticklines() + self.w_zaxis.get_ticklabels():
            t.set_visible(visible)
        self.w_zaxis.line.set_visible(visible)
        self.w_zaxis.pane.set_visible(visible)
        self.w_zaxis.label.set_visible(visible)

    def draw(self, renderer):
        # set visibility of some features False 
        self.set_some_features_visibility(False)
        # draw the axes
        super(MyAxes3D, self).draw(renderer)
        # set visibility of some features True. 
        # This could be adapted to set your features to desired visibility, 
        # e.g. storing the previous values and restoring the values
        self.set_some_features_visibility(True)

        zaxis = self.zaxis
        draw_grid_old = zaxis.axes._draw_grid
        # disable draw grid
        zaxis.axes._draw_grid = False

        tmp_planes = zaxis._PLANES

        if 'l' in self.sides_to_draw :
            # draw zaxis on the left side
            zaxis._PLANES = (tmp_planes[2], tmp_planes[3],
                             tmp_planes[0], tmp_planes[1],
                             tmp_planes[4], tmp_planes[5])
            zaxis.draw(renderer)
        if 'r' in self.sides_to_draw :
            # draw zaxis on the right side
            zaxis._PLANES = (tmp_planes[3], tmp_planes[2], 
                             tmp_planes[1], tmp_planes[0], 
                             tmp_planes[4], tmp_planes[5])
            zaxis.draw(renderer)

        zaxis._PLANES = tmp_planes

        # disable draw grid
        zaxis.axes._draw_grid = draw_grid_old

def example_surface(ax):
    """ draw an example surface. code borrowed from http://matplotlib.org/examples/mplot3d/surface3d_demo.html """
    from matplotlib import cm
    import numpy as np
    X = np.arange(-5, 5, 0.25)
    Y = np.arange(-5, 5, 0.25)
    X, Y = np.meshgrid(X, Y)
    R = np.sqrt(X**2 + Y**2)
    Z = np.sin(R)
    surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm, linewidth=0, antialiased=False)

if __name__ == '__main__':
    fig = plt.figure(figsize=(15, 5))
    ax = fig.add_subplot(131, projection='3d')
    ax.set_title('z-axis left side')
    ax = fig.add_axes(MyAxes3D(ax, 'l'))
    example_surface(ax) # draw an example surface
    ax = fig.add_subplot(132, projection='3d')
    ax.set_title('z-axis both sides')
    ax = fig.add_axes(MyAxes3D(ax, 'lr'))
    example_surface(ax) # draw an example surface
    ax = fig.add_subplot(133, projection='3d')
    ax.set_title('z-axis right side')
    ax = fig.add_axes(MyAxes3D(ax, 'r'))
    example_surface(ax) # draw an example surface
    plt.show()

这篇关于更改 3D 绘图 (Matplotlib) 的垂直 (z) 轴的位置?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆