@@ -160,8 +160,7 @@ def set_3d_properties(self, zs=0, zdir='z'):
160
160
ys = self .get_ydata ()
161
161
162
162
zs = np .broadcast_to (zs , len (xs ))
163
- xyz = np .asarray ([xs , ys , zs ])
164
- self ._verts3d = _juggle_axes_vec (xyz , zdir )
163
+ self ._verts3d = juggle_axes (xs , ys , zs , zdir )
165
164
self .stale = True
166
165
167
166
@artist .allow_rasterization
@@ -181,52 +180,58 @@ def line_2d_to_3d(line, zs=0, zdir='z'):
181
180
182
181
183
182
def path_to_3d_segment (path , zs = 0 , zdir = 'z' ):
184
- """Convert a path to a 3D segment."""
185
- seg3d = np .empty ((3 , len (path )))
186
- # Works both if zs is an array or a scalar
187
- seg3d [2 , :] = zs
183
+ """Convert a path to a 3D segment.
184
+
185
+ .. versionchanged :: 3.1
186
+ Return type changed from a list to a numpy.array
187
+ """
188
+ zs = np .broadcast_to (zs , len (path ))
188
189
189
190
pathsegs = path .iter_segments (simplify = False , curves = False )
190
- for i , ((x , y ), code ) in enumerate (pathsegs ):
191
- seg3d [0 , i ] = x
192
- seg3d [1 , i ] = y
191
+ if len (path ):
192
+ xs , ys = zip (* ((x , y ) for (x , y ), code in pathsegs ))
193
+ else :
194
+ xs , ys = [], []
193
195
194
- seg3d = _juggle_axes_vec ( seg3d , zdir )
195
- return seg3d .T
196
+ seg3d = juggle_axes ( xs , ys , zs , zdir )
197
+ return np . array ( seg3d ) .T
196
198
197
199
198
200
def paths_to_3d_segments (paths , zs = 0 , zdir = 'z' ):
199
201
"""Convert paths from a collection object to 3D segments.
200
202
201
- .. versionchanged :: 1. 3.1
202
- This function returns a numpy array instead of a list
203
+ .. versionchanged :: 3.1
204
+ Return type changed from a list to a numpy.array
203
205
"""
204
206
205
207
zs = np .broadcast_to (zs , len (paths ))
208
+
206
209
segs = [path_to_3d_segment (path , pathz , zdir )
207
210
for path , pathz in zip (paths , zs )]
208
- return np . asarray ( segs )
211
+ return segs
209
212
210
213
211
214
def path_to_3d_segment_with_codes (path , zs = 0 , zdir = 'z' ):
212
- """Convert a path to a 3D segment with path codes."""
213
- seg3d = np .empty ((3 , len (path )))
214
- # Works both if zs is an array and a scalar
215
- seg3d [2 , :] = zs
215
+ """Convert a path to a 3D segment with path codes.
216
+
217
+ .. versionchanged :: 3.1
218
+ Return type changed from a list to a numpy.array
219
+ """
220
+ zs = np .broadcast_to (zs , len (path ))
216
221
217
222
pathsegs = path .iter_segments (simplify = False , curves = False )
218
223
codes = np .empty (len (path ))
219
- for i , ((x , y ), code ) in enumerate (pathsegs ):
220
- seg3d [0 , i ] = x
221
- seg3d [1 , i ] = y
222
- codes [i ] = code
223
- seg3d = _juggle_axes_vec (seg3d , zdir )
224
- return seg3d .T , codes
224
+ xs , ys , codes = zip (* ((x , y , code ) for (x , y ), code in pathsegs ))
225
+ seg3d = juggle_axes (xs , ys , zs , zdir )
226
+ return np .array (seg3d ).T , codes
225
227
226
228
227
229
def paths_to_3d_segments_with_codes (paths , zs = 0 , zdir = 'z' ):
228
230
"""
229
231
Convert paths from a collection object to 3D segments with path codes.
232
+
233
+ .. versionchanged :: 3.1
234
+ Return type changed from a list to a numpy.array
230
235
"""
231
236
232
237
zs = np .broadcast_to (zs , len (paths ))
@@ -309,8 +314,8 @@ def __init__(self, *args, zs=(), zdir='z', **kwargs):
309
314
310
315
def set_3d_properties (self , verts , zs = 0 , zdir = 'z' ):
311
316
zs = np .broadcast_to (zs , len (verts ))
312
- verts = np . hstack ([ verts , zs [:, None ]])
313
- self ._segment3d = _juggle_axes_vec ( verts . T , zdir )
317
+ xs , ys = verts . T
318
+ self ._segment3d = juggle_axes ( xs , ys , zs , zdir )
314
319
self ._facecolor3d = Patch .get_facecolor (self )
315
320
316
321
def get_path (self ):
@@ -321,7 +326,11 @@ def get_facecolor(self):
321
326
322
327
def do_3d_projection (self , renderer ):
323
328
# pad ones
324
- s = np .vstack ([self ._segment3d , np .ones (self ._segment3d .shape [1 ])])
329
+ if self ._segment3d :
330
+ segments_3d_len = len (self ._segment3d [0 ])
331
+ else :
332
+ segments_3d_len = 0
333
+ s = np .vstack (self ._segment3d + (np .ones (segments_3d_len ),))
325
334
vxyzis = proj3d .proj_transform_vec_clip (s , renderer .M )
326
335
self ._path2d = mpath .Path (vxyzis [0 :2 ].T )
327
336
# FIXME: coloring
@@ -344,7 +353,11 @@ def set_3d_properties(self, path, zs=0, zdir='z'):
344
353
345
354
def do_3d_projection (self , renderer ):
346
355
# pad ones
347
- s = np .vstack ([self ._segment3d , np .ones (self ._segment3d .shape [1 ])])
356
+ if self ._segment3d :
357
+ segments_3d_len = len (self ._segment3d [0 ])
358
+ else :
359
+ segments_3d_len = 0
360
+ s = np .vstack (self ._segment3d + (np .ones (segments_3d_len ),))
348
361
vxyzis = proj3d .proj_transform_vec_clip (s , renderer .M )
349
362
self ._path2d = mpath .Path (vxyzis [0 :2 ].T , self ._code3d )
350
363
# FIXME: coloring
@@ -414,8 +427,13 @@ def set_3d_properties(self, zs, zdir):
414
427
# Force the collection to initialize the face and edgecolors
415
428
# just in case it is a scalarmappable with a colormap.
416
429
self .update_scalarmappable ()
417
- offsets = np .vstack (self .get_offsets (), np .atleast_1d (zs ))
418
- self ._offsets3d = _juggle_axes_vec (offsets , zdir )
430
+ offsets = self .get_offsets ()
431
+ if len (offsets ) > 0 :
432
+ xs , ys = offsets .T
433
+ else :
434
+ xs = []
435
+ ys = []
436
+ self ._offsets3d = juggle_axes (xs , ys , np .atleast_1d (zs ), zdir )
419
437
self ._facecolor3d = self .get_facecolor ()
420
438
self ._edgecolor3d = self .get_edgecolor ()
421
439
self .stale = True
@@ -478,9 +496,12 @@ def set_3d_properties(self, zs, zdir):
478
496
# just in case it is a scalarmappable with a colormap.
479
497
self .update_scalarmappable ()
480
498
offsets = self .get_offsets ()
481
- offsets = np .hstack ([offsets ,
482
- np .broadcast_to (zs , len (offsets ))[:, np .newaxis ]])
483
- self ._offsets3d = _juggle_axes_vec (offsets , zdir ).T
499
+ if len (offsets ) > 0 :
500
+ xs , ys = offsets .T
501
+ else :
502
+ xs = []
503
+ ys = []
504
+ self ._offsets3d = juggle_axes (xs , ys , np .atleast_1d (zs ), zdir )
484
505
self ._facecolor3d = self .get_facecolor ()
485
506
self ._edgecolor3d = self .get_edgecolor ()
486
507
self .stale = True
@@ -757,22 +778,6 @@ def juggle_axes(xs, ys, zs, zdir):
757
778
return xs , ys , zs
758
779
759
780
760
- def _juggle_axes_vec (xyz , zdir ):
761
- """
762
- Reorder coordinates so that 2D xs, ys can be plotted in the plane
763
- orthogonal to zdir. zdir is normally x, y or z. However, if zdir
764
- starts with a '-' it is interpreted as a compensation for rotate_axes.
765
- """
766
- if zdir == 'x' :
767
- return xyz [[2 , 0 , 1 ]]
768
- elif zdir == 'y' :
769
- return xyz [[0 , 2 , 1 ]]
770
- elif zdir .startswith ('-' ):
771
- return _rotate_axes_vec (xyz , zdir )
772
- else :
773
- return xyz
774
-
775
-
776
781
def rotate_axes (xs , ys , zs , zdir ):
777
782
"""
778
783
Reorder coordinates so that the axes are rotated with zdir along
@@ -791,26 +796,6 @@ def rotate_axes(xs, ys, zs, zdir):
791
796
return xs , ys , zs
792
797
793
798
794
- def _rotate_axes_vec (xyz , zdir ):
795
- """
796
- Reorder coordinates so that the axes are rotated with zdir along
797
- the original z axis. Prepending the axis with a '-' does the
798
- inverse transform, so zdir can be x, -x, y, -y, z or -z
799
- """
800
- if zdir == 'x' :
801
- return xyz [[1 , 2 , 0 ]]
802
- elif zdir == '-x' :
803
- return xyz [[2 , 0 , 1 ]]
804
-
805
- elif zdir == 'y' :
806
- return xyz [[2 , 0 , 1 ]]
807
- elif zdir == '-y' :
808
- return xyz [[1 , 2 , 0 ]]
809
-
810
- else :
811
- return xyz
812
-
813
-
814
799
def get_colors (c , num ):
815
800
"""Stretch the color argument to provide the required number *num*."""
816
801
if not len (c ):
0 commit comments