@@ -2733,7 +2733,8 @@ def calc_arrow(uvw, angle=15):
27332733
27342734 quiver3D = quiver
27352735
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 ):
27372738 """
27382739 ax.voxels([x, y, z,] /, filled, facecolors=None, edgecolors=None, \
27392740 **kwargs)
@@ -2776,6 +2777,17 @@ def voxels(self, *args, facecolors=None, edgecolors=None, **kwargs):
27762777 - A 4D ndarray of rgb/rgba data, with the components along the
27772778 last axis.
27782779
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+
27792791 **kwargs
27802792 Additional keyword arguments to pass onto
27812793 :func:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
@@ -2849,9 +2861,9 @@ def _broadcast_color_arg(color, name):
28492861 # points lying on corners of a square
28502862 square = np .array ([
28512863 [0 , 0 , 0 ],
2852- [0 , 1 , 0 ],
2864+ [1 , 0 , 0 ],
28532865 [1 , 1 , 0 ],
2854- [1 , 0 , 0 ]
2866+ [0 , 1 , 0 ],
28552867 ], dtype = np .intp )
28562868
28572869 voxel_faces = defaultdict (list )
@@ -2872,7 +2884,8 @@ def permutation_matrices(n):
28722884 qinds = np .arange (qc )
28732885 rinds = np .arange (rc )
28742886
2875- square_rot = square .dot (permute .T )
2887+ square_rot_pos = square .dot (permute .T )
2888+ square_rot_neg = square_rot_pos [::- 1 ]
28762889
28772890 # iterate within the current plane
28782891 for p in pinds :
@@ -2885,7 +2898,7 @@ def permutation_matrices(n):
28852898 p0 = permute .dot ([p , q , 0 ])
28862899 i0 = tuple (p0 )
28872900 if filled [i0 ]:
2888- voxel_faces [i0 ].append (p0 + square_rot )
2901+ voxel_faces [i0 ].append (p0 + square_rot_neg )
28892902
28902903 # draw middle faces
28912904 for r1 , r2 in zip (rinds [:- 1 ], rinds [1 :]):
@@ -2896,16 +2909,16 @@ def permutation_matrices(n):
28962909 i2 = tuple (p2 )
28972910
28982911 if filled [i1 ] and not filled [i2 ]:
2899- voxel_faces [i1 ].append (p2 + square_rot )
2912+ voxel_faces [i1 ].append (p2 + square_rot_pos )
29002913 elif not filled [i1 ] and filled [i2 ]:
2901- voxel_faces [i2 ].append (p2 + square_rot )
2914+ voxel_faces [i2 ].append (p2 + square_rot_neg )
29022915
29032916 # draw upper faces
29042917 pk = permute .dot ([p , q , rc - 1 ])
29052918 pk2 = permute .dot ([p , q , rc ])
29062919 ik = tuple (pk )
29072920 if filled [ik ]:
2908- voxel_faces [ik ].append (pk2 + square_rot )
2921+ voxel_faces [ik ].append (pk2 + square_rot_pos )
29092922
29102923 # iterate over the faces, and generate a Poly3DCollection for each
29112924 # voxel
@@ -2924,9 +2937,20 @@ def permutation_matrices(n):
29242937 face [:, 2 ] = z [ind ]
29252938 faces .append (face )
29262939
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+
29272951 poly = art3d .Poly3DCollection (faces ,
2928- facecolors = facecolors [ coord ] ,
2929- edgecolors = edgecolors [ coord ] ,
2952+ facecolors = facecolor ,
2953+ edgecolors = edgecolor ,
29302954 ** kwargs
29312955 )
29322956 self .add_collection3d (poly )
0 commit comments