【问题标题】:Plotting 3D Polygons in Python 3在 Python 3 中绘制 3D 多边形
【发布时间】:2016-06-02 07:29:23
【问题描述】:

在我寻求以某种方式实际绘制 3D 多边形时,我遇到了以下脚本(编辑:稍作修改):Plotting 3D Polygons in python-matplotlib

from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import Poly3DCollection
import matplotlib.pyplot as plt
fig = plt.figure()
ax = Axes3D(fig)
x = [0,1,1,0]
y = [0,0,1,1]
z = [0,1,0,1]
verts = [zip(x, y,z)]
ax.add_collection3d(Poly3DCollection(verts),zs=z)
plt.show()

但是当我运行它时,我收到以下错误消息:

TypeError: object of type 'zip' has no len()

看起来这可能是 Python 2 与 3 的事情,因为我在 Python 3 中运行,并且该帖子已有五年历史。所以我将倒数第三行改为:

verts = list(zip(x, y, z))

现在 verts 出现在变量列表中,但我仍然收到错误:

TypeError: zip argument #1 must support iteration

什么?我该如何解决这个问题?

【问题讨论】:

    标签: python matplotlib mplot3d


    【解决方案1】:

    这是一个当前的解决方案,以防您收到错误 ValueError: not enough values to unpack (expected 3, got 1),因为 verts 在其他解决方案中是如何构造的:

    from mpl_toolkits.mplot3d import Axes3D
    from mpl_toolkits.mplot3d.art3d import Poly3DCollection
    import matplotlib.pyplot as plt
    fig = plt.figure()
    ax = Axes3D(fig)
    x = [0,1,1,0]
    y = [0,0,1,1]
    z = [0,1,0,1]
    verts = [[xx,yy,zz] for xx,yy,zz in zip(x,y,z)]     # NEW
    ax.add_collection3d(Poly3DCollection(verts))
    plt.show()
    
    

    【讨论】:

      【解决方案2】:

      我在压缩时遇到了类似的问题。我支持这个论点,它是 python 2.x vs 3.x 的东西。

      但是,我发现了一个明显可行的地方:

      from mpl_toolkits.mplot3d import Axes3D
      from mpl_toolkits.mplot3d.art3d import Poly3DCollection
      import matplotlib.pyplot as plt
      
      fig = plt.figure()
      ax = Axes3D(fig)
      x = [0, 1, 1, 0]
      y = [0, 0, 1, 1]
      z = [0, 1, 0, 1]
      verts = [list(zip(x, y, z))]
      print(verts)
      ax.add_collection3d(Poly3DCollection(verts), zs='z')
      plt.show()
      

      因此我做了两个改变:

      1. 换行: from matplotlib.collections import Poly3DCollection 经过: from matplotlib.mplot3.art3d import Poly3DCollection.

        我不知道您的导入语句来自哪里,但它似乎对我不起作用

      2. 将行:verts = list(zip(x,y,z))改为verts = [list(zip(x, y, z))]

      不知何故,后者似乎起作用了。刚开始接触python,我无法给出一个铁定的解释。然而,这里什么都没有:Poly3DCollection 类需要一个“集合”作为第一个输入参数,因此需要一个列表列表。在这种情况下,仅给出列表,因此假设错过了一个级别。通过向它添加另一个级别(通过 [...])它起作用了。

      我不知道这个解释是否有意义,但它对我来说很直观;)

      这些修改似乎有效,因为这段代码创建了所需的 3D 多边形(我注意到,由于这是我的第一篇文章,我不允许发布布丁证明图...... )

      希望对你有用,

      亲切的问候

      【讨论】:

      • 你说得对,zip() 是问题所在。在 Python 2 中,zip() 用于直接返回一个普通的旧列表,matplotlib 可以消化。在 Python 3 中,zip() 被更改为返回一个迭代器,用于并非一次需要所有项目(如果有很多项目可能会占用大量内存)或在到达之前停止消费项目的上下文结尾。 matplotlib 函数无法消化迭代器,因此list() 将迭代器展平为列表并使其再次工作。
      【解决方案3】:

      您必须使用 Poly3DCollection 而不是 PolyCollection:

      from mpl_toolkits.mplot3d import Axes3D
      from mpl_toolkits.mplot3d.art3d import Poly3DCollection
      import matplotlib.pyplot as plt
      fig = plt.figure()
      ax = Axes3D(fig)
      x = [0,1,1,0]
      y = [0,0,1,1]
      z = [0,1,0,1]
      verts = [zip(x,y,z)]
      ax.add_collection3d(Poly3DCollection(verts), zs=z)
      plt.show()
      

      【讨论】:

      • 糟糕——我没有提到我已经在尝试 Poly3DCollection。同样,压缩是导致错误的原因。我不知道如何解决这个问题。
      • 当我删除 zs 参数时对我有用。即: ax.add_collection3d(Poly3DCollection(verts)) 有效。 ax.add_collection3d(Poly3DCollection(verts), zs=z) 返回错误
      • 如果使用Poly3DCollection,则不需要zs=z,因为z轴值已经包含在内。
      猜你喜欢
      • 2017-12-07
      • 1970-01-01
      • 2015-10-03
      • 2016-02-10
      • 2023-04-01
      • 2015-01-12
      • 2023-03-14
      • 1970-01-01
      • 2010-09-30
      相关资源
      最近更新 更多