diff --git a/galleries/examples/mplot3d/polys3d.py b/galleries/examples/mplot3d/polys3d.py index e6c51a2d8347..635c929908f6 100644 --- a/galleries/examples/mplot3d/polys3d.py +++ b/galleries/examples/mplot3d/polys3d.py @@ -30,7 +30,6 @@ poly = Poly3DCollection(verts, alpha=.7) ax.add_collection3d(poly) -ax.auto_scale_xyz(verts[:, :, 0], verts[:, :, 1], verts[:, :, 2]) ax.set_aspect('equalxy') plt.show() diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index 92a90b2f30ef..12f3682ae5e9 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -2738,7 +2738,7 @@ def tricontourf(self, *args, zdir='z', offset=None, **kwargs): self._auto_scale_contourf(X, Y, Z, zdir, levels, had_data) return cset - def add_collection3d(self, col, zs=0, zdir='z'): + def add_collection3d(self, col, zs=0, zdir='z', autolim=True): """ Add a 3D collection object to the plot. @@ -2750,8 +2750,21 @@ def add_collection3d(self, col, zs=0, zdir='z'): - `.PolyCollection` - `.LineCollection` - - `.PatchCollection` + - `.PatchCollection` (currently not supporting *autolim*) + + Parameters + ---------- + col : `.Collection` + A 2D collection object. + zs : float or array-like, default: 0 + The z-positions to be used for the 2D objects. + zdir : {'x', 'y', 'z'}, default: 'z' + The direction to use for the z-positions. + autolim : bool, default: True + Whether to update the data limits. """ + had_data = self.has_data() + zvals = np.atleast_1d(zs) zsortval = (np.min(zvals) if zvals.size else 0) # FIXME: arbitrary default @@ -2769,6 +2782,18 @@ def add_collection3d(self, col, zs=0, zdir='z'): art3d.patch_collection_2d_to_3d(col, zs=zs, zdir=zdir) col.set_sort_zpos(zsortval) + if autolim: + if isinstance(col, art3d.Line3DCollection): + self.auto_scale_xyz(*np.array(col._segments3d).transpose(), + had_data=had_data) + elif isinstance(col, art3d.Poly3DCollection): + self.auto_scale_xyz(*col._vec[:-1], had_data=had_data) + elif isinstance(col, art3d.Patch3DCollection): + pass + # FIXME: Implement auto-scaling function for Patch3DCollection + # Currently unable to do so due to issues with Patch3DCollection + # See https://github.com/matplotlib/matplotlib/issues/14298 for details + collection = super().add_collection(col) return collection diff --git a/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/voxels-named-colors.png b/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/voxels-named-colors.png index b71ad19c1608..33dfc2f2313a 100644 Binary files a/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/voxels-named-colors.png and b/lib/mpl_toolkits/mplot3d/tests/baseline_images/test_axes3d/voxels-named-colors.png differ diff --git a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py index 4d7acd83fbee..be988c31ee75 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -1004,8 +1004,8 @@ def test_poly3dcollection_closed(): facecolor=(0.5, 0.5, 1, 0.5), closed=True) c2 = art3d.Poly3DCollection([poly2], linewidths=3, edgecolor='k', facecolor=(1, 0.5, 0.5, 0.5), closed=False) - ax.add_collection3d(c1) - ax.add_collection3d(c2) + ax.add_collection3d(c1, autolim=False) + ax.add_collection3d(c2, autolim=False) def test_poly_collection_2d_to_3d_empty(): @@ -1038,8 +1038,8 @@ def test_poly3dcollection_alpha(): c2.set_facecolor((1, 0.5, 0.5)) c2.set_edgecolor('k') c2.set_alpha(0.5) - ax.add_collection3d(c1) - ax.add_collection3d(c2) + ax.add_collection3d(c1, autolim=False) + ax.add_collection3d(c2, autolim=False) @mpl3d_image_comparison(['add_collection3d_zs_array.png'], style='mpl20') @@ -1098,6 +1098,32 @@ def test_add_collection3d_zs_scalar(): ax.set_zlim(0, 2) +def test_line3dCollection_autoscaling(): + fig = plt.figure() + ax = fig.add_subplot(projection='3d') + + lines = [[(0, 0, 0), (1, 4, 2)], + [(1, 1, 3), (2, 0, 2)], + [(1, 0, 4), (1, 4, 5)]] + + lc = art3d.Line3DCollection(lines) + ax.add_collection3d(lc) + assert np.allclose(ax.get_xlim3d(), (-0.041666666666666664, 2.0416666666666665)) + assert np.allclose(ax.get_ylim3d(), (-0.08333333333333333, 4.083333333333333)) + assert np.allclose(ax.get_zlim3d(), (-0.10416666666666666, 5.104166666666667)) + + +def test_poly3dCollection_autoscaling(): + fig = plt.figure() + ax = fig.add_subplot(projection='3d') + poly = np.array([[0, 0, 0], [1, 1, 3], [1, 0, 4]]) + col = art3d.Poly3DCollection([poly]) + ax.add_collection3d(col) + assert np.allclose(ax.get_xlim3d(), (-0.020833333333333332, 1.0208333333333333)) + assert np.allclose(ax.get_ylim3d(), (-0.020833333333333332, 1.0208333333333333)) + assert np.allclose(ax.get_zlim3d(), (-0.0833333333333333, 4.083333333333333)) + + @mpl3d_image_comparison(['axes3d_labelpad.png'], remove_text=False, style='mpl20') def test_axes3d_labelpad():