16

我正在尝试使用用于 Python 的神话般的 Matplotlib 包绘制一些对象。这些对象由用 实现的点和用 实现的plt.scatter()补丁组成Poly3DCollection。我希望补丁具有轻微的透明度,以便可以看到补丁后面的点和边缘。

这里是我已经生成的代码和绘图。似乎我快到了,只是缺少透明度的功能。有趣的是,如果我先绘制点,Ploy3DCollection然后绘制scatter点,可以看到点,但看不到边缘。

有人对我有建议吗?

在此处输入图像描述

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]

vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]

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

poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.5))

plt.show()
4

5 回答 5

16

我对 OP 代码做了一些修改,让透明度工作。Poly3DCollection 的 facecolors 参数似乎覆盖了透明度参数,因此解决方案是在单独调用中设置颜色Poly3DCollection.set_coloror Poly3DCollection.set_facecolor

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]

vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]

tupleList = zip(x, y, z)

poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
collection = Poly3DCollection(poly3d, linewidths=1, alpha=0.2)
face_color = [0.5, 0.5, 1] # alternative: matplotlib.colors.rgb2hex([0.5, 0.5, 1])
collection.set_facecolor(face_color)
ax.add_collection3d(collection)

plt.show()

有趣的是,如果您使用 明确设置边缘颜色collection.set_edgecolor('k'),则边缘也将遵循透明度设置。

于 2014-03-14T11:19:35.403 回答
12

我找到了一个很好的解决方法:绘制数据后,在顶部用相同的颜色和较浅的线条样式绘制另一个图。而不是Poly3DCollection我使用Line3DCollection,所以没有绘制任何面孔。结果看起来非常像预期的那样。

请参阅下面的新图和创建它的脚本。

在此处输入图像描述

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]

vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]

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

poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, facecolors='w', linewidths=1, alpha=0.5))
ax.add_collection3d(Line3DCollection(poly3d, colors='k', linewidths=0.2, linestyles=':'))

plt.show()
于 2013-09-19T22:28:04.610 回答
4

非常感谢 Chilichiller 和 Julian。你的例子目前对我非常有用,因为我正在做一个关于使用 matplotlib 矩阵的 3D 表示的小项目,而 Poly3DCollection 似乎适合这项任务。

一点说明,这可能对未来的读者有用。在 Python 3 中运行您的示例会给出 TypeError: 'zip' object is not subscriptable。

最简单的解决方案是将 zip 的返回值包装在对 list() 的调用中(如“Dive Into Python 3”所示:http ://www.diveintopython3.net/porting-code-to-python-3-with -2to3.html )。

于 2014-05-14T15:30:05.847 回答
3

这是一个仅使用一次调用的版本Poly3DCollection,其中edgecolors='k'控制线条的颜色并facecolors='w'控制面的颜色。请注意 Matplotlib 如何将多边形后面的边缘染成浅灰色。

在此处输入图像描述

from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection, Line3DCollection

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

x = [0, 2, 1, 1]
y = [0, 0, 1, 0]
z = [0, 0, 0, 1]

vertices = [[0, 1, 2], [0, 1, 3], [0, 2, 3], [1, 2, 3]]

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

poly3d = [[tupleList[vertices[ix][iy]] for iy in range(len(vertices[0]))] for ix in range(len(vertices))]
ax.scatter(x,y,z)
ax.add_collection3d(Poly3DCollection(poly3d, edgecolors='k', facecolors='w', linewidths=1, alpha=0.5))

plt.show()

注意API forPoly3DCollection相当混乱:接受的关键字参数都是colors, edgecolor, edgecolors, facecolor, and facecolors(使用别名和装饰器来定义多个 kwargs 来表示同一事物,其中“s”对于facecolorand是可选的edgecolor)。

于 2020-06-04T17:02:13.750 回答
2

此错误已在新的 matplotlib 中修复。我正在运行 1.5.1 版。

您可以通过运行 python 查看您的版本,然后执行以下操作:

import matplotlib
matplotlib.__version__

您可以使用 pip 获取 matplotlib。如果您使用的是 Ubuntu,请从终端运行此命令:

sudo apt-get install python-pip
sudo pip install matplotlib
于 2016-03-11T01:42:52.767 回答