2017-08-24 380 views
2
from mpl_toolkits.mplot3d import Axes3D 
import matplotlib.pyplot as plt 
import numpy as np 

X = np.arange(1, 4, 0.2) 
Y = np.copy(X) 
X, Y = np.meshgrid(X, Y) 

Z1 = np.copy(X) 
Z2 = 2/X 

fig = plt.figure() 
ax = fig.gca(projection='3d') 
surf1 = ax.plot_surface(X, Y, Z1, rstride=1, cstride=1, color='b') 
surf2 = ax.plot_surface(X, Y, Z2, rstride=1, cstride=1, color='r') 

plt.show() 

当我运行上面的代码时,我得到以下内容。请注意,为了说明的目的,我从底部设置了观点。matplotlib 3D表面的半透明度和颜色渐变?

3D Plot

两个问题:

  1. 为什么红色平面有一个漂亮的,漂亮的颜色渐变,但蓝色的飞机,有这个不规则的图案?我如何使蓝色的图案像红色一样或使颜色均匀?

  2. 我想让两个平面,使得从观察者的角度来看,无论平面部分是“前”其他的是可见的。例如,在上图中,大部分红色平面都是可见的,但在z = sqrt(2)〜= 1.41的交线上方,它将隐藏在蓝色平面后面。我怎样才能让Matplotlib做到这一点?

回答

3

您的示例公开了matplotlib着色算法中的一个错误。遮光 算法计算的法线每个小面的表面,并且uses the color and its normal vector to shade the facet

colset = self._shade_colors(color, normals) 

虽然理论上法线都为一个平面是相同的,在实践中,存在 是在适当的数值有微小变化到了浮点算术的变幻莫测的 。这些非常小的变化是由 normalization因为这stretches the minimum and maximum shades放大到位于0和1之间

因此,这是完全平面的所有表面都容易出现这种着色缺陷。

当颜色是统一的(例如color='b')和法线都是相同的(如飞机的情况下是 ),每个方面的阴影应该是相同的。标准化应该使阴影为零。所以对于一架飞机,阴影不应该改变颜色 。

因此,要解决这个bug,关闭遮光用shade=False

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

X = np.arange(1, 4, 0.2) 
Y = np.copy(X) 
X, Y = np.meshgrid(X, Y) 
Z1 = np.copy(X) 
Z2 = 2/X 

fig = plt.figure() 
ax = fig.gca(projection='3d') 

surf1 = ax.plot_surface(
    X, Y, Z1, rstride=1, cstride=1, color='b', 
    shade=False, alpha=1.0) 

surf2 = ax.plot_surface(
    X, Y, Z2, rstride=1, cstride=1, color='r', 
    shade=True, alpha=1.0) 

ax.view_init(elev=-45, azim=-30) 
plt.show() 

enter image description here


PS。如果你想看看那里的正常化就会出差错的确切位置,在上面的代码更改shade=Falseshade=True,然后将这些print报表安装的matplotlib/colors.py

resdat = result.data 
resdat -= vmin 
print(resdat[0, :10]) 
resdat /= (vmax - vmin) 
print(resdat[0, :10]) 
result = np.ma.array(resdat, mask=result.mask, copy=False) 

运行上面的脚本然后打印

[ 0.00000000e+00 0.00000000e+00 0.00000000e+00 0.00000000e+00 
    0.00000000e+00 0.00000000e+00 2.22044605e-16 0.00000000e+00 
    0.00000000e+00 2.22044605e-16] 
[ 0. 0. 0. 0. 0. 0. 1. 0. 0. 1.] 

如果resdat已经均匀恒定,在resdat所有值将正常化后为零。相反,resdat中的微小错误会放大到等于1.导致您在蓝色表面上看到的有趣阴影。