带剖面的 3D 曲面图

use*_*839 2 python graph matplotlib matplotlib-3d

基本上,我有一个由一组时间序列组成的曲面图,我想在特定高度添加剖面图,以更好地了解一年中值高于所选阈值的时期。

由此:

在此输入图像描述

其中显示平面但不是剖面

对此:

在此输入图像描述

有什么建议吗?

使用 alpha 和相机仰角并没有解决问题

在此输入图像描述

平面似乎仍然在人物的前面,而不是作为一个截面

Joh*_*anC 5

绘制只需3步

正如其他人指出的那样,matplotlib 的 3D 功能有些有限。为了将对象隐藏在其他对象后面,它使用画家算法。因此,对象只是从后到前绘制,并且没有对象部分放置在某个平面之前,部分放置在某个平面之后。Matplotlib 计算每个对象的平均深度来定义顺序。您可以通过 覆盖此订单ax.computed_zorder = False,因为自动计算并不总是如您所愿。

您可以自己绘制“图层”:

  • 3D表面
  • 然后飞机
  • 然后是顶部可见的 3D 表面部分

一个例子:

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.ndimage.filters import gaussian_filter

x = np.linspace(-10, 10, 51)
y = np.linspace(-10, 10, 51)
X, Y = np.meshgrid(x, y)
np.random.seed(20220201)
Z = np.random.rand(*X.shape) ** 5
Z[X ** 2 + Y ** 2 > 30] = 0
Z = gaussian_filter(Z, sigma=2) * 100

fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.computed_zorder = False
ax.plot_surface(X, Y, Z, cmap='turbo')
special_z = 16
ax.plot_surface(X, Y, np.full_like(Z, special_z), color='blue', alpha=0.4)
ax.plot_surface(X, Y, np.where(Z >= special_z, Z, np.nan), cmap='turbo', vmin=0)
plt.show()
Run Code Online (Sandbox Code Playgroud)

使用 matplotlib 部分隐藏 3D 表面

逐层绘制

另一种方法是一次绘制一层表面。左侧的示例显示了分为 30 层的表面,右侧的示例停在给定的高度,可视化交叉点。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from scipy.ndimage.filters import gaussian_filter

x = np.linspace(-10, 10, 51)
y = np.linspace(-10, 10, 51)
X, Y = np.meshgrid(x, y)
np.random.seed(20220201)
Z = np.random.rand(*X.shape) ** 5
Z[X ** 2 + Y ** 2 > 30] = 0
Z = gaussian_filter(Z, sigma=2) * 100

fig = plt.figure()
for which in ['left', 'right']:
    ax = fig.add_subplot(121 + (which == 'right'), projection="3d")
    ax.computed_zorder = False

    layers = np.linspace(Z.min(), Z.max(), 32)[1:-1]
    colors = plt.get_cmap('turbo', len(layers)).colors

    special_z = 16
    plane_drawn = False
    for layer, color in zip(layers, colors):
        if layer >= special_z and not plane_drawn:
            ax.plot_surface(X, Y, np.full_like(Z, special_z), color='blue', alpha=0.5, zorder=2)
            plane_drawn = True
        ax.contour(X, Y, Z, levels=[layer], offset=layer, colors=[color])
        if plane_drawn and which == 'right':
            break
plt.show()
Run Code Online (Sandbox Code Playgroud)

逐层绘制 3D 表面