14
14
from six .moves import zip
15
15
16
16
from matplotlib import lines , text as mtext , path as mpath , colors as mcolors
17
+ from matplotlib import artist
17
18
from matplotlib .collections import Collection , LineCollection , \
18
19
PolyCollection , PatchCollection , PathCollection
19
20
from matplotlib .cm import ScalarMappable
@@ -310,9 +311,14 @@ def __init__(self, *args, **kwargs):
310
311
:class:`~matplotlib.collections.PatchCollection`. In addition,
311
312
keywords *zs=0* and *zdir='z'* are available.
312
313
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.
313
318
"""
314
319
zs = kwargs .pop ('zs' , 0 )
315
320
zdir = kwargs .pop ('zdir' , 'z' )
321
+ self ._depthshade = kwargs .pop ('depthshade' , True )
316
322
PatchCollection .__init__ (self , * args , ** kwargs )
317
323
self ._old_draw = lambda x : PatchCollection .draw (self , x )
318
324
self .set_3d_properties (zs , zdir )
@@ -339,10 +345,16 @@ def set_3d_properties(self, zs, zdir):
339
345
def do_3d_projection (self , renderer ):
340
346
xs , ys , zs = self ._offsets3d
341
347
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 )
346
358
super (self .__class__ , self ).set_offsets (list (zip (vxs , vys )))
347
359
348
360
if vzs .size > 0 :
@@ -362,9 +374,22 @@ class Path3DCollection(Collection3D, PathCollection):
362
374
pass
363
375
364
376
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
+
367
391
392
+ """
368
393
# The tricky part here is that there are several classes that are
369
394
# derived from PatchCollection. We need to use the right draw method.
370
395
col ._old_draw = col .draw
@@ -373,6 +398,7 @@ def patch_collection_2d_to_3d(col, zs=0, zdir='z'):
373
398
col .__class__ = Path3DCollection
374
399
elif isinstance (col , PatchCollection ):
375
400
col .__class__ = Patch3DCollection
401
+ col ._depthshade = depthshade
376
402
col .set_3d_properties (zs , zdir )
377
403
378
404
class Poly3DCollection (PolyCollection ):
@@ -461,6 +487,7 @@ def set_3d_properties(self):
461
487
self .set_zsort (True )
462
488
self ._facecolors3d = PolyCollection .get_facecolors (self )
463
489
self ._edgecolors3d = PolyCollection .get_edgecolors (self )
490
+ self ._alpha3d = PolyCollection .get_alpha (self )
464
491
465
492
def set_sort_zpos (self ,val ):
466
493
'''Set the position to use for z-sorting.'''
@@ -529,6 +556,30 @@ def set_edgecolor(self, colors):
529
556
self ._edgecolors3d = PolyCollection .get_edgecolor (self )
530
557
set_edgecolors = set_edgecolor
531
558
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
+
67F4
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
+
532
583
def get_facecolors (self ):
533
584
return self ._facecolors2d
534
585
get_facecolor = get_facecolors
0 commit comments