@@ -295,7 +295,7 @@ def pathpatch_2d_to_3d(pathpatch, z=0, zdir='z'):
295295 pathpatch .__class__ = PathPatch3D
296296 pathpatch .set_3d_properties (mpath , z , zdir )
297297
298- class Collection3D ( object ):
298+ class Patch3DCollection ( PatchCollection ):
299299 '''
300300 A collection of 3D patches.
301301 '''
@@ -319,8 +319,7 @@ def __init__(self, *args, **kwargs):
319319 zs = kwargs .pop ('zs' , 0 )
320320 zdir = kwargs .pop ('zdir' , 'z' )
321321 self ._depthshade = kwargs .pop ('depthshade' , True )
322- PatchCollection .__init__ (self , * args , ** kwargs )
323- self ._old_draw = lambda x : PatchCollection .draw (self , x )
322+ super (self .__class__ , self ).__init__ (* args , ** kwargs )
324323 self .set_3d_properties (zs , zdir )
325324
326325
@@ -362,16 +361,72 @@ def do_3d_projection(self, renderer):
362361 else :
363362 return np .nan
364363
365- def draw (self , renderer ):
366- self ._old_draw (renderer )
367364
365+ class Path3DCollection (PathCollection ):
366+ '''
367+ A collection of 3D paths.
368+ '''
369+
370+ def __init__ (self , * args , ** kwargs ):
371+ """
372+ Create a collection of flat 3D paths with its normal vector
373+ pointed in *zdir* direction, and located at *zs* on the *zdir*
374+ axis. 'zs' can be a scalar or an array-like of the same length as
375+ the number of paths in the collection.
376+
377+ Constructor arguments are the same as for
378+ :class:`~matplotlib.collections.PathCollection`. In addition,
379+ keywords *zs=0* and *zdir='z'* are available.
380+
381+ Also, the keyword argument "depthshade" is available to
382+ indicate whether or not to shade the patches in order to
383+ give the appearance of depth (default is *True*).
384+ This is typically desired in scatter plots.
385+ """
386+ zs = kwargs .pop ('zs' , 0 )
387+ zdir = kwargs .pop ('zdir' , 'z' )
388+ self ._depthshade = kwargs .pop ('depthshade' , True )
389+ super (self .__class__ , self ).__init__ (* args , ** kwargs )
390+ self .set_3d_properties (zs , zdir )
391+
392+
393+ def set_sort_zpos (self ,val ):
394+ '''Set the position to use for z-sorting.'''
395+ self ._sort_zpos = val
396+
397+ def set_3d_properties (self , zs , zdir ):
398+ # Force the collection to initialize the face and edgecolors
399+ # just in case it is a scalarmappable with a colormap.
400+ self .update_scalarmappable ()
401+ offsets = self .get_offsets ()
402+ if len (offsets ) > 0 :
403+ xs , ys = list (zip (* offsets ))
404+ else :
405+ xs = []
406+ ys = []
407+ self ._offsets3d = juggle_axes (xs , ys , np .atleast_1d (zs ), zdir )
408+ self ._facecolor3d = self .get_facecolor ()
409+ self ._edgecolor3d = self .get_edgecolor ()
410+
411+ def do_3d_projection (self , renderer ):
412+ xs , ys , zs = self ._offsets3d
413+ vxs , vys , vzs , vis = proj3d .proj_transform_clip (xs , ys , zs , renderer .M )
368414
369- class Patch3DCollection (Collection3D , PatchCollection ):
370- pass
415+ fcs = (zalpha (self ._facecolor3d , vzs ) if self ._depthshade else
416+ self ._facecolor3d )
417+ fcs = mcolors .colorConverter .to_rgba_array (fcs , self ._alpha )
418+ self .set_facecolors (fcs )
371419
420+ ecs = (zalpha (self ._edgecolor3d , vzs ) if self ._depthshade else
421+ self ._edgecolor3d )
422+ ecs = mcolors .colorConverter .to_rgba_array (ecs , self ._alpha )
423+ self .set_edgecolors (ecs )
424+ super (self .__class__ , self ).set_offsets (list (zip (vxs , vys )))
372425
373- class Path3DCollection (Collection3D , PathCollection ):
374- pass
426+ if vzs .size > 0 :
427+ return min (vzs )
428+ else :
429+ return np .nan
375430
376431
377432def patch_collection_2d_to_3d (col , zs = 0 , zdir = 'z' , depthshade = True ):
@@ -386,14 +441,9 @@ def patch_collection_2d_to_3d(col, zs=0, zdir='z', depthshade=True):
386441 collection along the *zdir* axis. Defaults to 0.
387442 *zdir* The axis in which to place the patches. Default is "z".
388443 *depthshade* Whether to shade the patches to give a sense of depth.
389- Defaults to *True*.
390-
444+ Defaults to *True*.
391445
392446 """
393- # The tricky part here is that there are several classes that are
394- # derived from PatchCollection. We need to use the right draw method.
395- col ._old_draw = col .draw
396-
397447 if isinstance (col , PathCollection ):
398448 col .__class__ = Path3DCollection
399449 elif isinstance (col , PatchCollection ):
0 commit comments