def set_axes_equal(ax: Axes): """ Make axes of 3D plot have equal scale so that spheres appear as spheres, cubes as cubes, etc.. This is one possible solution to Matplotlib's ax.set_aspect('equal') and ax.axis('equal') not working for 3D. Ref: https://github.com/borglab/gtsam/blob/develop/python/gtsam/utils/plot.py#L13 Args: ax: axis for the plot. """ # get the min and max value for each of (x, y, z) axes as 3x2 matrix. # This gives us the bounds of the minimum volume cuboid encapsulating all # data. limits = np.array([ax.get_xlim3d(), ax.get_ylim3d(), ax.get_zlim3d()]) # find the centroid of the cuboid centroid = np.mean(limits, axis=1) # pick the largest edge length for this cuboid largest_edge_length = np.max(np.abs(limits[:, 1] - limits[:, 0])) # set new limits to draw a cube using the largest edge length radius = 0.5 * largest_edge_length ax.set_xlim3d([centroid[0] - radius, centroid[0] + radius]) ax.set_ylim3d([centroid[1] - radius, centroid[1] + radius]) ax.set_zlim3d([centroid[2] - radius, centroid[2] + radius])
def axes_equal(axes: Axes): """Adjust axis in a 3d plot to be equally scaled. Source code taken from the stackoverflow answer of 'karlo' in the following question: https://stackoverflow.com/questions/13685386/matplotlib-equal-unit -length-with-equal-aspect-ratio-z-axis-is-not-equal-to Parameters ---------- axes : Matplotlib axes object (output from plt.gca()) """ x_limits = axes.get_xlim3d() y_limits = axes.get_ylim3d() z_limits = axes.get_zlim3d() x_range = abs(x_limits[1] - x_limits[0]) x_middle = np.mean(x_limits) y_range = abs(y_limits[1] - y_limits[0]) y_middle = np.mean(y_limits) z_range = abs(z_limits[1] - z_limits[0]) z_middle = np.mean(z_limits) # The plot bounding box is a sphere in the sense of the infinity # norm, hence I call half the max range the plot radius. plot_radius = 0.5 * max([x_range, y_range, z_range]) axes.set_xlim3d([x_middle - plot_radius, x_middle + plot_radius]) axes.set_ylim3d([y_middle - plot_radius, y_middle + plot_radius]) axes.set_zlim3d([z_middle - plot_radius, z_middle + plot_radius])