@@ -295,7 +295,7 @@ def pathpatch_2d_to_3d(pathpatch, z=0, zdir='z'):
295
295
pathpatch .__class__ = PathPatch3D
296
296
pathpatch .set_3d_properties (mpath , z , zdir )
297
297
298
- class Collection3D ( object ):
298
+ class Patch3DCollection ( PatchCollection ):
299
299
'''
300
300
A collection of 3D patches.
301
301
'''
@@ -319,8 +319,7 @@ def __init__(self, *args, **kwargs):
319
319
zs = kwargs .pop ('zs' , 0 )
320
320
zdir = kwargs .pop ('zdir' , 'z' )
321
321
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 )
324
323
self .set_3d_properties (zs , zdir )
325
324
326
325
@@ -362,16 +361,72 @@ def do_3d_projection(self, renderer):
362
361
else :
363
362
return np .nan
364
363
365
- def draw (self , renderer ):
366
- self ._old_draw (renderer )
367
364
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 )
368
414
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 )
371
419
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 )))
372
425
373
- class Path3DCollection (Collection3D , PathCollection ):
374
- pass
426
+ if vzs .size > 0 :
427
+ return min (vzs )
428
+ else :
429
+ return np .nan
375
430
376
431
377
432
def 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):
386
441
collection along the *zdir* axis. Defaults to 0.
387
442
*zdir* The axis in which to place the patches. Default is "z".
388
443
*depthshade* Whether to shade the patches to give a sense of depth.
389
- Defaults to *True*.
390
-
444
+ Defaults to *True*.
391
445
392
446
"""
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
-
397
447
if isinstance (col , PathCollection ):
398
448
col .__class__ = Path3DCollection
399
449
elif isinstance (col , PatchCollection ):
0 commit comments