您的示例公開了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()
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.導致您在藍色表面上看到的有趣陰影。