Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Fix and document lightsource argument in mplot3d #9990

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Sep 16, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 36 additions & 29 deletions lib/mpl_toolkits/mplot3d/axes3d.py
Original file line number Diff line number Diff line change
Expand Up @@ -1593,7 +1593,11 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None,
Bounds for the normalization.

shade : bool
Whether to shade the face colors.
Whether to shade the facecolors. Defaults to True. Shading is
always disabled when `cmap` is specified.

lightsource : `~matplotlib.colors.LightSource`
The lightsource to use when `shade` is True.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use *shade* to denote other variables.

https://matplotlib.org/devel/documenting_mpl.html#id3

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I missed this instance, sorry.


**kwargs :
Other arguments are forwarded to `.Poly3DCollection`.
Expand Down Expand Up @@ -1644,10 +1648,6 @@ def plot_surface(self, X, Y, Z, *args, norm=None, vmin=None,
cmap = kwargs.get('cmap', None)
shade = kwargs.pop('shade', cmap is None)

# Shade the data
if shade and cmap is not None and fcolors is not None:
fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)

# evenly spaced, and including both endpoints
row_inds = list(range(0, rows-1, rstride)) + [rows-1]
col_inds = list(range(0, cols-1, cstride)) + [cols-1]
Expand Down Expand Up @@ -1688,7 +1688,7 @@ def get_normals(polygons):

if fcolors is not None:
if shade:
colset = self._shade_colors(colset, get_normals(polys))
colset = self._shade_colors(colset, get_normals(polys), lightsource)
polyc.set_facecolors(colset)
polyc.set_edgecolors(colset)
elif cmap:
Expand All @@ -1701,7 +1701,7 @@ def get_normals(polygons):
polyc.set_norm(norm)
else:
if shade:
colset = self._shade_colors(color, get_normals(polys))
colset = self._shade_colors(color, get_normals(polys), lightsource)
else:
colset = color
polyc.set_facecolors(colset)
Expand All @@ -1725,13 +1725,16 @@ def _generate_normals(self, polygons):
normals.append(np.cross(v1, v2))
return normals

def _shade_colors(self, color, normals):
def _shade_colors(self, color, normals, lightsource=None):
'''
Shade *color* using normal vectors given by *normals*.
*color* can also be an array of the same length as *normals*.
'''
if lightsource is None:
# chosen for backwards-compatibility
lightsource = LightSource(azdeg=225, altdeg=19.4712)

shade = np.array([np.dot(n / proj3d.mod(n), [-1, -1, 0.5])
shade = np.array([np.dot(n / proj3d.mod(n), lightsource.direction)
if proj3d.mod(n) else np.nan
for n in normals])
mask = ~np.isnan(shade)
Expand All @@ -1751,11 +1754,6 @@ def _shade_colors(self, color, normals):

return colors

def _shade_colors_lightsource(self, data, cmap, lightsource):
if lightsource is None:
lightsource = LightSource(azdeg=135, altdeg=55)
return lightsource.shade(data, cmap)

def plot_wireframe(self, X, Y, Z, *args, **kwargs):
"""
Plot a 3D wireframe.
Expand Down Expand Up @@ -1879,17 +1877,7 @@ def plot_wireframe(self, X, Y, Z, *args, **kwargs):
def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
lightsource=None, **kwargs):
"""
============= ================================================
Argument Description
============= ================================================
*X*, *Y*, *Z* Data values as 1D arrays
*color* Color of the surface patches
*cmap* A colormap for the surface patches.
*norm* An instance of Normalize to map values to colors
*vmin* Minimum value to map
*vmax* Maximum value to map
*shade* Whether to shade the facecolors
============= ================================================
Plot a triangulated surface.

The (optional) triangulation can be specified in one of two ways;
either::
Expand All @@ -1914,10 +1902,29 @@ def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
where *Z* is the array of values to contour, one per point
in the triangulation.

Other arguments are passed on to
:class:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`
Parameters
----------
X, Y, Z : array-like
Data values as 1D arrays.
color
Color of the surface patches.
cmap
A colormap for the surface patches.
norm : Normalize
An instance of Normalize to map values to colors.
vmin, vmax : scalar, optional, default: None
Minimum and maximum value to map.
shade : bool
Whether to shade the facecolors. Defaults to True. Shading is
always disabled when *cmap* is specified.
lightsource : `~matplotlib.colors.LightSource`
The lightsource to use when *shade* is True.
**kwargs
All other arguments are passed on to
:class:`~mpl_toolkits.mplot3d.art3d.Poly3DCollection`

**Examples:**
Examples
--------

.. plot:: gallery/mplot3d/trisurf3d.py
.. plot:: gallery/mplot3d/trisurf3d_2.py
Expand Down Expand Up @@ -1965,7 +1972,7 @@ def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
v1 = verts[:, 0, :] - verts[:, 1, :]
v2 = verts[:, 1, :] - verts[:, 2, :]
normals = np.cross(v1, v2)
colset = self._shade_colors(color, normals)
colset = self._shade_colors(color, normals, lightsource)
else:
colset = color
polyc.set_facecolors(colset)
Expand Down