以下内容参考@karlo的回答,为了让事情更加简洁:
def set_axes_equal(ax: plt.Axes):
"""Set 3D plot axes to equal scale.
Make axes of 3D plot have equal scale so that spheres appear as
spheres and cubes as cubes. Required since `ax.axis('equal')`
and `ax.set_aspect('equal')` don't work on 3D.
"""
limits = np.array([
ax.get_xlim3d(),
ax.get_ylim3d(),
ax.get_zlim3d(),
])
origin = np.mean(limits, axis=1)
radius = 0.5 * np.max(np.abs(limits[:, 1] - limits[:, 0]))
_set_axes_radius(ax, origin, radius)
def _set_axes_radius(ax, origin, radius):
x, y, z = origin
ax.set_xlim3d([x - radius, x + radius])
ax.set_ylim3d([y - radius, y + radius])
ax.set_zlim3d([z - radius, z + radius])
用法:
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.set_aspect('equal')
set_axes_equal(ax)
plt.show()
编辑:由于在pull-request #13474
中合并的更改,本回答不适用于更新版本的Matplotlib,该更改已在issue #17172
和issue #1077
中跟踪。作为一种临时解决方法,可以删除lib/matplotlib/axes/_base.py
中新添加的行:
class _AxesBase(martist.Artist):
...
def set_aspect(self, aspect, adjustable=None, anchor=None, share=False):
...
+ if (not cbook._str_equal(aspect, 'auto')) and self.name == '3d':
+ raise NotImplementedError(
+ 'It is not currently possible to manually set the aspect '
+ 'on 3D axes')
set_box_aspect()
。请参见以下更新的答案。 - bertset_box_aspect
函数可以在matplotlib 3.3.0及以后版本中工作。 - karlo