Changing position of vertical (z) axis of 3D plot (Matplotlib)?
我正在使用 Python 中的 Matplotlib 绘制一些 3D 曲面图,并注意到一个令人讨厌的现象。根据我设置视点(相机位置)的方式,垂直 (z) 轴在左侧和右侧之间移动。这里有两个示例:示例 1,轴左,示例 2,轴右。第一个例子有 ax.view_init(25,-135) 而第二个例子有 ax.view_init(25,-45).
我希望保持相同的观点(查看数据的最佳方式)。有没有办法强制轴向一侧或另一侧?
我需要类似的东西:在两侧绘制 zaxis。感谢@crayzeewulf 的回答,我开始遵循以下解决方法(左侧、右侧或两侧):
首先根据需要绘制 3d,然后在调用
Wrapper Class 调用只是简单地将一些特征的可见性设置为 False,它绘制自身并最终绘制带有修改后的 PLANES 的 zaxis。这个 Wrapper 类允许您在左侧、右侧或两侧绘制 zaxis。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | 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() |
正如 OP 在下面的评论中指出的那样,下面建议的方法没有为原始问题提供足够的答案。
如本说明所述,axis3d 中有许多硬编码值,这使得自定义其行为变得困难。所以,我认为在当前的 API 中没有一个很好的方法来做到这一点。您可以通过修改
1 2 3 4 5 6 7 8 | tmp_planes = ax.zaxis._PLANES ax.zaxis._PLANES = ( tmp_planes[2], tmp_planes[3], tmp_planes[0], tmp_planes[1], tmp_planes[4], tmp_planes[5]) view_1 = (25, -135) view_2 = (25, -45) init_view = view_2 ax.view_init(*init_view) |
现在,无论您如何旋转图形,z 轴都将始终位于图形的左侧(只要 z 轴正方向向上)。 x 轴和 y 轴将继续翻转。您可以使用