在 matplotlib 中显示 Surface 前面的轮廓

Displaying Contours in front of Surface in matplotlib

我一直在四处寻找答案,但我似乎不明白为什么在我的代码中我无法让投影轮廓显示 "behind" 表面。

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.array([[200,800,1500,2000,3000],[200,700,1500,2000,3000],[200,800,1500,2000,3000],[200,800,1500,2000,3000]])
Y = np.array([[50,50,50,50,50],[350,350,350,350,350],[500,500,500,500,500],[1000,1000,1000,1000,1000]])
Z = np.array([[0,0,33,64,71],[44,62,69,74,76],[59,67,72,75,77],[63,68,73,76,77]])

ax.plot_surface(X, Y, Z, rstride=1, cstride=1, alpha=0.5)
cset = ax.contourf(X, Y, Z, zdir='z', offset=0, cmap=cm.coolwarm)
cset = ax.contourf(X, Y, Z, zdir='x', offset=200, cmap=cm.coolwarm)
cset = ax.contourf(X, Y, Z, zdir='y', offset=1000, cmap=cm.coolwarm)

ax.set_xlabel('X')
ax.set_xlim(200, 3000)
ax.set_ylabel('Y')
ax.set_ylim(0, 1000)
ax.set_zlabel('Z')
ax.set_zlim(0, 100)

plt.show()

我一直在使用此页面中的一个填充等高线图作为模板:http://matplotlib.org/mpl_toolkits/mplot3d/tutorial.html#scatter-plots

目前我能做的最好的就是改变轮廓的 alpha 值。我还尝试在等高线之后绘制曲面,但这并没有改变任何东西。

欢迎任何建议!

您遇到的问题是众所周知的bug/missing feature in matplotlib. Quoting a co-lead developer of matplotlib

As I understand it all the 3D plotting as a bit of a hack.

问题归结为连续的表面块是一个接一个地绘制的,这样每个表面要么完全落后于另一个,要么完全在它的前面。这意味着任何两个对象只能从特定角度正确绘制,并且不能保证所有对象都将以适当的顺序以合理的兴趣角度绘制。

人们会认为为各种对象设置 zorder 属性可能会影响结果,但是 this is not the case,因为

splitting up the plotting is that 'above' and 'below' are determined in a some what arcane way

in other words

Axes3D ignores zorder and draws artists in the order it thinks they should be.

这在各种 3d 绘图中都有体现,例如 plotting text with surfaces, , or even (尽管人们可能认为在单个函数调用中更容易确定绘图顺序)。

对于使用单个命令绘制的表面(即那些包含单个 Poly3DCollection 的表面),您可以使用 set_zsort() 方法向 matplotlib 提供有关首选绘图顺序的非常粗略的提示。除此之外,您唯一的选择是以问题不可见或至少不完全明显的方式移动您的表面和视角(如果可能的话)。 @tcaswell 提出的另一个选项是 to use mayavi 而不是 mplot3d(但我自己从未这样做过)。