@@ -2733,7 +2733,8 @@ def calc_arrow(uvw, angle=15):
2733
2733
2734
2734
quiver3D = quiver
2735
2735
2736
- def voxels (self , * args , facecolors = None , edgecolors = None , ** kwargs ):
2736
+ def voxels (self , * args , facecolors = None , edgecolors = None , shade = True ,
2737
+ lightsource = None , ** kwargs ):
2737
2738
"""
2738
2739
ax.voxels([x, y, z,] /, filled, facecolors=None, edgecolors=None, \
2739
2740
**kwargs)
@@ -2776,6 +2777,17 @@ def voxels(self, *args, facecolors=None, edgecolors=None, **kwargs):
2776
2777
- A 4D ndarray of rgb/rgba data, with the components along the
2777
2778
last axis.
2778
2779
2780
+ shade : bool
2781
+ Whether to shade the facecolors. Defaults to True. Shading is
2782
+ always disabled when *cmap* is specified.
2783
+
2784
+ .. versionadded:: 3.1
2785
+
2786
+ lightsource : `~matplotlib.colors.LightSource`
2787
+ The lightsource to use when *shade* is True.
2788
+
2789
+ .. versionadded:: 3.1
2790
+
2779
2791
**kwargs
2780
2792
Additional keyword arguments to pass onto
2781
2793
:func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
@@ -2849,9 +2861,9 @@ def _broadcast_color_arg(color, name):
2849
2861
# points lying on corners of a square
2850
2862
square = np .array ([
2851
2863
[0 , 0 , 0 ],
2852
- [0 , 1 , 0 ],
2864
+ [1 , 0 , 0 ],
2853
2865
[1 , 1 , 0 ],
2854
- [1 , 0 , 0 ]
2866
+ [0 , 1 , 0 ],
2855
2867
], dtype = np .intp )
2856
2868
2857
2869
voxel_faces = defaultdict (list )
@@ -2872,7 +2884,8 @@ def permutation_matrices(n):
2872
2884
qinds = np .arange (qc )
2873
2885
rinds = np .arange (rc )
2874
2886
2875
- square_rot = square .dot (permute .T )
2887
+ square_rot_pos = square .dot (permute .T )
2888
+ square_rot_neg = square_rot_pos [::- 1 ]
2876
2889
2877
2890
# iterate within the current plane
2878
2891
for p in pinds :
@@ -2885,7 +2898,7 @@ def permutation_matrices(n):
2885
2898
p0 = permute .dot ([p , q , 0 ])
2886
2899
i0 = tuple (p0 )
2887
2900
if filled [i0 ]:
2888
- voxel_faces [i0 ].append (p0 + square_rot )
2901
+ voxel_faces [i0 ].append (p0 + square_rot_neg )
2889
2902
2890
2903
# draw middle faces
2891
2904
for r1 , r2 in zip (rinds [:- 1 ], rinds [1 :]):
@@ -2896,16 +2909,16 @@ def permutation_matrices(n):
2896
2909
i2 = tuple (p2 )
2897
2910
2898
2911
if filled [i1 ] and not filled [i2 ]:
2899
- voxel_faces [i1 ].append (p2 + square_rot )
2912
+ voxel_faces [i1 ].append (p2 + square_rot_pos )
2900
2913
elif not filled [i1 ] and filled [i2 ]:
2901
- voxel_faces [i2 ].append (p2 + square_rot )
2914
+ voxel_faces [i2 ].append (p2 + square_rot_neg )
2902
2915
2903
2916
# draw upper faces
2904
2917
pk = permute .dot ([p , q , rc - 1 ])
2905
2918
pk2 = permute .dot ([p , q , rc ])
2906
2919
ik = tuple (pk )
2907
2920
if filled [ik ]:
2908
- voxel_faces [ik ].append (pk2 + square_rot )
2921
+ voxel_faces [ik ].append (pk2 + square_rot_pos )
2909
2922
2910
2923
# iterate over the faces, and generate a Poly3DCollection for each
2911
2924
# voxel
@@ -2924,9 +2937,20 @@ def permutation_matrices(n):
2924
2937
face [:, 2 ] = z [ind ]
2925
2938
faces .append (face )
2926
2939
2940
+ # shade the faces
2941
+ facecolor = facecolors [coord ]
2942
+ edgecolor = edgecolors [coord ]
2943
+ if shade :
2944
+ normals = self ._generate_normals (faces )
2945
+ facecolor = self ._shade_colors (facecolor , normals , lightsource )
2946
+ if edgecolor is not None :
2947
+ edgecolor = self ._shade_colors (
2948
+ edgecolor , normals , lightsource
2949
+ )
2950
+
2927
2951
poly = art3d .Poly3DCollection (faces ,
2928
- facecolors = facecolors [ coord ] ,
2929
- edgecolors = edgecolors [ coord ] ,
2952
+ facecolors = facecolor ,
2953
+ edgecolors = edgecolor ,
2930
2954
** kwargs
2931
2955
)
2932
2956
self .add_collection3d (poly )
0 commit comments