我正在尝试用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 = 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()
答案 0 :(得分:11)
我对OP代码做了一些修改,并使透明度有效。似乎Poly3DCollection的facecolors参数会覆盖透明度参数,因此解决方案是在单独调用Poly3DCollection.set_color
或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')
明确设置边缘颜色,则边缘也会遵循透明度设置。
答案 1 :(得分:8)
我找到了一个很好的解决方法:在绘制数据之后,在顶部绘制另一个具有相同颜色和较轻线条样式的绘图。我使用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 = 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()
答案 2 :(得分:3)
非常感谢Chilichiller和Julian。你的例子对我来说非常有用,因为我正在研究一个关于使用matplotlib进行矩阵三维表示的小项目,而且Poly3DCollection似乎适合这项任务。
一点点,可能对未来的读者有用。 在Python 3中运行示例会产生TypeError:'zip'对象不可订阅。
最简单的解决方案是在对list()的调用中包装zip的返回值(如“Dive Into Python 3”所示:http://www.diveintopython3.net/porting-code-to-python-3-with-2to3.html)。
答案 3 :(得分:2)
此错误已在新的matplotlib中修复。我正在运行1.5.1版本。
您可以通过运行python来查看您的版本,然后执行:
import matplotlib
matplotlib.__version__
您可以使用pip获取matplotlib。如果您使用的是Ubuntu,请从终端运行:
sudo apt-get install python-pip
sudo pip install matplotlib
答案 4 :(得分:0)
这里是一个仅使用一次对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()
警告:Poly3DCollection
的API令人困惑:接受的关键字参数是colors
,edgecolor
,edgecolors
,{{ 1}}和facecolor
(使用别名和修饰符定义多个kwarg表示同一件事,其中{s对facecolors
和facecolor
是可选的)。