You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Matplotlib实现基于阈值的三维曲面条件色图配置

Matplotlib 三维曲面按z阈值分区配色实现

核心实现逻辑是绕过全局色图映射,直接给每个曲面面片指定自定义颜色:先以基准值z0为界拆分Z值区间,分别对两个区间做归一化后映射到不同色系,再将生成的颜色数组传入plot_surface的facecolors参数即可。

实现步骤

  • 准备好三维网格数据X,Y,Z,定义分区基准阈值z0
  • 初始化和Z维度匹配的RGBA颜色数组
  • 对z < z0的区域做值归一化,映射到目标色系(示例为红色系Reds)
  • 对z > z0的区域做值归一化,映射到目标色系(示例为绿色系Greens)
  • 分界处z = z0可自定义中性色(示例用白色)做明确区分
  • 绘制曲面时传入自定义颜色数组,替换原有cmap参数配置

完整示例代码

import numpy as np
import matplotlib.pyplot as plt
from matplotlib import cm

# --------------- 数据和参数配置 ---------------
# 以下X/Y/Z可替换为你自己的三维数据集
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)
Z = np.sin(np.sqrt(X**2 + Y**2))  # 示例Z值

# 基准阈值替换为你的z0
z0 = 0

# --------------- 生成分区颜色 ---------------
face_colors = np.zeros(Z.shape + (4,))  # 四通道对应RGBA

# 低于z0区域:红色系渐变
z_low_mask = Z < z0
if np.any(z_low_mask):
    # 归一化:Z最小值对应红色最浅,z0对应红色最深
    low_norm = (Z[z_low_mask] - Z.min()) / (z0 - Z.min())
    face_colors[z_low_mask] = cm.Reds(low_norm)

# 高于z0区域:绿色系渐变
z_high_mask = Z > z0
if np.any(z_high_mask):
    # 归一化:z0对应绿色最浅,Z最大值对应绿色最深
    high_norm = (Z[z_high_mask] - z0) / (Z.max() - z0)
    face_colors[z_high_mask] = cm.Greens(high_norm)

# z=z0分界处设为白色
face_colors[Z == z0] = [1, 1, 1, 1]

# --------------- 绘制曲面 ---------------
fig = plt.figure(figsize=(10, 7))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(
    X, Y, Z,
    rstride=1, cstride=1,
    facecolors=face_colors,
    edgecolor='none'
)

# 可选:添加z0位置的黑色等高线强化分界
ax.contour3D(X, Y, Z, levels=[z0], colors='black', linewidths=2)

ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
plt.show()

注意事项

  • 如果你修改了rstride/cstride参数(即设置大于1的步长),需要先对Z数组按相同步长下采样,再生成对应维度的颜色数组,避免维度不匹配报错
  • 可根据需求替换色图,例如低于阈值用蓝色系cm.Blues、高于阈值用橙色系cm.Oranges,也可调整归一化范围修改颜色渐变的对比度
  • 该方案下默认全局颜色条无法准确表达两套色标,如需色标建议分别添加两个独立颜色条对应高低值区间

内容的提问来源于stack exchange,提问作者Daneel Olivaw

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.31 20:33:17