FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

[Bug]: Surface draws incorrectly after set_verts on Poly3DCollection · Issue #21163 · matplotlib/matplotlib · GitHub

Repository navigation

[Bug]: Surface draws incorrectly after set_verts on Poly3DCollection  #21163

Closed as not planned

Description

Bug summary

Surface is not rendered properly after changing the data using set_verts: the simple MWE below shows the effect.

Code for reproduction

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

x = np.array([10, -10])
y = np.array([25, -25])
z = 5

X, 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)
plt.pause(1.0)

time = np.linspace(0, 5, 101)
for t in time:
    zt = z + 2 * np.sin(2 * np.pi * t)
    Z = zt * np.ones_like(X)
    verts = np.array([X, Y, Z]).T.reshape(4, 3)
    surf.set_verts(verts)
    plt.pause(0.1)

Actual outcome

Expected outcome

The full surface, as is shown prior to updating using set_verts should be shown:

Operating system

Ubuntu 21.04

Matplotlib Version

3.4.2

Matplotlib Backend

Qt5Agg

Python version

3.8.11

Jupyter version

No response

Other libraries

No response

Installation

conda

Conda channel

No response

Activity

  1. jklymak commented on Sep 24, 2021

    Member

    Can you modify that to not have the loop/animation? Is it just a clipping problem?

  2. ccaprani commented on Sep 24, 2021

    Author

    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.

  3. jklymak commented on Sep 24, 2021

    Member

    I mean does it happen at t[0]? t[1]? Please remove the loop from the example if possible

  4. ccaprani commented on Sep 24, 2021

    Author

    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:

    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    
    x = np.array([10, -10])
    y = np.array([25, -25])
    z = 5
    
    X, 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)
    plt.pause(1.0)
    
    zt = 6
    Z = zt * np.ones_like(X)
    verts = np.array([X, Y, Z]).T.reshape(4, 3)
    surf.set_verts(verts)
    plt.show()
  5. ccaprani commented on Sep 24, 2021

    Author

    @jklymak some insight perhaps: why does surf._vec return a 4x4 array? It should be 4x3 surely (4 points, x,y,z triple)?

  6. jklymak commented on Sep 24, 2021

    Member

    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.

  7. ccaprani commented on Sep 24, 2021

    Author

    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

    xs, ys, zs = np.row_stack(segments3d).T

    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?

  8. jklymak commented on Sep 24, 2021

    Member
    [[ 10  25   6]
     [ 10 -25   6]
     [-10  25   6]
     [-10 -25   6]]
    

    draws out a an N instead of a square.

  9. ccaprani commented on Sep 24, 2021

    Author

    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.

    import numpy as np
    import matplotlib.pyplot as plt
    
    x = np.array([10, -10])
    y = np.array([25, -25])
    z = 5
    
    X, 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._vec
    verts[2] = 6 * np.ones(4)
    plt.draw()
    plt.pause(1.0)
    
    # Makes a bow, even though the order seems reasonable
    Z = 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 input
    Z = 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).T
    surf._vec = np.vstack((np.array([i, l, k, j]).T, np.ones(4)))
    print(surf._vec)
    plt.draw()
    plt.pause(1.0)
  10. ccaprani commented on Sep 24, 2021

    Author

    @apaszke would #16688 solve this?

  11. 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!

  12. added
    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.
    on Dec 4, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    status: closed as inactiveIssues closed by the "Stale" Github Action. Please comment on any you think should still be open.status: inactiveMarked by the “Stale” Github Actiontopic: mplot3d

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions


      Back | FazBrowse Home | New Git URL