Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

[mplot3d] Add custom values for determining colors in trisurf#23878

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
aaarne wants to merge7 commits intomatplotlib:main
base:main
Choose a base branch
Loading
fromaaarne:main
Open
Show file tree
Hide file tree
Changes fromall 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
35 changes: 35 additions & 0 deletionsdoc/users/next_whats_new/colored_trisurf.rst
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
3D Trisurf plots can now have colors and allow color-maps
---------------------------------------------------------

We can now show custom properties on triangle surface in 3D color coded.
You can provide an array of one value per vertex OR one value per face.
The faces will then be painted based on a color map. If one value per vertex
is specified (this is probably the default case, as we usually know data only on
the vertices) the vertex values will be averaged over the face an then color-mapped.

Now also shading of colored trisurfs is added. Before it was only possible for uniformly
colored meshes. This might not be what you want on colormaps, so the default is off.

.. plot::
:include-source: true

import numpy as np
import matplotlib.tri as mtri
import matplotlib.pyplot as plt

fig = plt.figure()

# Create a parametric sphere
r = np.linspace(0, np.pi, 50)
phi = np.linspace(-np.pi, np.pi, 50)
r, phi = np.meshgrid(r, phi)
r, phi = r.flatten(), phi.flatten()
tri = mtri.Triangulation(r, phi)

x = np.sin(r)*np.cos(phi)
y = np.sin(r)*np.sin(phi)
z = np.cos(r)

ax = fig.add_subplot(projection='3d')
ax.plot_trisurf(x, y, z, triangles=tri.triangles, C=phi, cmap=plt.cm.get_cmap('terrain'))
plt.show()
35 changes: 35 additions & 0 deletionsexamples/mplot3d/trisurf3d_3.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
"""
===========================
Colored triangular 3D surfaces
===========================

This shows how to do colored trisurf plots.

"""

import numpy as np
import matplotlib.tri as mtri
import matplotlib.pyplot as plt

fig = plt.figure()

# Create a parametric sphere
r = np.linspace(0, np.pi, 50)
phi = np.linspace(-np.pi, np.pi, 50)
r, phi = np.meshgrid(r, phi)
r, phi = r.flatten(), phi.flatten()
tri = mtri.Triangulation(r, phi)

x = np.sin(r)*np.cos(phi)
y = np.sin(r)*np.sin(phi)
z = np.cos(r)

ax = fig.add_subplot(projection='3d')
ax.plot_trisurf(x, y, z,
triangles=tri.triangles,
cmap=plt.colormaps['terrain'],
C=np.sin(2*phi)*(r - np.pi/2),
shade=True)

fig.tight_layout()
plt.show()
2 changes: 1 addition & 1 deletionlib/matplotlib/tri/tripcolor.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -45,7 +45,7 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None,
number of points and triangles in the triangulation it is assumed that
color values are defined at points; to force the use of color values at
triangles use the keyword argument ``facecolors=C`` instead of just
``C``.
``C``. The values in C will be color-mapped.
This parameter is position-only.
facecolors : array-like, optional
Can be used alternatively to *C* to specify colors at the triangle
Expand Down
86 changes: 65 additions & 21 deletionslib/mpl_toolkits/mplot3d/axes3d.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -1733,7 +1733,7 @@ def plot_wireframe(self, X, Y, Z, **kwargs):
return linec

def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
lightsource=None, **kwargs):
C=None, facecolors=None,lightsource=None, **kwargs):
"""
Plot a triangulated surface.

Expand DownExpand Up@@ -1763,16 +1763,30 @@ def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
X, Y, Z : array-like
Data values as 1D arrays.
color
Color of the surface patches.
Color of the surface patches. This is only a single color vector
applied to every face.
cmap
A colormap for the surface patches.
norm : Normalize
An instance of Normalize to map values to colors.
vmin, vmax : float, default: None
Minimum and maximum value to map.
C : array-like, default: None
Values or colors used to determine face colors. If cmap is
specified the values will be color-mapped before the faces are
painted. If there is one value/color per vertex, these will be
averaged over each triangle to determine face colors. Defaults to
the z-coordinate of vertices. This keyword argument resembles the
functionality of ``C`` in `matplotlib.axes.Axes.tripcolor`.
facecolors: array-like, shape (n, 3/4), default None
Individual face colors. Must be of shape *(#faces, 3)* for
RBG or *(#faces, 4)* for RGBA with the colors in the rows.
Overrides everything from the ``C`` keyword argument.
This works like the ``facecolors`` keyword argument in
'~matplotlib.axes.Axes.tripcolor'.
shade : bool, default: True
Whether to shade the facecolors. Shading is always disabled when
*cmap* is specified.
*facecolors* is specified.
lightsource : `~matplotlib.colors.LightSource`
The lightsource to use when *shade* is True.
**kwargs
Expand All@@ -1783,17 +1797,13 @@ def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,
--------
.. plot:: gallery/mplot3d/trisurf3d.py
.. plot:: gallery/mplot3d/trisurf3d_2.py
.. plot:: gallery/mplot3d/trisurf3d_3.py
"""

had_data = self.has_data()

# TODO: Support custom face colours
if color is None:
color = self._get_lines.get_next_color()
color = np.array(mcolors.to_rgba(color))

cmap = kwargs.get('cmap', None)
shade = kwargs.pop('shade', cmap is None)
shade = kwargs.pop('shade',(cmap is None) and (facecolors is None))

tri, args, kwargs = \
Triangulation.get_from_args_and_kwargs(*args, **kwargs)
Expand All@@ -1812,21 +1822,55 @@ def plot_trisurf(self, *args, color=None, norm=None, vmin=None, vmax=None,

polyc = art3d.Poly3DCollection(verts, *args, **kwargs)

if cmap:
# average over the three points of each triangle
avg_z = verts[:, :, 2].mean(axis=1)
polyc.set_array(avg_z)
if vmin is not None or vmax is not None:
polyc.set_clim(vmin, vmax)
if norm is not None:
polyc.set_norm(norm)
else:
if facecolors is None:
if cmap:
if C is None:
C = z

if vmin is not None or vmax is not None:
polyc.set_clim(vmin, vmax)
if norm is not None:
polyc.set_norm(norm)

if C.shape[0] == z.shape[0]:
face_values = C[triangles].mean(axis=1)
elif C.shape[0] == triangles.shape[0]:
face_values = C
else:
raise ValueError("c needs either one value per vertex or "
"per face")

facecolors = polyc.to_rgba(face_values)
elif C is not None:
if C.shape[0] == z.shape[0]:
facecolors = C[triangles].mean(axis=1)
elif C.shape[0] == triangles.shape[0]:
facecolors = C
else:
raise ValueError("c needs either one color per vertex or "
"per face")
else:
if color is None:
color = self._get_lines.get_next_color()
color = np.array(mcolors.to_rgba(color))
if shade:
normals = self._generate_normals(verts)
colset = self._shade_colors(color, normals, lightsource)
else:
colset = color
polyc.set_facecolors(colset)

if facecolors is not None:
if facecolors.shape[0] != triangles.shape[0]:
raise ValueError("As many colors as faces required for "
"facecolors keyword argument")
if shade:
normals = self._generate_normals(verts)
colset = self._shade_colors(color, normals, lightsource)
polyc.set_facecolor(
self._shade_colors(facecolors, normals, lightsource)
)
else:
colset = color
polyc.set_facecolors(colset)
polyc.set_facecolor(facecolors)

self.add_collection(polyc)
self.auto_scale_xyz(tri.x, tri.y, z, had_data)
Expand Down
59 changes: 59 additions & 0 deletionslib/mpl_toolkits/tests/test_mplot3d.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -14,6 +14,7 @@
from matplotlib.patches import Circle, PathPatch
from matplotlib.path import Path
from matplotlib.text import Text
from matplotlib.tri import Triangulation

import matplotlib.pyplot as plt
import numpy as np
Expand DownExpand Up@@ -669,6 +670,64 @@ def test_trisurf3d():
ax.plot_trisurf(x, y, z, cmap=cm.jet, linewidth=0.2)


@check_figures_equal(extensions=['png'])
def test_colorcoded_trisurf3d(fig_ref, fig_test):
ax = fig_ref.add_subplot(projection='3d')
ax_test = fig_test.add_subplot(projection='3d')

# Create a parametric unit sphere
r = np.linspace(0, np.pi, 20)
phi = np.linspace(-np.pi, np.pi, 20)
r, phi = np.meshgrid(r, phi)
r, phi = r.flatten(), phi.flatten()
tri = Triangulation(r, phi)

x = np.sin(r)*np.cos(phi)
y = np.sin(r)*np.sin(phi)
z = np.cos(r)

# Old implementation uses z-coordinates for color code
ax.plot_trisurf(x, y, z,
triangles=tri.triangles,
cmap=cm.Spectral)

# Manually specify z-value as custom color-source
ax_test.plot_trisurf(x, y, z,
triangles=tri.triangles,
cmap=cm.Spectral,
C=z)


@check_figures_equal(extensions=['png'])
def test_value_per_vertex_vs_value_per_face(fig_ref, fig_test):
ax = fig_ref.add_subplot(projection='3d')
ax_test = fig_test.add_subplot(projection='3d')

# Create a parametric unit sphere
r = np.linspace(0, np.pi, 20)
phi = np.linspace(-np.pi, np.pi, 20)
r, phi = np.meshgrid(r, phi)
r, phi = r.flatten(), phi.flatten()
tri = Triangulation(r, phi)

x = np.sin(r)*np.cos(phi)
y = np.sin(r)*np.sin(phi)
z = np.cos(r)

norm = plt.Normalize(vmin=phi.min(), vmax=phi.max())
cmap = plt.colormaps['jet']
expected_facecolors = cmap(norm(phi[tri.triangles].mean(axis=1)))
ax.plot_trisurf(x, y, z,
triangles=tri.triangles,
facecolors=expected_facecolors)

ax_test.plot_trisurf(x, y, z,
triangles=tri.triangles,
C=phi,
cmap=cmap,
norm=norm)


@mpl3d_image_comparison(['trisurf3d_shaded.png'], tol=0.03)
def test_trisurf3d_shaded():
n_angles = 36
Expand Down

[8]ページ先頭

©2009-2025 Movatter.jp