【问题标题】:drawing a line on a 3D plot in matplotlib在 matplotlib 的 3D 图上画一条线
【发布时间】:2013-12-26 08:50:16
【问题描述】:

我有一个看起来与 this one 非常相似的 3D 图,但我想在底部等高线图上添加两条线。我希望两条线交叉并指向一个特定的 (x,y) 值。

我可以在那里画一条线,但它总是在等高线图的下方,尽管我做了无数次尝试。谁能帮我在等高线图上画线 on?我在下面粘贴我的代码。该线仅在其突出轮廓的部分可见。

#!/usr/bin/env python

import sys, re, math
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import LineCollection
from matplotlib import cm
from matplotlib.mlab import griddata
import numpy as np

x = []
y = []
z = []
for i in range(0,628,10) :
  for j in range(0,628,10) :
    x.append(i*0.01)
    y.append(j*0.01)
    z.append(math.sin(x[-1]*y[-1])*20)

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

xi = np.linspace(min(x), max(x))
yi = np.linspace(min(y), max(y))

X, Y = np.meshgrid(xi, yi)
Z = griddata(x, y, z, xi, yi)
ax.autoscale(False)
ax.view_init(elev=30, azim=-140)

surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.cool,
               linewidth=0.1, antialiased=True, shade=True,alpha=0.8)
cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.cool, cstride=1,
        linewidth=0.1, antialiased=True, shade=True)

ax.set_xlim3d(0, math.pi*2)
ax.set_ylim3d(0, math.pi*2)
ax.set_zlim3d(-100, 20)

xi = [0,6]
yi = [3,3]
l=zip(xi,yi)
lines = LineCollection((l,l),zorder=10000,color='k')
ax.add_collection3d(lines,zs=-90)

plt.show()

【问题讨论】:

    标签: 3d matplotlib


    【解决方案1】:

    因为 Axe3D 将通过 3d 投影为每个 3d 对象计算 zorder 属性。要禁用此功能,您可以创建 FixZorderCollection 类并更改 3d 线的 __class__ 属性。这是一个完整的例子:

    import sys, re, math
    import matplotlib.pyplot as plt
    from mpl_toolkits.mplot3d import Axes3D
    from matplotlib.collections import LineCollection
    from matplotlib import cm
    from matplotlib.mlab import griddata
    import numpy as np
    
    x = []
    y = []
    z = []
    for i in range(0,628,10) :
      for j in range(0,628,10) :
        x.append(i*0.01)
        y.append(j*0.01)
        z.append(math.sin(x[-1]*y[-1])*20)
    
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    
    xi = np.linspace(min(x), max(x))
    yi = np.linspace(min(y), max(y))
    
    X, Y = np.meshgrid(xi, yi)
    Z = griddata(x, y, z, xi, yi)
    ax.autoscale(False)
    ax.view_init(elev=30, azim=-140)
    
    surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.cool,
                   linewidth=0.1, antialiased=True, shade=True,alpha=0.8)
    cset = ax.contourf(X, Y, Z, zdir='z', offset=-100, cmap=cm.cool, cstride=1,
            linewidth=0.1, antialiased=True, shade=True)
    
    ax.set_xlim3d(0, math.pi*2)
    ax.set_ylim3d(0, math.pi*2)
    ax.set_zlim3d(-100, 20)
    
    xi = [0,6]
    yi = [3,3]
    l=zip(xi,yi)
    lines = LineCollection((l,l),zorder=1000,color='k',lw=3)
    ax.add_collection3d(lines,zs=-90)
    
    from mpl_toolkits.mplot3d.art3d import Line3DCollection
    
    class FixZorderCollection(Line3DCollection):
        _zorder = 1000
    
        @property
        def zorder(self):
            return self._zorder
    
        @zorder.setter
        def zorder(self, value):
            pass
    
    ax.collections[-1].__class__ = FixZorderCollection
    
    plt.show()
    

    输出:

    【讨论】:

    • 但是我怎样才能使这个技巧与散点图一起使用呢?我需要在轮廓部分标记几个点。我以为我会在 contourf 的顶部绘制一个散点图,但它隐藏在 contourf 的下方
    【解决方案2】:

    HYRY 的回答帮助了我。由于 tnorgd 想知道如何处理散点图(我还不能发表评论),所以我在这里给出了答案。 pyplot.scatter 在投影“3d”中创建 Patch3DCollection。所以同样的技巧也会奏效:

    from mpl_toolkits.mplot3d.art3d import Patch3DCollection
    class FixZorderScatter(Patch3DCollection):
        _zorder = 2000
        @property
        def zorder(self):
            return self._zorder
        @zorder.setter
        def zorder(self, value):
            pass
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      • 2012-04-20
      • 2011-12-17
      • 2016-07-27
      • 2011-09-30
      相关资源
      最近更新 更多