Skip to content

Commit 0d54829

Browse files
committed
Merge pull request #3211 from WeatherGod/mplot3d/depthshade
Mplot3d/depthshade
2 parents 2d43258 + 923272f commit 0d54829

File tree

2 files changed

+65
-8
lines changed

2 files changed

+65
-8
lines changed

lib/mpl_toolkits/mplot3d/art3d.py

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
from six.moves import zip
1515

1616
from matplotlib import lines, text as mtext, path as mpath, colors as mcolors
17+
from matplotlib import artist
1718
from matplotlib.collections import Collection, LineCollection, \
1819
PolyCollection, PatchCollection, PathCollection
1920
from matplotlib.cm import ScalarMappable
@@ -310,9 +311,14 @@ def __init__(self, *args, **kwargs):
310311
:class:`~matplotlib.collections.PatchCollection`. In addition,
311312
keywords *zs=0* and *zdir='z'* are available.
312313
314+
Also, the keyword argument "depthshade" is available to
315+
indicate whether or not to shade the patches in order to
316+
give the appearance of depth (default is *True*).
317+
This is typically desired in scatter plots.
313318
"""
314319
zs = kwargs.pop('zs', 0)
315320
zdir = kwargs.pop('zdir', 'z')
321+
self._depthshade = kwargs.pop('depthshade', True)
316322
PatchCollection.__init__(self, *args, **kwargs)
317323
self._old_draw = lambda x: PatchCollection.draw(self, x)
318324
self.set_3d_properties(zs, zdir)
@@ -339,10 +345,16 @@ def set_3d_properties(self, zs, zdir):
339345
def do_3d_projection(self, renderer):
340346
xs, ys, zs = self._offsets3d
341347
vxs, vys, vzs, vis = proj3d.proj_transform_clip(xs, ys, zs, renderer.M)
342-
#FIXME: mpl allows us no way to unset the collection alpha value
343-
self._alpha = None
344-
self.set_facecolors(zalpha(self._facecolor3d, vzs))
345-
self.set_edgecolors(zalpha(self._edgecolor3d, vzs))
348+
349+
fcs = (zalpha(self._facecolor3d, vzs) if self._depthshade else
350+
self._facecolor3d)
351+
fcs = mcolors.colorConverter.to_rgba_array(fcs, self._alpha)
352+
self.set_facecolors(fcs)
353+
354+
ecs = (zalpha(self._edgecolor3d, vzs) if self._depthshade else
355+
self._edgecolor3d)
356+
ecs = mcolors.colorConverter.to_rgba_array(ecs, self._alpha)
357+
self.set_edgecolors(ecs)
346358
super(self.__class__, self).set_offsets(list(zip(vxs, vys)))
347359

348360
if vzs.size > 0 :
@@ -362,9 +374,22 @@ class Path3DCollection(Collection3D, PathCollection):
362374
pass
363375

364376

365-
def patch_collection_2d_to_3d(col, zs=0, zdir='z'):
366-
"""Convert a PatchCollection to a Patch3DCollection object."""
377+
def patch_collection_2d_to_3d(col, zs=0, zdir='z', depthshade=True):
378+
"""
379+
Convert a :class:`~matplotlib.collections.PatchCollection` into a
380+
:class:`Patch3DCollection` object
381+
(or a :class:`~matplotlib.collections.PathCollection` into a
382+
:class:`Path3DCollection` object).
383+
384+
Keywords:
385+
*za* The location or locations to place the patches in the
386+
collection along the *zdir* axis. Defaults to 0.
387+
*zdir* The axis in which to place the patches. Default is "z".
388+
*depthshade* Whether to shade the patches to give a sense of depth.
389+
Defaults to *True*.
390+
367391
392+
"""
368393
# The tricky part here is that there are several classes that are
369394
# derived from PatchCollection. We need to use the right draw method.
370395
col._old_draw = col.draw
@@ -373,6 +398,7 @@ def patch_collection_2d_to_3d(col, zs=0, zdir='z'):
373398
col.__class__ = Path3DCollection
374399
elif isinstance(col, PatchCollection):
375400
col.__class__ = Patch3DCollection
401+
col._depthshade = depthshade
376402
col.set_3d_properties(zs, zdir)
377403

378404
class Poly3DCollection(PolyCollection):
@@ -461,6 +487,7 @@ def set_3d_properties(self):
461487
self.set_zsort(True)
462488
self._facecolors3d = PolyCollection.get_facecolors(self)
463489
self._edgecolors3d = PolyCollection.get_edgecolors(self)
490+
self._alpha3d = PolyCollection.get_alpha(self)
464491

465492
def set_sort_zpos(self,val):
466493
'''Set the position to use for z-sorting.'''
@@ -529,6 +556,30 @@ def set_edgecolor(self, colors):
529556
self._edgecolors3d = PolyCollection.get_edgecolor(self)
530557
set_edgecolors = set_edgecolor
531558

559+
def set_alpha(self, alpha):
560+
"""
561+
Set the alpha tranparencies of the collection. *alpha* must be
562+
a float or *None*.
563+
564+
ACCEPTS: float or None
565+
"""
566+
if alpha is not None:
567+
try:
568+
float(alpha)
569+
except TypeError:
570+
raise TypeError('alpha must be a float or None')
571+
artist.Artist.set_alpha(self, alpha)
572+
try:
573+
self._facecolors = mcolors.colorConverter.to_rgba_array(
574+
self._facecolors3d, self._alpha)
575+
except (AttributeError, TypeError, IndexError):
576+
pass
577+
try:
578+
self._edgecolors = mcolors.colorConverter.to_rgba_array(
579+
self._edgecolors3d, self._alpha)
580+
except (AttributeError, TypeError, IndexError):
581+
pass
582+
532583
def get_facecolors(self):
533584
return self._facecolors2d
534585
get_facecolor = get_facecolors

lib/mpl_toolkits/mplot3d/axes3d.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,7 +2176,8 @@ def add_collection3d(self, col, zs=0, zdir='z'):
21762176

21772177
Axes.add_collection(self, col)
21782178

2179-
def scatter(self, xs, ys, zs=0, zdir='z', s=20, c='b', *args, **kwargs):
2179+
def scatter(self, xs, ys, zs=0, zdir='z', s=20, c='b', depthshade=True,
2180+
*args, **kwargs):
21802181
'''
21812182
Create a scatter plot.
21822183
@@ -2200,6 +2201,10 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c='b', *args, **kwargs):
22002201
sequence because that is indistinguishable from an array
22012202
of values to be colormapped. *c* can be a 2-D array in
22022203
which the rows are RGB or RGBA, however.
2204+
2205+
*depthshade*
2206+
Whether or not to shade the scatter markers to give the
2207+
appearance of depth. Default is *True*.
22032208
========== ==========================================================
22042209
22052210
Keyword arguments are passed on to
@@ -2238,7 +2243,8 @@ def scatter(self, xs, ys, zs=0, zdir='z', s=20, c='b', *args, **kwargs):
22382243
zs = np.ones(len(xs)) * zs
22392244
else:
22402245
is_2d = False
2241-
art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir)
2246+
art3d.patch_collection_2d_to_3d(patches, zs=zs, zdir=zdir,
2247+
depthshade=depthshade)
22422248

22432249
if self._zmargin < 0.05 and xs.size > 0:
22442250
self.set_zmargin(0.05)

0 commit comments

Comments
 (0)