1010from matplotlib import lines , text as mtext , path as mpath , colors as mcolors
1111from matplotlib .collections import Collection , LineCollection , \
1212 PolyCollection , PatchCollection
13+ from matplotlib .cm import ScalarMappable
1314from matplotlib .patches import Patch
1415from matplotlib .colors import Normalize
1516from matplotlib .cbook import iterable
@@ -111,26 +112,30 @@ def line_2d_to_3d(line, zs=0, zdir='z'):
111112 line .__class__ = Line3D
112113 line .set_3d_properties (zs , zdir )
113114
114- def path_to_3d_segment (path , z = 0 , zdir = 'z' ):
115+ def path_to_3d_segment (path , zs = 0 , zdir = 'z' ):
115116 '''Convert a path to a 3D segment.'''
117+
118+ if not iterable (zs ):
119+ zs = [zs ] * len (path )
120+
116121 seg = []
117- for (pathseg , code ) in path .iter_segments ():
118- seg .append (pathseg )
119- seg3d = [juggle_axes (x , y , z , zdir ) for (x , y ) in seg ]
122+ pathsegs = path .iter_segments (simplify = False , curves = False )
123+ for (((x , y ), code ), z ) in zip (pathsegs , zs ):
124+ seg .append ((x , y , z ))
125+ seg3d = [juggle_axes (x , y , z , zdir ) for (x , y , z ) in seg ]
120126 return seg3d
121127
122128def paths_to_3d_segments (paths , zs = 0 , zdir = 'z' ):
123- '''Convert paths from a collection object to 3D segments.'''
129+ '''
130+ Convert paths from a collection object to 3D segments.
131+ '''
124132
125- try :
126- zs = float (zs )
133+ if not iterable (zs ):
127134 zs = [zs ] * len (paths )
128- except :
129- pass
130135
131136 segments = []
132- for path , z in zip (paths , zs ):
133- segments .append (path_to_3d_segment (path , z , zdir ))
137+ for path , pathz in zip (paths , zs ):
138+ segments .append (path_to_3d_segment (path , pathz , zdir ))
134139 return segments
135140
136141class Line3DCollection (LineCollection ):
@@ -255,8 +260,17 @@ class Poly3DCollection(PolyCollection):
255260 '''
256261
257262 def __init__ (self , verts , * args , ** kwargs ):
263+ '''
264+ Create a Poly3DCollection.
265+
266+ *verts* should contain 3D coordinates.
267+
268+ Note that this class does a bit of magic with the _facecolors
269+ and _edgecolors properties.
270+ '''
271+
258272 PolyCollection .__init__ (self , verts , * args , ** kwargs )
259- self .set_3d_properties ()
273+ self ._zsort = 1
260274
261275 def get_vector (self , segments3d ):
262276 """Optimize points for projection"""
@@ -276,47 +290,81 @@ def get_vector(self, segments3d):
276290 self ._sort_zpos = min (zs )
277291
278292 def set_verts (self , verts , closed = True ):
293+ '''Set 3D vertices.'''
279294 self .get_vector (verts )
280295 # 2D verts will be updated at draw time
281296 PolyCollection .set_verts (self , [], closed )
282297
283298 def set_3d_properties (self ):
284299 self ._zsort = 1
285300 self ._facecolors3d = PolyCollection .get_facecolors (self )
286- self ._edgecolors3d = self .get_edgecolors ()
301+ self ._edgecolors3d = PolyCollection .get_edgecolors (self )
287302
288303 def do_3d_projection (self , renderer ):
304+ '''
305+ Perform the 3D projection for this object.
306+ '''
307+
308+ if self ._A is not None :
309+ self .update_scalarmappable ()
310+ self ._facecolors3d = self ._facecolors
311+
289312 txs , tys , tzs = proj3d .proj_transform_vec (self ._vec , renderer .M )
290313 xyzlist = [(txs [si :ei ], tys [si :ei ], tzs [si :ei ]) \
291314 for si , ei in self ._segis ]
292- colors = self ._facecolors3d
315+
316+ # This extra fuss is to re-order face / edge colors
317+ cface = self ._facecolors3d
318+ if len (self ._edgecolors3d ) != len (cface ):
319+ cedge = cface
320+ else :
321+ cedge = self ._edgecolors3d
293322
294323 # if required sort by depth (furthest drawn first)
295324 if self ._zsort :
296- z_segments_2d = [(min (zs ), zip (xs , ys ), c ) for
297- (xs , ys , zs ), c in zip (xyzlist , colors )]
325+ z_segments_2d = [(min (zs ), zip (xs , ys ), fc , ec ) for
326+ (xs , ys , zs ), fc , ec in zip (xyzlist , cface , cedge )]
298327 z_segments_2d .sort ()
299328 z_segments_2d .reverse ()
300329 else :
301330 raise ValueError , "whoops"
302- segments_2d = [ s for z , s , c in z_segments_2d ]
303- colors = [c for z , s , c in z_segments_2d ]
331+
332+ segments_2d = [s for z , s , fc , ec in z_segments_2d ]
304333 PolyCollection .set_verts (self , segments_2d )
305- self ._facecolors2d = colors
334+
335+ self ._facecolors2d = [fc for z , s , fc , ec in z_segments_2d ]
336+ if len (self ._edgecolors3d ) == len (cface ):
337+ self ._edgecolors2d = [ec for z , s , fc , ec in z_segments_2d ]
338+ else :
339+ self ._edgecolors2d = self ._edgecolors3d
306340
307341 # Return zorder value
308342 zvec = np .array ([[0 ], [0 ], [self ._sort_zpos ], [1 ]])
309343 ztrans = proj3d .proj_transform_vec (zvec , renderer .M )
310344 return ztrans [2 ][0 ]
311345
346+ def set_facecolor (self , colors ):
347+ PolyCollection .set_facecolor (self , colors )
348+ self ._facecolors3d = PolyCollection .get_facecolor (self )
349+ set_facecolors = set_facecolor
350+
351+ def set_edgecolor (self , colors ):
352+ PolyCollection .set_edgecolor (self , colors )
353+ self ._edgecolors3d = PolyCollection .get_edgecolor (self )
354+ set_edgecolors = set_edgecolor
355+
312356 def get_facecolors (self ):
313357 return self ._facecolors2d
314358 get_facecolor = get_facecolors
315359
360+ def get_edgecolors (self ):
361+ return self ._edgecolors2d
362+ get_edgecolor = get_edgecolors
363+
316364 def draw (self , renderer ):
317365 return Collection .draw (self , renderer )
318366
319- def poly_collection_2d_to_3d (col , zs = None , zdir = 'z' ):
367+ def poly_collection_2d_to_3d (col , zs = 0 , zdir = 'z' ):
320368 """Convert a PolyCollection to a Poly3DCollection object."""
321369 segments_3d = paths_to_3d_segments (col .get_paths (), zs , zdir )
322370 col .__class__ = Poly3DCollection
0 commit comments