@@ -598,19 +598,20 @@ def set_3d_properties(self, zs, zdir):
598
598
# Force the collection to initialize the face and edgecolors
599
599
# just in case it is a scalarmappable with a colormap.
600
600
self .update_scalarmappable ()
601
- offsets = self .get_offsets ()
601
+ offsets = super () .get_offsets ()
602
602
if len (offsets ) > 0 :
603
603
xs , ys = offsets .T
604
604
else :
605
605
xs = []
606
606
ys = []
607
- self ._offsets3d = juggle_axes (xs , ys , np .atleast_1d (zs ), zdir )
607
+ self ._zdir = zdir
608
+ self .set_offsets3d (np .ma .column_stack ((xs , ys , np .atleast_1d (zs ))), zdir )
608
609
self ._z_markers_idx = slice (- 1 )
609
610
self ._vzs = None
610
611
self .stale = True
611
612
612
613
def do_3d_projection (self ):
613
- xs , ys , zs = self ._offsets3d
614
+ xs , ys , zs = self .get_offsets3d ()
614
615
vxs , vys , vzs , vis = proj3d .proj_transform_clip (xs , ys , zs ,
615
616
self .axes .M )
616
617
self ._vzs = vzs
@@ -642,6 +643,29 @@ def get_edgecolor(self):
642
643
return self .get_facecolor ()
643
644
return self ._maybe_depth_shade_and_sort_colors (super ().get_edgecolor ())
644
645
646
+ def set_offsets3d (self , offsets , zdir = 'z' ):
647
+ """
648
+ Set the 3d offsets for the collection.
649
+
650
+ Parameters
651
+ ----------
652
+ offsets : (N, 3) or (3,) array-like
653
+ The offsets to be set.
654
+ zdir : {'x', 'y', 'z'}
655
+ The axis in which to place the offsets. Default: 'z'.
656
+ See `.get_dir_vector` for a description of the values.
657
+ """
658
+ return _set_offsets3d (self , offsets , zdir )
659
+
660
+ def get_offsets3d (self ):
661
+ """Return the 3d offsets for the collection.
662
+
663
+ Returns
664
+ -------
665
+ offsets : (N, 3) array
666
+ The offsets for the collection.
667
+ """
668
+ return _get_offsets3d (self )
645
669
646
670
class Path3DCollection (PathCollection ):
647
671
"""
@@ -696,13 +720,13 @@ def set_3d_properties(self, zs, zdir):
696
720
# Force the collection to initialize the face and edgecolors
697
721
# just in case it is a scalarmappable with a colormap.
698
722
self .update_scalarmappable ()
699
- offsets = self .get_offsets ()
723
+ offsets = super () .get_offsets ()
700
724
if len (offsets ) > 0 :
701
725
xs , ys = offsets .T
702
726
else :
703
727
xs = []
704
728
ys = []
705
- self ._offsets3d = juggle_axes ( xs , ys , np .atleast_1d (zs ), zdir )
729
+ self .set_offsets3d ( np . ma . column_stack (( xs , ys , np .atleast_1d (zs )) ), zdir )
706
730
# In the base draw methods we access the attributes directly which
707
731
# means we cannot resolve the shuffling in the getter methods like
708
732
# we do for the edge and face colors.
@@ -715,7 +739,6 @@ def set_3d_properties(self, zs, zdir):
715
739
# Grab the current sizes and linewidths to preserve them.
716
740
self ._sizes3d = self ._sizes
717
741
self ._linewidths3d = np .array (self ._linewidths )
718
- xs , ys , zs = self ._offsets3d
719
742
720
743
# Sort the points based on z coordinates
721
744
# Performance optimization: Create a sorted index array and reorder
@@ -751,7 +774,7 @@ def set_depthshade(self, depthshade):
751
774
self .stale = True
752
775
753
776
def do_3d_projection (self ):
754
- xs , ys , zs = self ._offsets3d
777
+ xs , ys , zs = self .get_offsets3d ()
755
778
vxs , vys , vzs , vis = proj3d .proj_transform_clip (xs , ys , zs ,
756
779
self .axes .M )
757
780
# Sort the points based on z coordinates
@@ -818,6 +841,30 @@ def get_edgecolor(self):
818
841
return self .get_facecolor ()
819
842
return self ._maybe_depth_shade_and_sort_colors (super ().get_edgecolor ())
820
843
844
+ def set_offsets3d (self , offsets , zdir = 'z' ):
845
+ """
846
+ Set the 3d offsets for the collection.
847
+
848
+ Parameters
849
+ ----------
850
+ offsets : (N, 3) or (3,) array-like
851
+ The offsets to be set.
852
+ zdir : {'x', 'y', 'z'}
853
+ The axis in which to place the offsets. Default: 'z'.
854
+ See `.get_dir_vector` for a description of the values.
855
+ """
856
+ return _set_offsets3d (self , offsets , zdir )
857
+
858
+ def get_offsets3d (self ):
859
+ """Return the 3d offsets for the collection.
860
+
861
+ Returns
862
+ -------
863
+ offsets : (N, 3) array
864
+ The offsets for the collection.
865
+ """
866
+ return _get_offsets3d (self )
867
+
821
868
822
869
def patch_collection_2d_to_3d (col , zs = 0 , zdir = 'z' , depthshade = True ):
823
870
"""
@@ -1113,6 +1160,30 @@ def get_edgecolor(self):
1113
1160
self .do_3d_projection ()
1114
1161
return np .asarray (self ._edgecolors2d )
1115
1162
1163
+ def set_offsets3d (self , offsets , zdir = 'z' ):
1164
+ """
1165
+ Set the 3d offsets for the collection.
1166
+
1167
+ Parameters
1168
+ ----------
1169
+ offsets : (N, 3) or (3,) array-like
1170
+ The offsets to be set.
1171
+ zdir : {'x', 'y', 'z'}
1172
+ The axis in which to place the offsets. Default: 'z'.
1173
+ See `.get_dir_vector` for a description of the values.
1174
+ """
1175
+ return _set_offsets3d (self , offsets , zdir )
1176
+
1177
+ def get_offsets3d (self ):
1178
+ """Return the 3d offsets for the collection.
1179
+
1180
+ Returns
1181
+ -------
1182
+ offsets : (N, 3) array
1183
+ The offsets for the collection.
1184
+ """
1185
+ return _get_offsets3d (self )
1186
+
1116
1187
1117
1188
def poly_collection_2d_to_3d (col , zs = 0 , zdir = 'z' ):
1118
1189
"""
@@ -1167,6 +1238,34 @@ def rotate_axes(xs, ys, zs, zdir):
1167
1238
return xs , ys , zs
1168
1239
1169
1240
1241
+ def _set_offsets3d (col_3d , offsets , zdir = 'z' ):
1242
+ """
1243
+ Set the 3d offsets for the collection.
1244
+
1245
+ Parameters
1246
+ ----------
1247
+ offsets : (N, 3) or (3,) array-like
1248
+ The offsets to be set.
1249
+ zdir : {'x', 'y', 'z'}
1250
+ The axis in which to place the offsets. Default: 'z'.
1251
+ See `.get_dir_vector` for a description of the values.
1252
+ """
1253
+ offsets = np .asanyarray (offsets )
1254
+ if offsets .shape == (3 ,): # Broadcast (3,) -> (1, 3) but nothing else.
1255
+ offsets = offsets [None , :]
1256
+ xs = np .asanyarray (col_3d .convert_xunits (offsets [:, 0 ]), float )
1257
+ ys = np .asanyarray (col_3d .convert_yunits (offsets [:, 1 ]), float )
1258
+ zs = np .asanyarray (col_3d .convert_yunits (offsets [:, 2 ]), float )
1259
+ col_3d ._offsets3d = juggle_axes (xs , ys , np .atleast_1d (zs ), zdir )
1260
+ col_3d .stale = True
1261
+
1262
+
1263
+ def _get_offsets3d (col3d ):
1264
+ """Return the offsets for the collection."""
1265
+ # Default to zeros in the no-offset (None) case
1266
+ return np .zeros ((1 , 3 )) if col3d ._offsets3d is None else col3d ._offsets3d
1267
+
1268
+
1170
1269
def _zalpha (colors , zs ):
1171
1270
"""Modify the alphas of the color list according to depth."""
1172
1271
# FIXME: This only works well if the points for *zs* are well-spaced
0 commit comments