diff --git a/examples/pylab_examples/tripcolor_demo.py b/examples/pylab_examples/tripcolor_demo.py index 0817c63c53b1..f97910af7d89 100644 --- a/examples/pylab_examples/tripcolor_demo.py +++ b/examples/pylab_examples/tripcolor_demo.py @@ -32,19 +32,19 @@ mask = np.where(xmid*xmid + ymid*ymid < min_radius*min_radius, 1, 0) triang.set_mask(mask) -# pcolor plot. +# tripcolor plot. plt.figure() plt.gca().set_aspect('equal') plt.tripcolor(triang, z, shading='flat', cmap=plt.cm.rainbow) plt.colorbar() -plt.title('tripcolor of Delaunay triangulation: flat') +plt.title('tripcolor of Delaunay triangulation, flat shading') # Illustrate Gouraud shading. plt.figure() plt.gca().set_aspect('equal') plt.tripcolor(triang, z, shading='gouraud', cmap=plt.cm.rainbow) plt.colorbar() -plt.title('tripcolor with Gouraud shading') +plt.title('tripcolor of Delaunay triangulation, gouraud shading') # You can specify your own triangulation rather than perform a Delaunay @@ -70,9 +70,6 @@ [-0.057,0.916],[-0.025,0.933],[-0.077,0.990],[-0.059,0.993] ]) x = xy[:,0]*180/3.14159 y = xy[:,1]*180/3.14159 -x0 = -5 -y0 = 52 -z = np.exp(-0.01*( (x-x0)*(x-x0) + (y-y0)*(y-y0) )) triangles = np.asarray([ [67,66, 1],[65, 2,66],[ 1,66, 2],[64, 2,65],[63, 3,64],[60,59,57], @@ -90,14 +87,21 @@ [32,31,33],[39,38,72],[33,72,38],[33,38,34],[37,35,38],[34,38,35], [35,37,36] ]) +xmid = x[triangles].mean(axis=1) +ymid = y[triangles].mean(axis=1) +x0 = -5 +y0 = 52 +zfaces = np.exp(-0.01*( (xmid-x0)*(xmid-x0) + (ymid-y0)*(ymid-y0) )) + # Rather than create a Triangulation object, can simply pass x, y and triangles # arrays to tripcolor directly. It would be better to use a Triangulation object # if the same triangulation was to be used more than once to save duplicated # calculations. +# Can specify one color value per face rather than one per point by using the +# facecolors kwarg. plt.figure() plt.gca().set_aspect('equal') -plt.tripcolor(x, y, triangles, z, shading='flat', edgecolors='k', - cmap='summer') +plt.tripcolor(x, y, triangles, facecolors=zfaces, edgecolors='k') plt.colorbar() plt.title('tripcolor of user-specified triangulation') plt.xlabel('Longitude (degrees)') diff --git a/lib/matplotlib/__init__.py b/lib/matplotlib/__init__.py index 3860b031e319..312d30a76f43 100644 --- a/lib/matplotlib/__init__.py +++ b/lib/matplotlib/__init__.py @@ -1021,6 +1021,7 @@ def tk_window_focus(): 'matplotlib.tests.test_legend', 'matplotlib.tests.test_colorbar', 'matplotlib.tests.test_patches', + 'matplotlib.tests.test_triangulation' ] def test(verbosity=1): diff --git a/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.pdf b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.pdf new file mode 100644 index 000000000000..ac2c3873949c Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.pdf differ diff --git a/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.png b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.png new file mode 100644 index 000000000000..1e5e83701ffb Binary files /dev/null and b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.png differ diff --git a/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.svg b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.svg new file mode 100644 index 000000000000..f9196f76c987 --- /dev/null +++ b/lib/matplotlib/tests/baseline_images/test_triangulation/tripcolor1.svg @@ -0,0 +1,1229 @@ + + + + diff --git a/lib/matplotlib/tests/test_triangulation.py b/lib/matplotlib/tests/test_triangulation.py index 52279758e074..81f922a0b225 100644 --- a/lib/matplotlib/tests/test_triangulation.py +++ b/lib/matplotlib/tests/test_triangulation.py @@ -1,8 +1,10 @@ import numpy as np +import matplotlib.pyplot as plt import matplotlib.tri as mtri import matplotlib.delaunay as mdel from nose.tools import assert_equal from numpy.testing import assert_array_equal, assert_array_almost_equal +from matplotlib.testing.decorators import image_comparison def test_delaunay(): # No duplicate points. @@ -94,3 +96,29 @@ def test_delaunay_duplicate_points(): mpl_triang.edges) assert_array_equal(del_triang.edge_db, converted_indices) +@image_comparison(baseline_images=['tripcolor1']) +def test_tripcolor(): + x = np.asarray([0, 0.5, 1, 0, 0.5, 1, 0, 0.5, 1, 0.75]) + y = np.asarray([0, 0, 0, 0.5, 0.5, 0.5, 1, 1, 1, 0.75]) + triangles = np.asarray([ + [0, 1, 3], [1, 4, 3], + [1, 2, 4], [2, 5, 4], + [3, 4, 6], [4, 7, 6], + [4, 5, 9], [7, 4, 9], [8, 7, 9], [5, 8, 9] ]) + + # Triangulation with same number of points and triangles. + triang = mtri.Triangulation(x, y, triangles) + + Cpoints = x + 0.5*y + + xmid = x[triang.triangles].mean(axis=1) + ymid = y[triang.triangles].mean(axis=1) + Cfaces = 0.5*xmid + ymid + + plt.subplot(121) + plt.tripcolor(triang, Cpoints, edgecolors='k') + plt.title('point colors') + + plt.subplot(122) + plt.tripcolor(triang, facecolors=Cfaces, edgecolors='k') + plt.title('facecolors') diff --git a/lib/matplotlib/tri/tripcolor.py b/lib/matplotlib/tri/tripcolor.py index aaf7896be39d..b65290bcaa6a 100644 --- a/lib/matplotlib/tri/tripcolor.py +++ b/lib/matplotlib/tri/tripcolor.py @@ -28,12 +28,20 @@ def tripcolor(ax, *args, **kwargs): :class:`~matplotlib.tri.Triangulation` for a explanation of these possibilities. - The next argument must be *C*, the array of color values, one per - point in the triangulation. - - *shading* may be 'flat', 'faceted' or 'gouraud'. If *shading* is - 'flat' or 'faceted', the colors used for each triangle are from - the mean C of the triangle's three points. + The next argument must be *C*, the array of color values, either + one per point in the triangulation if color values are defined at + points, or one per triangle in the triangulation if color values + are defined at triangles. If there are the same 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 kwarg *facecolors*=C instead of just *C*. + + *shading* may be 'flat' (the default) or 'gouraud'. If *shading* + is 'flat' and C values are defined at points, the color values + used for each triangle are from the mean C of the triangle's + three points. If *shading* is 'gouraud' then color values must be + defined at points. *shading* of 'faceted' is deprecated; + please use *edgecolors* instead. The remaining kwargs are the same as for :meth:`~matplotlib.axes.Axes.pcolor`. @@ -50,35 +58,78 @@ def tripcolor(ax, *args, **kwargs): vmin = kwargs.pop('vmin', None) vmax = kwargs.pop('vmax', None) shading = kwargs.pop('shading', 'flat') + facecolors = kwargs.pop('facecolors', None) tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args, **kwargs) - x = tri.x - y = tri.y - triangles = tri.get_masked_triangles() - C = np.asarray(args[0]) - if C.shape != x.shape: - raise ValueError('C array must have same length as triangulation x and' - ' y arrays') + # C is the colors array, defined at either points or faces (i.e. triangles). + # If facecolors is None, C are defined at points. + # If facecolors is not None, C are defined at faces. + if facecolors is not None: + C = facecolors + else: + C = np.asarray(args[0]) + + # If there are a different number of points and triangles in the + # triangulation, can omit facecolors kwarg as it is obvious from + # length of C whether it refers to points or faces. + # Do not do this for gouraud shading. + if (facecolors is None and len(C) == len(tri.triangles) and + len(C) != len(tri.x) and shading != 'gouraud'): + facecolors = C + + # Check length of C is OK. + if ( (facecolors is None and len(C) != len(tri.x)) or + (facecolors is not None and len(C) != len(tri.triangles)) ): + raise ValueError('Length of color values array must be the same ' + 'as either the number of triangulation points ' + 'or triangles') + + + # Handling of linewidths, shading, edgecolors and antialiased as + # in Axes.pcolor + linewidths = (0.25,) + if 'linewidth' in kwargs: + kwargs['linewidths'] = kwargs.pop('linewidth') + kwargs.setdefault('linewidths', linewidths) + + if shading == 'faceted': # Deprecated. + edgecolors = 'k', + else: + edgecolors = 'none' + if 'edgecolor' in kwargs: + kwargs['edgecolors'] = kwargs.pop('edgecolor') + ec = kwargs.setdefault('edgecolors', edgecolors) + + if 'antialiased' in kwargs: + kwargs['antialiaseds'] = kwargs.pop('antialiased') + if 'antialiaseds' not in kwargs and ec.lower() == "none": + kwargs['antialiaseds'] = False + if shading == 'gouraud': + if facecolors is not None: + raise ValueError('Gouraud shading does not support the use ' + 'of facecolors kwarg') + if len(C) != len(tri.x): + raise ValueError('For gouraud shading, the length of color ' + 'values array must be the same as the ' + 'number of triangulation points') collection = TriMesh(tri, **kwargs) else: - if shading == 'faceted': - edgecolors = (0,0,0,1), - linewidths = (0.25,) - else: - edgecolors = 'face' - linewidths = (1.0,) - kwargs.setdefault('edgecolors', edgecolors) - kwargs.setdefault('antialiaseds', (0,)) - kwargs.setdefault('linewidths', linewidths) - # Vertices of triangles. - verts = np.concatenate((x[triangles][...,np.newaxis], - y[triangles][...,np.newaxis]), axis=2) - # Color values, one per triangle, mean of the 3 vertex color values. - C = C[triangles].mean(axis=1) + maskedTris = tri.get_masked_triangles() + verts = np.concatenate((tri.x[maskedTris][...,np.newaxis], + tri.y[maskedTris][...,np.newaxis]), axis=2) + + # Color values. + if facecolors is None: + # One color per triangle, the mean of the 3 vertex color values. + C = C[maskedTris].mean(axis=1) + elif tri.mask is not None: + # Remove color values of masked triangles. + C = C.compress(1-tri.mask) + collection = PolyCollection(verts, **kwargs) collection.set_alpha(alpha)
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: