简体   繁体   English

matplotlib 3D表面的透明度和颜色梯度?

[英]Translucency and color gradients of matplotlib 3D surfaces?

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

When I run the code above, I get the following. 当我运行上面的代码时,我得到以下内容。 Note, I set the viewpoint from the bottom for purposes of illustration. 注意,出于说明目的,我从底部开始设置了视点。

3D图

Two questions: 两个问题:

  1. Why does the red plane have a nice, pretty color gradient, but the blue plane has this irregular pattern? 为什么红色平面有一个漂亮的,漂亮的颜色渐变,而蓝色平面却有这种不规则的图案? How do I make the blue's pattern like the red's or make the coloring uniform? 如何使蓝色的图案像红色的一样或使着色均匀?

  2. I want to make the two planes such that, from the viewpoint of the viewer, whichever plane portion is "in front" of the other is visible. 我想制作两个平面,以便从查看者的角度来看,可以看到另一个平面“位于另一个”的前面。 For example, in the above image, most of the red plane shown would be visible, but above the intersection line of z = sqrt(2) ~= 1.41, it would be hidden behind the blue plane. 例如,在上图中,显示的大多数红色平面都是可见的,但是在z = sqrt(2)〜= 1.41的交线上方,它将隐藏在蓝色平面的后面。 How can I get Matplotlib to do this? 我如何获得Matplotlib来做到这一点?

Your example exposes a bug in matplotlib's shading algorithm. 您的示例暴露了matplotlib的着色算法中的错误。 The shading algorithm computes the normals to each facet in the surface, and uses the color and its normal vector to shade the facet : 着色算法计算曲面中每个构面的法线,并使用颜色及其法线向量对构面进行着色

colset = self._shade_colors(color, normals)

Although in theory the normals are all identical for a plane, in practice, there are very slight variations in the numerical values due to the vagaries of floating-point arithmetic. 尽管理论上一个平面的法线都相同,但实际上,由于浮点运算的变化,数值会有很小的变化。 These very slight variations are magnified by normalization since this stretches the minimum and maximum shades to lie between 0 and 1. 归一化会放大这些非常小的变化,因为这会将最小和最大阴影扩展到0到1之间。

Thus all surfaces which are completely planar are prone to this shading bug. 因此,所有完全平面的表面都容易出现此着色错误。

When the color is uniform (eg color='b' ) and the normals are all identical (as is the case for a plane), the shading should be the same for each facet. 当颜色是统一的(例如color='b' )并且法线都相同时(就像平面一样),每个小面的阴影都应该相同。 Normalization should make the shading zero. 归一化应使阴影为零。 So for a plane the shading should not change the color at all. 因此,对于飞机而言,阴影根本不应该改变颜色。

Thus, to work around the bug, turn off shading with shade=False : 因此,要解决该错误,请使用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. PS。 If you'd like to see the exact location where the normalization goes awry, change shade=False to shade=True in the code above, then place these print statements in your installation's matplotlib/colors.py : 如果您想查看规范化的确切位置,请在上面的代码中将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)

Running the script above then prints 运行上面的脚本然后打印

[  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.]

If resdat had been uniformly constant, all values in resdat would be zero after normalization. 如果resdat一直一致恒定,则归一化后resdat所有值都将为零。 Instead, the tiny errors in resdat get magnified to equal 1. That leads to the funny shading you are seeing on the blue surface. 相反, resdat的微小错误会放大为等于1。这会导致您在蓝色表面上看到有趣的阴影。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM