【问题标题】:Translucency and color gradients of matplotlib 3D surfaces?matplotlib 3D表面的半透明度和颜色渐变?
【发布时间】:2017-08-24 18:56:17
【问题描述】:
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()

当我运行上面的代码时,我得到以下信息。请注意,出于说明的目的,我从底部设置了视点。

两个问题:

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

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

【问题讨论】:

    标签: python matplotlib graphing


    【解决方案1】:

    您的示例暴露了 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()
    


    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。这会导致您在蓝色表面上看到有趣的阴影。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-12
      • 2016-12-02
      • 2013-02-07
      • 1970-01-01
      相关资源
      最近更新 更多