@@ -217,23 +217,39 @@ def set_segments(self, segments):
217
217
'''
218
218
Set 3D segments
219
219
'''
220
- self ._segments3d = np .asanyarray (segments )
220
+ self ._seg_sizes = [len (c ) for c in segments ]
221
+ self ._segments3d = []
222
+ if len (segments ) > 0 :
223
+ # Store the points in a single array for easier projection
224
+ n_segments = np .sum (self ._seg_sizes )
225
+ # Put all segments in a big array
226
+ self ._segments3d_data = np .vstack (segments )
227
+ # Add a fourth dimension for quaternions
228
+ self ._segments3d_data = np .hstack ([self ._segments3d_data ,
229
+ np .ones ((n_segments , 1 ))])
230
+
231
+ # For coveniency, store a view of the array in the original shape
232
+ cum_s = 0
233
+ for s in self ._seg_sizes :
234
+ self ._segments3d .append (
235
+ self ._segments3d_data [cum_s :cum_s + s , :3 ])
236
+ cum_s += s
221
237
LineCollection .set_segments (self , [])
222
238
223
239
def do_3d_projection (self , renderer ):
224
240
'''
225
241
Project the points according to renderer matrix.
226
242
'''
227
- shape = self ._segments3d . shape
228
- segments3d = np . transpose ( self . _segments3d , axes = [ 2 , 0 , 1 ])
229
- segments3d = segments3d . reshape (( 3 , - 1 ))
230
- # Pad ones
231
- segments3d = np . vstack ([ segments3d , np . ones (( 1 , segments3d . shape [ 1 ]))])
232
- xys = proj3d . proj_transform_vec ( segments3d , renderer . M )
233
- xys = np . reshape (xys . T , shape )
234
- segments_2d = xys [:, :, 0 : 2 ]
243
+ if len ( self ._segments3d ) == 0 :
244
+ return 1e9
245
+ xys = proj3d . proj_transform_vec ( self . _segments3d_data . T , renderer . M ). T
246
+ segments_2d = []
247
+ cum_s = 0
248
+ for s in self . _seg_sizes :
249
+ segments_2d . append (xys [ cum_s : cum_s + s , : 2 ] )
250
+ cum_s += s
235
251
LineCollection .set_segments (self , segments_2d )
236
- minz = np .min (xys [:, :, 2 ]) if xys . size > 0 else 1e9
252
+ minz = np .min (xys [:, 2 ])
237
253
return minz
238
254
239
255
def draw (self , renderer , project = False ):
@@ -301,7 +317,7 @@ def set_3d_properties(self, path, zs=0, zdir='z'):
301
317
302
318
def do_3d_projection (self , renderer ):
303
319
# pad ones
304
- s = np .vstack (self ._segmenta3d , np .ones (self ._segment3d .shape [1 ]))
320
+ s = np .vstack (self ._segments3d , np .ones (self ._segments3d .shape [1 ]))
305
321
vxyzis = proj3d .proj_transform_vec_clip (s , renderer .M )
306
322
self ._path2d = mpath .Path (vxyzis [0 :2 ].T , self ._code3d )
307
323
# FIXME: coloring
@@ -433,8 +449,10 @@ def set_3d_properties(self, zs, zdir):
433
449
# Force the collection to initialize the face and edgecolors
434
450
# just in case it is a scalarmappable with a colormap.
435
451
self .update_scalarmappable ()
436
- offsets = np .vstack (self .get_offsets (), np .ones (len (verts )) * zs )
437
- self ._offsets3d = juggle_axes_vec (offsets , zdir )
452
+ offsets = self .get_offsets ()
453
+ offsets = np .hstack ([offsets ,
454
+ (np .ones (len (offsets )) * zs )[:, np .newaxis ]])
455
+ self ._offsets3d = juggle_axes_vec (offsets , zdir ).T
438
456
self ._facecolor3d = self .get_facecolor ()
439
457
self ._edgecolor3d = self .get_edgecolor ()
440
458
self .stale = True
@@ -539,14 +557,16 @@ def set_zsort(self, zsort):
539
557
540
558
def get_vector (self , segments3d ):
541
559
"""Optimize points for projection"""
542
- segments3d = np .asarray (segments3d )
543
- # Segments 3d are given in shape (n_segments, segsize, 3)
544
- self ._segsize = segments3d .shape [1 ]
545
- # Flatten
546
- xyz = segments3d .T .reshape ((3 , - 1 ))
547
- # Add a fourth dimension with only ones
548
- ones = np .ones (xyz .shape [1 ])
549
- self ._vec = np .vstack ([xyz , ones ])
560
+
561
+ self ._seg_sizes = [len (c ) for c in segments3d ]
562
+ self ._vec = []
563
+ if len (segments3d ) > 0 :
564
+ # Store the points in a single array for easier projection
565
+ n_segments = np .sum (self ._seg_sizes )
566
+ # Put all segments in a big array
567
+ self ._vec = np .vstack (segments3d )
568
+ # Add a fourth dimension for quaternions
569
+ self ._vec = np .hstack ([self ._vec , np .ones ((n_segments , 1 ))]).T
550
570
551
571
def set_verts (self , verts , closed = True ):
552
572
'''Set 3D vertices.'''
@@ -574,7 +594,7 @@ def set_3d_properties(self):
574
594
self ._alpha3d = PolyCollection .get_alpha (self )
575
595
self .stale = True
576
596
577
- def set_sort_zpos (self ,val ):
597
+ def set_sort_zpos (self , val ):
578
598
'''Set the position to use for z-sorting.'''
579
599
self ._sort_zpos = val
580
600
self .stale = True
@@ -588,9 +608,12 @@ def do_3d_projection(self, renderer):
588
608
self .update_scalarmappable ()
589
609
self ._facecolors3d = self ._facecolors
590
610
591
- xys = proj3d .proj_transform_vec (self ._vec , renderer .M )
592
- xys = np .reshape (xys , (3 , self ._segsize , - 1 ))
593
- xyzlist = xys .T
611
+ xys = proj3d .proj_transform_vec (self ._vec , renderer .M ).T
612
+ xyzlist = []
613
+ cum_s = 0
614
+ for s in self ._seg_sizes :
615
+ xyzlist .append (xys [cum_s :cum_s + s , :3 ])
616
+ cum_s += s
594
617
595
618
# This extra fuss is to re-order face / edge colors
596
619
cface = self ._facecolors3d
@@ -605,11 +628,11 @@ def do_3d_projection(self, renderer):
605
628
# if required sort by depth (furthest drawn first)
606
629
if self ._zsort :
607
630
z_argsort = np .argsort (
608
- self ._zsortfunc (xyzlist [:, :, 2 ], axis = 1 ) )[::- 1 ]
631
+ [ self ._zsortfunc (xyz [:, 2 ]) for xyz in xyzlist ] )[::- 1 ]
609
632
else :
610
633
raise ValueError ("whoops" )
611
634
612
- segments_2d = xyzlist [z_argsort , :, 0 :2 ]
635
+ segments_2d = [ xyzlist [i ][ :, 0 :2 ] for i in z_argsort ]
613
636
if self ._codes3d is not None :
614
637
codes = self ._codes3d [z_argsort ]
615
638
PolyCollection .set_verts_and_codes (self , segments_2d , codes )
0 commit comments