1

I'm trying to plot a hull using trisurf. I need to specify the color of each triangle (there are many). Can this be done? I tried this but it does not work:

import matplotlib.pyplot as plt:

...

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot_trisurf(points[:,0], points[:,1], points[:,2],
            triangles=faces, cmap=facecolors)
plt.show()

facecolorsis a matrix withlen(faces)rows; each row is (R,G,B). If I omit thecmapargument it plots fine but monochromatically, of course.

Is it possible to do what I want?

Eduardo
  • 1,235
  • 16
  • 27

2 Answers2

1

Concerning the colors you will need to decide if

  1. you want to use the data (points[:,2]) in conjunction with a colormap to colorize your surface or if
  2. you want to specify the colors yourself.

In the first case, cmap needs to be a matplotlib colormap and not an array. You can use a named colormap, like "jet", or create your own colormap.

In the second case, you need to omit the cmap keyword and use the facecolors keyword argument instead, which will be passed to the Poly3DCollection in the background. The facecolor argument is currently being ignored. In the code you can see that although the facecolor argument is correctly passed onto the Poly3DCollection, the facecolor is afterwards overwritten by the colorargument, which does not seem to accept a numpy array.

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
  • What I want is 2. I tried to use facecolors; didn't fail but didn't use my colors either (it still plots in blue). the facecolors I am passing look like [[ 0.92732552 0.86409221 0.13920713] [ 0.90771008 0.86711351 0.16366606] [ 0.36837615 0.09819653 0.11761538] ...] – Eduardo Feb 11 '17 at 20:01
  • You are correct, the `facecolors` argument seems to be ignored. Sorry for the confusion. I'm trying to find out why that is, but it is a bit involved. – ImportanceOfBeingErnest Feb 11 '17 at 21:10
  • Interestingly, if I pass (R,G,B) values in 0-255 (I tried that at one point) it fails with a message saying the the values must be in (0,1). So it looks at facecolors, complains if it's wrong, but does not use it... – Eduardo Feb 11 '17 at 21:16
  • Jep, true. Even if I manipulate the matplotlib code such that the numpy array is actually passed on to the collection, it will be ignored. The problem may then be in colors.py where it may fall back to a single color (the first in the array). But in any case, with the current version it's simply not possible to use custom colors. – ImportanceOfBeingErnest Feb 11 '17 at 21:56
  • 1
    Any news on the color problem? Or any alternative to plot_trisurf that allows the color to be decided by any function...? – gingras.ol Feb 01 '20 at 01:10
0

I have found the same problem (still in 2023 isnt fixed). I avoided it using this code that hope to be usefull for other users.

fig = plt.figure()
ax = fig.add_subplot(1,1,1)

#Having a node list (point list) "nodes"
#Having a face list (triangle list) "faces"
#Having a "color_faces" list that contains the colors of each face 

polygons = []
for i in range(faces.shape[0]):
    face = faces[i]
    polygon = Poly3DCollection([nodes[face]], alpha=.75, facecolor= color_faces[i] ,linewidths=2)
    polygons.append(polygon)
    ax.add_collection3d(polygon)

ax.set_xlim3d(np.min(nodes[:, 0]), np.max(nodes[:, 0]))
ax.set_ylim3d(np.min(nodes[:, 1]), np.max(nodes[:, 1]))
ax.set_zlim3d(np.min(nodes[:, 2]), np.max(nodes[:, 2]))

plt.show()

If you have the color information for nodes and not for faces, maybe this function to estimate the colors of the faces from the points that form it may be useful. (This just calculates the mean value, it doesnt do a gradient)

def color_nodes2faces(colorNodes,nodes,faces):
    colored_faces = []
    for face in faces:
        face_color = (colorNodes[face[0]] + colorNodes[face[1]] + colorNodes[face[2]]) / 3
        colored_faces.append(face_color)
    return  cm.jet(colored_faces)
Agutig
  • 1