Sorry for not being clear: a minimum of one further call to draw the surface is necessary to demonstrate the problem. The initial call to plot_surface correctly renders the surface (and this is visible during the first plt.pause(1.0) call. Then, once it has the set_verts called again, it does not render correctly. This demonstrates the problem without a loop:
If you try print(verts) you will see that you have
[[ 10 25 6]
[ 10 -25 6]
[-10 25 6]
[-10 -25 6]]
which traces the corners out in a non-closed order. plot_surface goes from X, Y, Z to polygons in a somewhat obfuscated way (cbook._array_patch_perimeters), so I am not 100% sure what the "best" way to move the vertices around is supposed to be for three-D surfaces. Worse, it appears we do not have a public way to get the vertices that are in the Poly3DCollection?
So I think that this is more of a feature request than a "bug" per-se. I'm not expert enough in the 3D API to help further.
My bad @jklymak - thanks for picking that up. Actually, this seems key to the whole thing. So let's say I have four points, one in each quadrant when looking along negative z direction, labelled as follows:
y
^
l | i
--------------> x
k | j
|
np.meshgrid generates the X and Y matrices in the order [[i, l], [j, k]] where the appropriate x or y coord is in the corresponding entry; but surf._vec is in the order [i, l, k, j] where each of i,j,k,l is a 4x1 column vector, of which the first three entries are the x,y,z coordinate triple.
So it seems that vertices are expected in an anticlockwise manner, but even this is not consistent. I've extended the MWE to show some various ways of setting the coords and their effects; the last one is most strange.
importnumpyasnpimportmatplotlib.pyplotaspltx=np.array([10, -10])
y=np.array([25, -25])
z=5X, Y=np.meshgrid(x, y)
Z=z*np.ones_like(X)
fig=plt.figure(figsize=(8, 4.5))
ax=fig.add_subplot(projection="3d")
ax.axes.set_xlim3d(left=-15, right=15)
ax.axes.set_ylim3d(bottom=-30, top=30)
ax.axes.set_zlim3d(bottom=0, top=10)
surf=ax.plot_surface(X, Y, Z, color="r", alpha=0.3, edgecolor="r", lw=2)
print(surf._vec)
plt.pause(1.0)
# This shifts z ok, but what is the order of verts?verts=surf._vecverts[2] =6*np.ones(4)
plt.draw()
plt.pause(1.0)
# Makes a bow, even though the order seems reasonableZ=7*np.ones_like(X)
surf._vec=np.vstack((X.flatten(), Y.flatten(), Z.flatten(), np.ones(X.size)))
plt.draw()
plt.pause(1.0)
# Does something rather wild, even though it seems like a reasonable inputZ=4*np.ones_like(X)
verts=np.array([X, Y, Z]).reshape(4, 3)
surf.set_verts(verts)
plt.draw()
plt.pause(1.0)
# And even with careful manipulation of the point coords, to match the original _vec# this doesn't plot correctly (check print output)Z=5*np.ones_like(X)
i, l, j, k=np.array([X, Y, Z]).reshape(3, 4).Tsurf._vec=np.vstack((np.array([i, l, k, j]).T, np.ones(4)))
print(surf._vec)
plt.draw()
plt.pause(1.0)
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!
Activity
jklymak commented on Sep 24, 2021
Can you modify that to not have the loop/animation? Is it just a clipping problem?
ccaprani commented on Sep 24, 2021
No, it appears as part of a more detailed animation, and setting the axes limits outside the surface should mean it is not a clipping problem.
jklymak commented on Sep 24, 2021
I mean does it happen at t[0]? t[1]? Please remove the loop from the example if possible
ccaprani commented on Sep 24, 2021
Sorry for not being clear: a minimum of one further call to draw the surface is necessary to demonstrate the problem. The initial call to plot_surface correctly renders the surface (and this is visible during the first plt.pause(1.0) call. Then, once it has the set_verts called again, it does not render correctly. This demonstrates the problem without a loop:
ccaprani commented on Sep 24, 2021
@jklymak some insight perhaps: why does surf._vec return a 4x4 array? It should be 4x3 surely (4 points, x,y,z triple)?
jklymak commented on Sep 24, 2021
If you try print(verts) you will see that you have
which traces the corners out in a non-closed order. plot_surface goes from X, Y, Z to polygons in a somewhat obfuscated way (cbook._array_patch_perimeters), so I am not 100% sure what the "best" way to move the vertices around is supposed to be for three-D surfaces. Worse, it appears we do not have a public way to get the vertices that are in the Poly3DCollection?
So I think that this is more of a feature request than a "bug" per-se. I'm not expert enough in the 3D API to help further.
ccaprani commented on Sep 24, 2021
I do think it is a bug: Looking at the code it calls get_vector which interprets non-zero length input (variable passed is now called segments3d using
so it is expecting an (N,3) shape. And while the documentation for 3D is not great, the 2D version is categoric in expecting an (N,2) input.
The issue is also implicit in a number of questions (not or badly answered on SO), e.g. here and here.
I'm also not sure about the "non closed order" - looking in the negative z direction, these are list clockwise from the first to 4th quadrant?
jklymak commented on Sep 24, 2021
draws out a an N instead of a square.
ccaprani commented on Sep 24, 2021
My bad @jklymak - thanks for picking that up. Actually, this seems key to the whole thing. So let's say I have four points, one in each quadrant when looking along negative z direction, labelled as follows:
y ^ l | i --------------> x k | j |np.meshgrid generates the X and Y matrices in the order [[i, l], [j, k]] where the appropriate x or y coord is in the corresponding entry; but surf._vec is in the order [i, l, k, j] where each of i,j,k,l is a 4x1 column vector, of which the first three entries are the x,y,z coordinate triple.
So it seems that vertices are expected in an anticlockwise manner, but even this is not consistent. I've extended the MWE to show some various ways of setting the coords and their effects; the last one is most strange.
ccaprani commented on Sep 24, 2021
@apaszke would #16688 solve this?
github-actions commented on Nov 3, 2025
This issue has been marked "inactive" because it has been 365 days since the last comment. If this issue is still present in recent Matplotlib releases, or the feature request is still wanted, please leave a comment and this label will be removed. If there are no updates in another 30 days, this issue will be automatically closed, but you are free to re-open or create a new issue if needed. We value issue reports, and this procedure is meant to help us resurface and prioritize issues that have not been addressed yet, not make them disappear. Thanks for your help!