matplotlib 带剖面的三维曲面图

6jygbczu  于 2023-05-01  发布在  其他
关注(0)|答案(1)|浏览(155)

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

其中平面被示出但不是截面
为此:

有什么建议吗?
使用alpha和相机仰角并没有解决这个问题

平面看起来仍然是在图的前面,而不是作为一个部分

5cg8jx4n

5cg8jx4n1#

三步绘制

正如其他人指出的那样,matplotlib的3D功能有些有限。要将对象隐藏在其他对象后面,它使用painter's algorithm。所以,物体只是简单地从后往前画,没有物体被部分地放在某个平面的前面和后面。Matplotlib计算每个对象的平均深度来定义顺序。您可以通过ax.computed_zorder = False覆盖此订单,因为自动计算并不总是希望的。
你可以自己画“层”:

  • 三维表面
  • 然后是飞机
  • 然后是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()

逐层绘制

另一种方法可以是一次绘制一层表面。左边的示例显示了被划分为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()

相关问题