Python Matplotlib-在同一轴上打印两个三维曲面时重叠错误

Python Matplotlib-在同一轴上打印两个三维曲面时重叠错误,python,matplotlib,Python,Matplotlib,我正在尝试使用plot_surface命令在matplotlib中的相同轴上绘制两个三维曲面 fig = plt.figure() fig.figsize = fig_size ax = fig.gca(projection='3d') surf = ax.plot_surface(X, Y, Exp_Fric_map, alpha = 1, rstride=1, cstride=1, cmap=cm.winter, linewidth=0.5, antialiased=True) surf

我正在尝试使用plot_surface命令在matplotlib中的相同轴上绘制两个三维曲面

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

surf = ax.plot_surface(X, Y, Exp_Fric_map, alpha = 1, rstride=1, cstride=1, cmap=cm.winter, linewidth=0.5, antialiased=True)
surf = ax.plot_surface(X, Y, Fric_map, alpha = 1, rstride=1, cstride=1, cmap=cm.autumn,linewidth=0.5, antialiased=True)
我遇到的问题是,在查看绘图时,并非总是正确的曲面位于“顶部”,例如在绘图中:

在后角(200N,轴上为2.5Hz),蓝绿色表面位于“顶部”,而实际上黄红色更靠近观察者。如果旋转绘图:

现在一切都好了,蓝绿色的表面在黄红色的下面,200N和2.5Hz(现在在左侧)。我曾尝试搜索stackoverflow和Google,但找不到任何类似的解决方案


我在Linux上使用Python 2.7.3、Numpy 1.6.1和Matplotlib 1.1.1rc。

就像画画一样。哪一个“在上面”取决于你最后画的是哪一个

您可能希望使用
zorder
属性告知matplotlib曲面的绘制顺序

例如:

ax.plot_surface(X, Y, Exp_Fric_map, alpha = 1, rstride=1, cstride=1, cmap=cm.winter, linewidth=0.5, antialiased=True, zorder = 0.5)
ax.plot_surface(X, Y, Fric_map, alpha = 1, rstride=1, cstride=1, cmap=cm.autumn,linewidth=0.5, antialiased=True, zorder = 0.3)

更新

我已经运行了两个测试,我相信这是matplotlib在一个图形中绘制多个曲面时出现的一个错误。例如,它生成了一些在3D世界中不应该存在的曲面,如:

,尝试后,我看不到有效的解决方案。原因在于绘画的顺序,正如我所说:matplotlib总是一个接一个地画东西。如果曲面的一部分位于顶部,而另一部分位于底部,则matplotlib将出错


因此,我的建议是停止解决这个问题,除非你想为matplotlib做贡献,否则这是浪费时间。如果您必须解决此问题,我建议您去找另一个绘图工具来完成您的工作。

matplotlib FAQ中记录了此行为。同一页建议安装适用于3D绘图的软件

  • 它的接口与matplotlib非常相似
  • 它的主要问题是在Python3上安装它仍然很棘手。(现在轻松多了)

下面是一个演示“matplotlib vs mayavi”比较:

# generate data
import numpy as np

x = np.arange(-2, 2, 0.1)
y = np.arange(-2, 2, 0.1)
mx, my = np.meshgrid(x, y, indexing='ij')
mz1 = np.abs(mx) + np.abs(my)
mz2 = mx ** 2 + my ** 2

# A fix for "API 'QString' has already been set to version 1"
# see https://github.com/enthought/pyface/issues/286#issuecomment-335436808
from sys import version_info
if version_info[0] < 3:
    import pyface.qt


def v1_matplotlib():
    from matplotlib import pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D

    fig = plt.figure()
    ax = fig.gca(projection='3d')
    surf1 = ax.plot_surface(mx, my, mz1, cmap='winter')
    surf2 = ax.plot_surface(mx, my, mz2, cmap='autumn')
    ax.view_init(azim=60, elev=16)
    fig.show()


def v2_mayavi(transparency):
    from mayavi import mlab
    fig = mlab.figure()

    ax_ranges = [-2, 2, -2, 2, 0, 8]
    ax_scale = [1.0, 1.0, 0.4]
    ax_extent = ax_ranges * np.repeat(ax_scale, 2)

    surf3 = mlab.surf(mx, my, mz1, colormap='Blues')
    surf4 = mlab.surf(mx, my, mz2, colormap='Oranges')

    surf3.actor.actor.scale = ax_scale
    surf4.actor.actor.scale = ax_scale
    mlab.view(60, 74, 17, [-2.5, -4.6, -0.3])
    mlab.outline(surf3, color=(.7, .7, .7), extent=ax_extent)
    mlab.axes(surf3, color=(.7, .7, .7), extent=ax_extent,
              ranges=ax_ranges,
              xlabel='x', ylabel='y', zlabel='z')

    if transparency:
        surf3.actor.property.opacity = 0.5
        surf4.actor.property.opacity = 0.5
        fig.scene.renderer.use_depth_peeling = 1


v1_matplotlib()
v2_mayavi(False)
v2_mayavi(True)

# To install mayavi, the following currently works for me (Windows 10):
#
#   conda create --name mayavi_test_py2 python=2.7 matplotlib mayavi=4.4.0
#    (installs pyqt=4.10.4 mayavi=4.4.0 vtk=5.10.1)
#    * the `use_depth_peeling=1` got no effect. Transparency is not correct.
#    * requires `import pyface.qt` or similar workaround
#
# or
#
#   conda create --name mayavi_test_py3 python=3.6 matplotlib
#   conda activate mayavi_test_py3
#   pip install mayavi
#生成数据
将numpy作为np导入
x=np.arange(-2,2,0.1)
y=np.arange(-2,2,0.1)
mx,my=np.meshgrid(x,y,index='ij')
mz1=np.abs(mx)+np.abs(my)
mz2=mx**2+my**2
#“API'QString'的修复程序已设置为版本1”
#看https://github.com/enthought/pyface/issues/286#issuecomment-335436808
从系统导入版本信息
如果版本信息[0]<3:
导入pyface.qt
def v1_matplotlib():
从matplotlib导入pyplot作为plt
从mpl_toolkits.mplot3d导入Axes3D
图=plt.图()
ax=图gca(投影=3d')
surf1=最大绘图曲面(mx,my,mz1,cmap='winter')
surf2=最大绘图曲面(mx,my,mz2,cmap='秋')
ax.view_init(方位角=60,标高=16)
图2(图3)
def v2_mayavi(透明度):
来自mayavi import mlab
图=mlab.图()
ax_范围=[-2,2,-2,2,0,8]
ax_标度=[1.0,1.0,0.4]
ax\u范围=ax\u范围*np.重复(ax\u刻度,2)
surf3=mlab.surf(mx,my,mz1,colormap='Blues')
surf4=mlab.surf(mx,my,mz2,colormap='Oranges')
surf3.actor.actor.scale=最大刻度
surf4.actor.actor.scale=最大刻度
mlab.视图(60,74,17,[-2.5,-4.6,-0.3])
轮廓线(surf3,颜色=(.7,.7,.7),范围=最大范围)
mlab.轴(surf3,颜色=(.7,.7,.7),范围=最大范围,
范围=最大范围,
xlabel='x',ylabel='y',zlabel='z')
如果透明:
surf3.actor.property.opacity=0.5
surf4.actor.property.opacity=0.5
图.scene.renderer.use_depth_seeling=1
v1_matplotlib()
v2_mayavi(假)
v2_mayavi(真实)
#要安装mayavi,以下内容目前适用于我(Windows 10):
#
#conda create--name mayavi_test_py2 python=2.7 matplotlib mayavi=4.4.0
#(安装pyqt=4.10.4 mayavi=4.4.0 vtk=5.10.1)
#*使用深度剥皮=1没有效果。透明度是不正确的。
#*需要“import pyface.qt”或类似的解决方法
#
#或
#
#conda create——名称mayavi_test_py3 python=3.6 matplotlib
#conda激活mayavi_测试_py3
#pip安装mayavi

可以手动修复此问题。这显然不是最干净的解决方案,但它能给你想要的。假设您要为公共X和Y绘制Z1和Z2

  • 创建一个数组Z1_gte,作为Z1的副本,其中Z1>=Z2,并且 np.nan另有规定
  • 创建阵列Z1_lte,作为Z1的副本,其中
    Z1另一个可能对某些应用有用的技巧是将曲面更改为一种颜色,将两个曲面的alpha值都更改为0.5,然后通过旋转曲面,至少可以了解到正在发生的事情。如果您正在调试交叉曲面,或者像我的情况一样,如果您想检查尖峰的平滑效果,那么这会很快。蓝色是下面的平滑表面,红色是原始表面


    您可以通过同时绘制这两个图形来避免此问题。只需附加两个矩阵并为它们指定单独的颜色

    def plotTwo(ax, X, Y, Z1, Z2):
        col1 = np.full(Z1.shape, 'b', dtype='U50')
        col2 = np.full(Z2.shape, 'r', dtype='U50')
        ax[2].plot_surface(np.append(X, X, axis=0),
                          np.append(Y, Y, axis=0),
                          np.append(Z1, Z2, axis=0),
                          facecolors= np.append(col1, col2, axis=0),
                          edgecolor='none', alpha=1)
    

    谢谢你的回答!但这并不是我想要达到的目标。我希望较近的曲面(即z轴值较大的曲面)位于前面。由于目前的图表,解释数据非常混乱。在第一个图中,蓝绿色的表面大部分应该隐藏在黄红色的表面后面,事实上,它显示在前面。我可以最后绘制黄色-红色表面,使其位于前面,但这对于图中蓝绿色表面的z轴值较大的其他区域来说是不正确的。@Andrewspuncer我建议查看Enthough的
    mayavi
    ,我认为这不是一个bug,而是一个缺少的特性。据我所知,所有的3D绘图都是一种技巧@安德鲁斯彭斯·马亚维并没有看上去那么可怕。这个问题仍然存在
    def plotTwo(ax, X, Y, Z1, Z2):
        col1 = np.full(Z1.shape, 'b', dtype='U50')
        col2 = np.full(Z2.shape, 'r', dtype='U50')
        ax[2].plot_surface(np.append(X, X, axis=0),
                          np.append(Y, Y, axis=0),
                          np.append(Z1, Z2, axis=0),
                          facecolors= np.append(col1, col2, axis=0),
                          edgecolor='none', alpha=1)