Matplotlib 3d alpha透明度错误?

时间:2017-04-02 07:12:31

标签: matplotlib 3d transparency alpha

使用matplotlib,我试图创建一个沿xy,yz和xz平面有三个半透明平面的3d图。我的代码基于this post,它对三年前报告的透明度错误有部分解决方法。

如果你试试下面的代码并旋转图形,你会发现平面重叠的区域会突然发生颜色变化。例如下面你看到中心区域突然从绿色变为蓝色。是否有进一步的解决方法来防止这种情况?

Color shift upon rotation

这是我的代码:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d as mp3d

xy = [ (-1, -1, 0),
       ( 1, -1, 0),
       ( 1,  1, 0),
       (-1,  1, 0),
    ]

yz = [ (0, -1, -1),
       (0,  1, -1),
       (0,  1,  1),
       (0, -1,  1),
    ]

xz = [ (-1, 0, -1),
       ( 1, 0, -1),
       ( 1, 0,  1),
       (-1, 0,  1),
    ]

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.scatter([-1, -1, -1, -1, 1, 1, 1, 1], [-1, -1, 1, 1, -1, -1, 1, 1], [-1, 1, -1, 1, -1, 1, -1, 1])
face1 = mp3d.art3d.Poly3DCollection([xy], alpha=0.5, linewidth=1)
face2 = mp3d.art3d.Poly3DCollection([yz], alpha=0.5, linewidth=1)
face3 = mp3d.art3d.Poly3DCollection([xz], alpha=0.5, linewidth=1)

# This is the key step to get transparency working
alpha = 0.5
face1.set_facecolor((0, 0, 1, alpha))
face2.set_facecolor((0, 1, 0, alpha))
face3.set_facecolor((1, 0, 0, alpha))

ax.add_collection3d(face1)
ax.add_collection3d(face2)
ax.add_collection3d(face3)

plt.show()

1 个答案:

答案 0 :(得分:1)

正如评论中所建议的那样,您可以将每个平面划分为四个象限平面并单独绘制。通过这种方式,matplotlib能够确定它们中的哪一个应该在前面,并且平面遵循透明度。

enter image description here

一个最小的例子:

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
import mpl_toolkits.mplot3d as mp3d

a = np.array([( 0, 0, 0),( 1, 0, 0),( 1, 1, 0),( 0, 1, 0)])
R1 = np.array([[0,-1,0],[1,0,0],[0,0,1]])
R2 = (R1[::-1].T)[:,[1,0,2]]
R3 = (R1[::-1])[:,[1,0,2]]
f = lambda a,r: np.matmul(r, a.T).T
g = lambda a,r: [a, f(a,r), f(f(a,r),r), f(f(f(a,r),r),r)]


fig = plt.figure()
ax = fig.add_subplot(111, projection=Axes3D.name)
ax.scatter([-1,1], [-1,1], [-1,1], alpha=0.0)

for i, ind , r in zip(range(3),[[0,1,2],[2,0,1],[1,2,0]], [R1,R2,R3]):
    xy = g(a[:,ind], r )
    for x in xy:
        face1 = mp3d.art3d.Poly3DCollection([x] , alpha=0.5, linewidth=1)
        face1.set_facecolor((i//2, i%2, i==0,  0.5))
        ax.add_collection3d(face1)

plt.show()