diff --git a/lib/mpl_toolkits/mplot3d/axes3d.py b/lib/mpl_toolkits/mplot3d/axes3d.py index bd96321aa26f..7c12877ec1c7 100644 --- a/lib/mpl_toolkits/mplot3d/axes3d.py +++ b/lib/mpl_toolkits/mplot3d/axes3d.py @@ -2158,7 +2158,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. @@ -2171,6 +2171,9 @@ def add_collection3d(self, col, zs=0, zdir='z'): - LineCollection - PatchCollection """ + + had_data = self.has_data() + zvals = np.atleast_1d(zs) zsortval = (np.min(zvals) if zvals.size else 0) # FIXME: arbitrary default @@ -2188,6 +2191,26 @@ 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) + # FIXME: Implement auto-scaling function for Patch3DCollection + # Currently unable to do so due to issues with Patch3DCollection + # See issue #14298 for details + + # Bounding box checks + # If a 2D collection was passed, it has been converted to 3D + + if autolim: + if type(col) is art3d.Line3DCollection: + # Calculate bounds of Line3DCollection + tSeg = np.array(col._segments3d) # Copy coordinates + # Auto-scale with start points + self.auto_scale_xyz(*tSeg[:, 0].transpose(), had_data=had_data) + # Auto-scale with end points + self.auto_scale_xyz(*tSeg[:, 1].transpose(), had_data=True) + + if type(col) is art3d.Poly3DCollection: + # Calculate bounds of poly collection + self.auto_scale_xyz(*col._vec[:-1], had_data=had_data) + 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 20bf16a37f56..1c4b5d04de6e 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 796151ae3ea6..95edd0f5ce84 100644 --- a/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py +++ b/lib/mpl_toolkits/mplot3d/tests/test_axes3d.py @@ -868,8 +868,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(): @@ -902,8 +902,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']) @@ -960,6 +960,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, 2)) + assert np.allclose(ax.get_ylim3d(), (0, 4)) + assert np.allclose(ax.get_zlim3d(), (0, 5)) + + +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]]) + coll = art3d.Poly3DCollection([poly]) + ax.add_collection3d(coll) + assert np.allclose(ax.get_xlim3d(), (0, 1)) + assert np.allclose(ax.get_ylim3d(), (0, 1)) + assert np.allclose(ax.get_zlim3d(), (0, 4)) + + @mpl3d_image_comparison(['axes3d_labelpad.png'], remove_text=False) def test_axes3d_labelpad(): fig = plt.figure()