matplotlib 3D表面的半透明度和颜色渐变?

时间:2017-08-24 18:56:17

标签: python matplotlib graphing

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()

当我运行上面的代码时,我得到以下内容。注意,为了说明的目的,我从底部设置了视点。

3D Plot

两个问题:

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

  2. 我想制作这两个平面,从观察者的角度来看,无论哪个平面部分位于另一个平面部分的前方都是可见的。例如,在上图中,显示的大部分红色平面是可见的,但在z = sqrt(2)〜= 1.41的交叉线上方,它将隐藏在蓝色平面后面。我怎样才能让Matplotlib这样做?

1 个答案:

答案 0 :(得分: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')并且法线全部相同(按原样) 对于平面而言,每个方面的阴影应该相同。标准化应使着色为零。因此,对于飞机,阴影不应该 改变颜色。

因此,要解决此问题,请使用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=False更改为shade=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.这会导致您在蓝色表面上看到有趣的阴影。