How to set face color per triangle when using plot_trisurf in PyPlot

Hi, I want to set the face color of each triangle individually when plotting with plot_trisurf in PyPlot. The matplotlib manual seems to indicate that face color is set with the option ‘color’ (as a tuple), but there is also an optional argument ‘facecolor’ that is passed to Poly3DCollection. However, I cannot figure out how to apply this so that each triangle (patch) gets a separately defined color. I do manage to set the edge colors separately using the argument ‘edgecolor’.

This produces the result when all triangles (only two here) get the same color:

using PyPlot
fig  = figure()
ax   = Axes3D(fig)
x    = [0., 1., 1., 0.]
y    = [0., 0.5, 1., 1.]
z    = [0., 0., 1., 0.2]
t    = [1 2 4; 2 3 4]-1 # Zero-based indexing required (?)
fclr = [1. 0. 0.; 0. 0. 1.]
c    = (0.,1.,0.)
plot_trisurf(x,y,z,triangles=t,color=c,edgecolor=fclr,alpha=0.8, linewidth=3.);

I have not managed to get any effect by setting the ‘facecolor’ argument and I don’t know the syntax for passing multiple colors to ‘color’.

Any pointers to where I can find documentation about this, i.e., plotting surfaces with individually defined triangles, without resorting to a loop “over the triangles”?

Tested with v. 0.5.2 and 0.6.0.

I tried to do the same thing. At the time browsing through the matplotlib source lead me to a line saying ‘todo: support facecolors’. Gave up at that point. Not sure what the status is now.

I succeeded in making a coloured mesh plot using PlotlyJs though.

Thanks,

using PlotlyJS.jl I managed to set the face colors individually! But with this solution I don’t know how to set the edge colors… :slight_smile:

The code that gives me (sort of) what I want:

using PlotlyJS
function triplot(vertices,faces,facecolor;opacity=0.5,cameraEye=[-1 -1 1])
    fcStr = [@sprintf("rgb(%5.2f,%5.2f,%5.2f)",255*facecolor[k,1],255*facecolor[k,2],255*facecolor[k,3]) for k = 1:size(facecolor,1) ]
    t = mesh3d(
        x = vertices[:,1], y = vertices[:,2], z = vertices[:,3],
        i = faces[:,1]-1,  j = faces[:,2]-1,  i = faces[:,3]-1, # Zero-based indexing in plotly
        facecolor=fcStr,opacity=opacity)
        layout = Layout(;title="Basic Triangle Plot",
                        scene=attr(;camera=attr(eye=attr(x=cameraEye[1],y=cameraEye[2],z=cameraEye[3]))))
    plot(t, layout)
end

verts = [0. 0. 0.;  1. 0.5 0.; 1. 1. 1.; 0. 1. 0.2]
faces = [1 2 4; 2 3 4]
fclr  = [1. 0. 0.; 0. 0. 1.]
triplot(verts,faces,fclr)

A step in the right direction.

On further inspection, this is a non-working MWE. The triangle indexing appears to have no impact (incorrect syntax?) and the triangles are not colored in the given order. Any ideas would be appreciated. Another graphics package?

This is how I use PlotlyJs. As far as i know it works as expected: https://github.com/krcools/CompScienceMeshes.jl/blob/master/examples/plotlyjs_patches.jl

Thanks, it does work as expected now! I had a typo in the code above (not assigning any values to ‘k’). Vacation can be productive… :slight_smile:

So I’m really new to Python (starting playing around today!) but I think I found a fix. Just put

        if 'facecolors' in kwargs:
            fcolors = kwargs.pop('facecolors')
            polyc.sets_facecolors(fcolors)

at line 2032 and it should work if you use facecolor as an input argument to plot_trisurf. Just make sure you format the input colour array correctly and you’ll be dandy!

I know this is editing the library functions and that can be dubious, but if it works…

You can do it using set_array, see this stack thread

For FEM visualization, I really need the functionality of Matlab’s trisurf()… specifically where I specify a value on all the nodes, and I get a “smoothed” color plot on the triangles.

I can’t get PyPlot set_array() to work (I really don’t understand Python Numpy well enough to figure out the more arcane documentation.)

I’m able to import a triangle mesh from GMSH, and get it to plot, but everytime I feed any array to P.set_array() I get pages of Python errors, or a single color. Any help would be greatly appreciated.

Thanks. GMSH triangle file hole.m available here:
https://ellipticalcow.com/hole.m![pyplot_plot_trisurf|660x500]

The attached plot shows what I’m looking for (that plot was made in Paraview).

## gmsh matlab format (NICE!) just need to replace % with # and get rid of . 
include("hole.m")  ## an xy triangularization, z = zero 

T = Tgmsh[:,1:3]
X = vec(nodes[:,1])
Y = vec(nodes[:,2])
Tpy = T .- 1 ## Numpy apparently uses zero based indexing... 
P = PyPlot.plot_trisurf(X,Y,zeros(length(X)),triangles=Tpy)

C = vec(rand(length(X)))  ## to be replaced with FEM data 

P.set_array(C) ## ?? help appreciated. thanks

Also, I’d love to able to do this in Makie too, but that seems to be an open issue.

my link to the mesh file got corrupted. here it is

https://ellipticalcow.com/hole.m