8000 Merge pull request #18189 from tacaswell/fix_3370 · matplotlib/matplotlib@073ea22 · GitHub
[go: up one dir, main page]

Skip to content

Commit 073ea22

Browse files
authored
Merge pull request #18189 from tacaswell/fix_3370
FIX: Add get/set methods for 3D collections
2 parents 2486ba2 + 021dd9b commit 073ea22

File tree

3 files changed

+128
-9
lines changed

3 files changed

+128
-9
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
3D Collection properties are now modifiable
2+
-------------------------------------------
3+
4+
Previously, properties of a 3D Collection that were used for 3D effects (e.g.,
5+
colors were modified to produce depth shading) could not be changed after it
6+
was created.
7+
8+
Now it is possible to modify all properties of 3D Collections at any time.

lib/mpl_toolkits/mplot3d/art3d.py

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,32 @@ def __init__(self, *args, zs=0, zdir='z', depthshade=True, **kwargs):
435435
super().__init__(*args, **kwargs)
436436
self.set_3d_properties(zs, zdir)
437437

438+
def get_depthshade(self):
439+
return self._depthshade
440+
441+
def set_depthshade(self, depthshade):
442+
"""
443+
Set whether depth shading is performed on collection members.
444+
445+
Parameters
446+
----------
447+
depthshade : bool
448+
Whether to shade the patches in order to give the appearance of
449+
depth.
450+
"""
451+
self._depthshade = depthshade
452+
self.stale = True
453+
454+
def set_facecolor(self, c):
455+
# docstring inherited
456+
super().set_facecolor(c)
457+
self._facecolor3d = self.get_facecolor()
458+
459+
def set_edgecolor(self, c):
460+
# docstring inherited
461+
super().set_edgecolor(c)
462+
self._edgecolor3d = self.get_edgecolor()
463+
438464
def set_sort_zpos(self, val):
439465
"""Set the position to use for z-sorting."""
440466
self._sort_zpos = val
@@ -462,13 +488,13 @@ def do_3d_projection(self, renderer):
462488
fcs = (_zalpha(self._facecolor3d, vzs) if self._depthshade else
463489
self._facecolor3d)
464490
fcs = mcolors.to_rgba_array(fcs, self._alpha)
465-
self.set_facecolors(fcs)
491+
super().set_facecolor(fcs)
466492

467493
ecs = (_zalpha(self._edgecolor3d, vzs) if self._depthshade else
468494
self._edgecolor3d)
469495
ecs = mcolors.to_rgba_array(ecs, self._alpha)
470-
self.set_edgecolors(ecs)
471-
PatchCollection.set_offsets(self, np.column_stack([vxs, vys]))
496+
super().set_edgecolor(ecs)
497+
super().set_offsets(np.column_stack([vxs, vys]))
472498

473499
if vzs.size > 0:
474500
return min(vzs)
@@ -523,6 +549,42 @@ def set_3d_properties(self, zs, zdir):
523549
self._linewidth3d = self.get_linewidth()
524550
self.stale = True
525551

552+
def get_depthshade(self):
553+
return self._depthshade
554+
555+
def set_depthshade(self, depthshade):
556+
"""
557+
Set whether depth shading is performed on collection members.
558+
559+
Parameters
560+
----------
561+
depthshade : bool
562+
Whether to shade the patches in order to give the appearance of
563+
depth.
564+
"""
< 57AE /code>565+
self._depthshade = depthshade
566+
self.stale = True
567+
568+
def set_facecolor(self, c):
569+
# docstring inherited
570+
super().set_facecolor(c)
571+
self._facecolor3d = self.get_facecolor()
572+
573+
def set_edgecolor(self, c):
574+
# docstring inherited
575+
super().set_edgecolor(c)
576+
self._edgecolor3d = self.get_edgecolor()
577+
578+
def set_sizes(self, sizes, dpi=72.0):
579+
# docstring inherited
580+
super().set_sizes(sizes, dpi=dpi)
581+
self._sizes3d = self.get_sizes()
582+
583+
def set_linewidth(self, lw):
584+
# docstring inherited
585+
super().set_linewidth(lw)
586+
self._linewidth3d = self.get_linewidth()
587+
526588
def do_3d_projection(self, renderer):
527589
xs, ys, zs = self._offsets3d
528590
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
@@ -556,10 +618,10 @@ def do_3d_projection(self, renderer):
556618
fcs = mcolors.to_rgba_array(fcs, self._alpha)
557619
ecs = mcolors.to_rgba_array(ecs, self._alpha)
558620

559-
self.set_edgecolors(ecs)
560-
self.set_facecolors(fcs)
561-
self.set_sizes(sizes)
562-
self.set_linewidth(lws)
621+
super().set_edgecolor(ecs)
622+
super().set_facecolor(fcs)
623+
super().set_sizes(sizes)
624+
super().set_linewidth(lws)
563625

564626
PathCollection.set_offsets(self, vps)
565627

@@ -754,10 +816,12 @@ def do_3d_projection(self, renderer):
754816
return np.nan
755817

756818
def set_facecolor(self, colors):
819+
# docstring inherited
757820
super().set_facecolor(colors)
758821
self._facecolors3d = PolyCollection.get_facecolor(self)
759822

760823
def set_edgecolor(self, colors):
824+
# docstring inherited
761825
super().set_edgecolor(colors)
762826
self._edgecolors3d = PolyCollection.get_edgecolor(self)
763827

lib/mpl_toolkits/tests/test_mplot3d.py

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,27 @@ def test_scatter3d_color():
249249
color='b', marker='s')
250250

251251

252+
@check_figures_equal(extensions=['png'])
253+
def test_scatter3d_modification(fig_ref, fig_test):
254+
# Changing Path3DCollection properties post-creation should work correctly.
255+
ax_test = fig_test.add_subplot(projection='3d')
256+
c = ax_test.scatter(np.arange(10), np.arange(10), np.arange(10),
257+
marker='o')
258+
c.set_facecolor('C1')
259+
c.set_edgecolor('C2')
260+
c.set_alpha([0.3, 0.7] * 5)
261+
assert c.get_depthshade()
262+
c.set_depthshade(False)
263+
assert not c.get_depthshade()
264+
c.set_sizes(np.full(10, 75))
265+
c.set_linewidths(3)
266+
267+
ax_ref = fig_ref.add_subplot(projection='3d')
268+
ax_ref.scatter(np.arange(10), np.arange(10), np.arange(10), marker='o',
269+
facecolor='C1', edgecolor='C2', alpha=[0.3, 0.7] * 5,
270+
depthshade=False, s=75, linewidths=3)
271+
272+
252273
@pytest.mark.parametrize('depthshade', [True, False])
253274
@check_figures_equal(extensions=['png'])
254275
def test_scatter3d_sorting(fig_ref, fig_test, depthshade):
@@ -557,6 +578,30 @@ def test_quiver3d_masked():
557578
ax.quiver(x, y, z, u, v, w, length=0.1, pivot='tip', normalize=True)
558579

559580

581+
@check_figures_equal(extensions=['png'])
582+
def test_patch_collection_modification(fig_test, fig_ref):
583+
# Test that modifying Patch3DCollection properties after creation works.
584+
patch = Circle((0, 0), 0.05)
585+
c = art3d.Patch3DCollection([patch], linewidths=3)
586+
587+
ax_test = fig_test.add_subplot(projection='3d')
588+
ax_test.add_collection3d(c)
589+
c.set_edgecolor('C2')
590+
c.set_facecolor('C3')
591+
c.set_alpha(0.7)
592+
assert c.get_depthshade()
593+
c.set_depthshade(False)
594+
assert not c.get_depthshade()
595+
596+
patch = Circle((0, 0), 0.05)
597+
c = art3d.Patch3DCollection([patch], linewidths=3,
598+
edgecolor='C2', facecolor='C3', alpha=0.7,
599+
depthshade=False)
600+
601+
ax_ref = fig_ref.add_subplot(projection='3d')
602+
ax_ref.add_collection3d(c)
603+
604+
560605
@mpl3d_image_comparison(['poly3dcollection_closed.png'])
561606
def test_poly3dcollection_closed():
562607
fig = plt.figure()
@@ -589,8 +634,10 @@ def test_poly3dcollection_alpha():
589634
c1 = art3d.Poly3DCollection([poly1], linewidths=3, edgecolor='k',
590635
facecolor=(0.5, 0.5, 1), closed=True)
591636
c1.set_alpha(0.5)
592-
c2 = art3d.Poly3DCollection([poly2], linewidths=3, edgecolor='k',
593-
facecolor=(1, 0.5, 0.5), closed=False)
637+
c2 = art3d.Poly3DCollection([poly2], linewidths=3, closed=False)
638+
# Post-creation modification should work.
639+
c2.set_facecolor((1, 0.5, 0.5))
640+
c2.set_edgecolor('k')
594641
c2.set_alpha(0.5)
595642
ax.add_collection3d(c1)
596643
ax.add_collection3d(c2)

0 commit comments

Comments
 (0)
0