mjo*_*mjo 6 python matplotlib mplot3d
我正在使用 Matplotlib 设计一个三维插图。一切都很好,除了(红色)参数曲线得到错误的 zorder 而(绿色)参数曲面完全正确绘制。
由以下代码生成的输出:

我知道 Matplotlib 在准确计算对象的 zorder 方面的能力有限,但由于它可以为参数曲面执行此操作,因此它似乎是 Matplotlib 中的一个错误。
也就是说,有没有办法强制正确的 z-ordering 只是为了让事情快速工作?似乎我只能说正确的透明蓝色平面位于其他一切之上。但是,将 zorder 参数放入 PolyCollection 似乎没有任何效果,并且将显式 zorder 参数放入绘制读取线的绘图函数中会弄乱其相对于绿色表面的顺序。
有没有办法将正确的蓝色透明表面强加于一切之上?这是我到目前为止的代码:
#!/bin/env python3
from pylab import *
from mpl_toolkits.mplot3d import *
from matplotlib.collections import PolyCollection
from matplotlib.colors import colorConverter
from matplotlib.patches import FancyArrowPatch
rc('text', usetex=True)
rc('font', size=20)
fig = figure(figsize=(11,6))
ax = fig.gca(projection='3d')
ax.set_axis_off()
def f(x,t):
return t/2 * 0.55*(sin(2*x)+0.4*x**2-0.65)
c_plane = colorConverter.to_rgba('b', alpha=0.15)
N = 50
y = linspace(-1,1,N)
t = linspace(0,2,N)
yy, tt = meshgrid(y, t)
zz = f(yy,tt)
ax.plot(0*ones(y.shape), y, f(y,0), '-g', linewidth=3)
ax.plot(2*ones(y.shape), y, f(y,2), '-g', linewidth=3)
yt = 0.7*y
zt = f(yt, t) + 0.2*t
ax.plot(t, yt, zt, '-r', linewidth=3)
ax.plot((0,2), (yt[0], yt[-1]), (zt[0], zt[-1]), 'or')
ax.plot([2,2,2], [-1,yt[-1],yt[-1]], [zt[-1],zt[-1],-1], 'k--')
ax.plot(2*ones(y.shape), yt, f(yt,2)+0.1*(y+1), 'g:', linewidth=2)
ax.plot((2,2),
(yt[0], yt[-1]),
(f(yt[0], 2), f(yt[-1], 2) + 0.1*(y[-1]+1)), 'og')
ax.plot((0,2,2),
(-1,-1,zt[-1]),
(0,yt[-1],-1), 'ok')
ax.text(0, -1.1, 0, r'$p(0)=0$', ha='right', va='center')
ax.text(2, -1.05, zt[-1], r'$p(T)$', ha='right', va='center')
ax.text(0, -1.0, 1, r'$p$', ha='right', va='bottom')
ax.text(0, 1, -1.1, r'$q$', ha='center', va='top')
ax.text(0, -1, -1.1, r'$t=0$', ha='right', va='top')
ax.text(2, -1, -1.1, r'$t=T$', ha='right', va='top')
ax.text(2, yt[-1]-0.05, -1.05, r'$q(T)=q^*$', ha='left', va='top')
ax.text(0, 0.5, 0.05, r'$\mathcal{M}(0)$', ha='center', va='bottom')
ax.text(2, 0.1, -0.8, r'$\mathcal{M}(T)$', ha='center', va='bottom')
arrowprops = dict(mutation_scale=20,
linewidth=2,
arrowstyle='-|>',
color='k')
# For arrows, see
# /sf/ask/2043202871/
class Arrow3D(FancyArrowPatch):
def __init__(self, xs, ys, zs, *args, **kwargs):
FancyArrowPatch.__init__(self, (0,0), (0,0), *args, **kwargs)
self._verts3d = xs, ys, zs
def draw(self, renderer):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
FancyArrowPatch.draw(self, renderer)
a = Arrow3D([0,2], [-1,-1], [-1,-1], **arrowprops)
ax.add_artist(a)
a = Arrow3D([0,0], [-1,-1], [-1,1], **arrowprops)
ax.add_artist(a)
a = Arrow3D([0,0], [-1,1], [-1,-1], **arrowprops)
ax.add_artist(a)
# For surface illumination, see
# http://physicalmodelingwithpython.blogspot.de/2015/08/illuminating-surface-plots.html
# Get lighting object for shading surface plots.
from matplotlib.colors import LightSource
# Get colormaps to use with lighting object.
from matplotlib import cm
# Create an instance of a LightSource and use it to illuminate the surface.
light = LightSource(70, -120)
white = np.ones((zz.shape[0], zz.shape[1], 3))
illuminated_surface = light.shade_rgb(white*(0,1,0), zz)
ax.plot_surface(tt, yy, zz,
cstride=1, rstride=1,
alpha=0.3, facecolors=illuminated_surface,
linewidth=0)
verts = [array([(-1,-1), (-1,1), (1,1), (1,-1), (-1,-1)])]
poly = PolyCollection(verts, facecolors=c_plane)
ax.add_collection3d(poly, zs=[0], zdir='x')
poly = PolyCollection(verts, facecolors=c_plane)
ax.add_collection3d(poly, zs=[2], zdir='x')
ax.set_xlim3d(0, 2)
ax.view_init(elev=18, azim=-54)
show()
Run Code Online (Sandbox Code Playgroud)
小智 13
Matplotlib 3.5.0 中添加了使用 axis3d 更改绘图绘制顺序的方法。设置参数 'compulated_zorder' False 允许手动控制绘图顺序
ax = plt.axes(projection='3d',computed_zorder=False)
ax.plot_surface(X1, Y1, Z1,zorder=4.4)
ax.plot_surface(X2, Y2, Z2,zorder=4.5)
Run Code Online (Sandbox Code Playgroud)
较高的“zorders”绘制在顶部。一些常见的艺术家 z 顺序(这样您就不会在图例上绘制图例):
| 艺术家 | Z 顺序 |
|---|---|
| 图像(AxesImage、FigureImage、BboxImage) | 0 |
| 补丁、补丁集合 | 1 |
| Line2D、LineCollection(包括小刻度、网格线) | 2 |
| 主要蜱虫 | 2.01 |
| 文本(包括轴标签和标题) | 3 |
| 传奇 | 5 |
来自:https: //matplotlib.org/stable/gallery/misc/zorder_demo.html
来源: https: //github.com/matplotlib/matplotlib/commit/2db6a0429af47102456366f8d3a4df24352b252e(来自: https: //github.com/matplotlib/matplotlib/pull/14508)
Axes3D忽略zorder并按照它认为应该的顺序绘制所有艺术家。但是,您可以设置zorder=0红线和zorder=-1绿色表面(反之亦然),将它们放在右侧蓝色面板后面。
我的结果:
你必须知道:
轴的默认绘制顺序是面片、线条、文本。该顺序由 zorder 属性确定。设置了以下默认值
艺术家 Z 顺序
补丁/补丁集合 1
Line2D / LineCollection 2
文字3