Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2db6a04

Browse files
authored
Merge pull request #14508 from kentcr/axes3d-force-zorder
Add force_zorder parameter
2 parents 69edfa2 + a65c7b8 commit 2db6a04

File tree

4 files changed

+121
-20
lines changed

4 files changed

+121
-20
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
Axes3D now allows manual control of draw order
2+
----------------------------------------------
3+
4+
The :class:`~mpl_toolkits.mplot3d.axes3d.Axes3D` class now has
5+
``computed_zorder`` parameter. When set to False, Artists are drawn using their
6+
``zorder`` attribute.

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 32 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Axes3D(Axes):
4949
def __init__(
5050
self, fig, rect=None, *args,
5151
azim=-60, elev=30, sharez=None, proj_type='persp',
52-
box_aspect=None,
52+
box_aspect=None, computed_zorder=True,
5353
**kwargs):
5454
"""
5555
Parameters
@@ -66,6 +66,15 @@ def __init__(
6666
Other axes to share z-limits with.
6767
proj_type : {'persp', 'ortho'}
6868
The projection type, default 'persp'.
69+
computed_zorder : bool, default: True
70+
If True, the draw order is computed based on the average position
71+
of the `.Artist`s along the view direction.
72+
Set to False if you want to manually control the order in which
73+
Artists are drawn on top of each other using their *zorder*
74+
attribute. This can be used for fine-tuning if the automatic order
75+
does not produce the desired result. Note however, that a manual
76+
zorder will only be correct for a limited view angle. If the figure
77+
is rotated by the user, it will look wrong from certain angles.
6978
auto_add_to_figure : bool, default: True
7079
Prior to Matplotlib 3.4 Axes3D would add themselves
7180
to their host Figure on init. Other Axes class do not
@@ -79,11 +88,6 @@ def __init__(
7988
Other optional keyword arguments:
8089
8190
%(Axes3D_kwdoc)s
82-
83-
Notes
84-
-----
85-
.. versionadded:: 1.2.1
86-
The *sharez* parameter.
8791
"""
8892

8993
if rect is None:
@@ -92,6 +96,7 @@ def __init__(
9296
self.initial_azim = azim
9397
self.initial_elev = elev
9498
self.set_proj_type(proj_type)
99+
self.computed_zorder = computed_zorder
95100

96101
self.xy_viewLim = Bbox.unit()
97102
self.zz_viewLim = Bbox.unit()
@@ -477,20 +482,26 @@ def do_3d_projection(artist):
477482
"%(since)s and will be removed %(removal)s.")
478483
return artist.do_3d_projection(renderer)
479484

480-
# Calculate projection of collections and patches and zorder them.
481-
# Make sure they are drawn above the grids.
482-
zorder_offset = max(axis.get_zorder()
483-
for axis in self._get_axis_list()) + 1
484-
for i, col in enumerate(
485-
sorted(self.collections,
486-
key=do_3d_projection,
487-
reverse=True)):
488-
col.zorder = zorder_offset + i
489-
for i, patch in enumerate(
490-
sorted(self.patches,
491-
key=do_3d_projection,
492-
reverse=True)):
493-
patch.zorder = zorder_offset + i
485+
if self.computed_zorder:
486+
# Calculate projection of collections and patches and zorder
487+
# them. Make sure they are drawn above the grids.
488+
zorder_offset = max(axis.get_zorder()
489+
for axis in self._get_axis_list()) + 1
490+
for i, col in enumerate(
491+
sorted(self.collections,
492+
key=do_3d_projection,
493+
reverse=True)):
494+
col.zorder = zorder_offset + i
495+
for i, patch in enumerate(
496+
sorted(self.patches,
497+
key=do_3d_projection,
498+
reverse=True)):
499+
patch.zorder = zorder_offset + i
500+
else:
501+
for col in self.collections:
502+
col.do_3d_projection()
503+
for patch in self.patches:
504+
patch.do_3d_projection()
494505

495506
if self._axis3don:
496507
# Draw panes first
@@ -3505,6 +3516,7 @@ def stem(self, x, y, z, *, linefmt='C0-', markerfmt='C0o', basefmt='C3-',
35053516

35063517
stem3D = stem
35073518

3519+
35083520
docstring.interpd.update(Axes3D_kwdoc=artist.kwdoc(Axes3D))
35093521
docstring.dedent_interpd(Axes3D.__init__)
35103522

lib/mpl_toolkits/tests/test_mplot3d.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,3 +1425,86 @@ def test_subfigure_simple():
14251425
sf = fig.subfigures(1, 2)
14261426
ax = sf[0].add_subplot(1, 1, 1, projection='3d')
14271427
ax = sf[1].add_subplot(1, 1, 1, projection='3d', label='other')
1428+
1429+
1430+
@image_comparison(baseline_images=['computed_zorder'], remove_text=True,
1431+
extensions=['png'])
1432+
def test_computed_zorder():
1433+
fig = plt.figure()
1434+
ax1 = fig.add_subplot(221, projection='3d')
1435+
ax2 = fig.add_subplot(222, projection='3d')
1436+
ax2.computed_zorder = False
1437+
1438+
# create a horizontal plane
1439+
corners = ((0, 0, 0), (0, 5, 0), (5, 5, 0), (5, 0, 0))
1440+
for ax in (ax1, ax2):
1441+
tri = art3d.Poly3DCollection([corners],
1442+
facecolors='white',
1443+
edgecolors='black',
1444+
zorder=1)
1445+
ax.add_collection3d(tri)
1446+
1447+
# plot a vector
1448+
ax.plot((2, 2), (2, 2), (0, 4), c='red', zorder=2)
1449+
1450+
# plot some points
1451+
ax.scatter((3, 3), (1, 3), (1, 3), c='red', zorder=10)
1452+
1453+
ax.set_xlim((0, 5.0))
1454+
ax.set_ylim((0, 5.0))
1455+
ax.set_zlim((0, 2.5))
1456+
1457+
ax3 = fig.add_subplot(223, projection='3d')
1458+
ax4 = fig.add_subplot(224, projection='3d')
1459+
ax4.computed_zorder = False
1460+
1461+
dim = 10
1462+
X, Y = np.meshgrid((-dim, dim), (-dim, dim))
1463+
Z = np.zeros((2, 2))
1464+
1465+
angle = 0.5
1466+
X2, Y2 = np.meshgrid((-dim, dim), (0, dim))
1467+
Z2 = Y2 * angle
1468+
X3, Y3 = np.meshgrid((-dim, dim), (-dim, 0))
1469+
Z3 = Y3 * angle
1470+
1471+
r = 7
1472+
M = 1000
1473+
th = np.linspace(0, 2 * np.pi, M)
1474+
x, y, z = r * np.cos(th), r * np.sin(th), angle * r * np.sin(th)
1475+
for ax in (ax3, ax4):
1476+
ax.plot_surface(X2, Y3, Z3,
1477+
color='blue',
1478+
alpha=0.5,
1479+
linewidth=0,
1480+
zorder=-1)
1481+
ax.plot(x[y < 0], y[y < 0], z[y < 0],
1482+
lw=5,
1483+
linestyle='--',
1484+
color='green',
1485+
zorder=0)
1486+
1487+
ax.plot_surface(X, Y, Z,
1488+
color='red',
1489+
alpha=0.5,
1490+
linewidth=0,
1491+
zorder=1)
1492+
1493+
ax.plot(r * np.sin(th), r * np.cos(th), np.zeros(M),
1494+
lw=5,
1495+
linestyle='--',
1496+
color='black',
1497+
zorder=2)
1498+
1499+
ax.plot_surface(X2, Y2, Z2,
1500+
color='blue',
1501+
alpha=0.5,
1502+
linewidth=0,
1503+
zorder=3)
1504+
1505+
ax.plot(x[y > 0], y[y > 0], z[y > 0], lw=5,
1506+
linestyle='--',
1507+
color='green',
1508+
zorder=4)
1509+
ax.view_init(azim=-20, elev=20)
1510+
ax.axis('off')

0 commit comments

Comments
 (0)