Matplotlib绘制非凸星形域XYZ散点数据热力图实现方案
非凸星形区域不规则采样点热力图实现方案
失效原因
常规griddata、无掩码contour类方法无法正确绘制该图形的核心原因:
- 目标星形为非凸凹多边形,默认三角剖分会在凹口位置生成跨区域的三角形,把区域外的空间纳入插值计算
- 未做区域范围掩码,区域外的错误插值结果会被直接绘制,出现图形溢出、错乱的问题
实现思路
- 基于给定的星形边界坐标,创建多边形路径对象,用于判断任意坐标点是否在区域内部
- 生成覆盖整个星形范围的高密度规则网格
- 基于离散采样点做三角插值,得到所有网格点对应的Z值
- 用多边形掩码过滤掉区域外的网格值,将其设为空值
np.nan,绘制时自动跳过这部分内容 - 渲染热力图,叠加边界线、可选的采样点标记,调整坐标轴比例避免图形变形
完整可运行代码
import numpy as np import matplotlib.pyplot as plt from matplotlib.tri import Triangulation, LinearTriInterpolator from matplotlib.path import Path # 原始输入数据 coords= [(0.5, 0.0), (0.8660254037844387, 0.49999999999999994), (0.25000000000000006, 0.4330127018922193), (6.123233995736766e-17, 1.0), (-0.2499999999999999, 0.43301270189221935), (-0.8660254037844385, 0.5000000000000003), (-0.5, 6.123233995736766e-17), (-0.8660254037844388, -0.4999999999999997), (-0.2500000000000002, -0.4330127018922192), (-1.8369701987210297e-16, -1.0), (0.24999999999999967, -0.4330127018922195), (0.8660254037844384, -0.5000000000000004), (0.5, -1.2246467991473532e-16)] X = np.array([-0.10885458, 0.38719084, 0.126246 , 0.32831633, -0.43470323, -0.14589308, 0.03527489, -0.30802489, 0.03631802, -0.6407443 , 0.1420586 , -0.04242902, 0.56713419, 0.03697127, 0.56324232, -0.17307027, 0.23414952, -0.1249898 , 0.10993816, -0.15574171, 0.22480668, -0.16938372, 0.46415079, 0.05454076, 0.63360403, -0.43812225, 0.39817569, -0.31963035, -0.31926434, 0.16913435, 0.68687168, -0.14839105, 0.53042922, -0.04944691, -0.20848955, 0.60348851, -0.23746634, -0.00968032, -0.63404439, -0.05204527, 0.27697056, -0.0023835 , -0.60480204, -0.29335925, 0.08750121, 0.13853292, 0.01434203, -0.51095204, 0.17537239, -0.21610341]) Y = np.array([-0.10566327, 0.36444335, 0.50664288, 0.34520176, 0.12666237, 0.24523639, 0.45936775, 0.36855297, -0.89093646, 0.25080176, -0.21871761, 0.56413549, -0.37842424, -0.85040143, 0.28691973, -0.02916441, 0.20025945, -0.25469069, 0.52055077, -0.23973923, -0.03349382, -0.4850852 , -0.22147722, 0.82357372, 0.19736351, 0.16366808, -0.30763208, -0.07932644, 0.18458957, 0.19116663, -0.37589083, -0.62173701, -0.08265561, 0.28642521, -0.3096187 , 0.18280694, 0.0287418 , -0.35277588, 0.41465303, 0.77087622, -0.20084426, 0.72120447, -0.29936638, 0.39579946, 0.35693334, 0.41785566, -0.39066645, 0.01689062, 0.25396642, 0.12154352]) Z = np.array([0.36857377, 0.08481739, 0.08529314, 0.09577443, 0.12750615, 0.22158901, 0.18614892, 0.0703758 , 0.0111191 , 0.03745636, 0.24347694, 0.13703608, 0.08855241, 0.03235803, 0.11979384, 0.33964959, 0.23354923, 0.23385712, 0.09479431, 0.22835837, 0.29181292, 0.0550857 , 0.15981413, 0.02425207, 0.01008352, 0.14666378, 0.14105369, 0.20266958, 0.25451451, 0.25561241, 0.07160838, 0.0181599 , 0.02512438, 0.25329402, 0.14160124, 0.02455915, 0.275493 , 0.25261528, 0.05976918, 0.04502752, 0.23377016, 0.11031544, 0.09229812, 0.04252507, 0.1807899 , 0.11100155, 0.23271334, 0.00184005, 0.19467501, 0.31437854]) # 生成星形边界路径,用于区域掩码 star_path = Path(coords) # 生成高密度规则插值网格 x_min, x_max = -1.1, 1.1 y_min, y_max = -1.1, 1.1 grid_res = 300 xi, yi = np.meshgrid(np.linspace(x_min, x_max, grid_res), np.linspace(y_min, y_max, grid_res)) # 判断网格点是否在星形区域内部 grid_points = np.vstack([xi.flatten(), yi.flatten()]).T in_region_mask = star_path.contains_points(grid_points).reshape(xi.shape) # 基于采样点做三角插值 tri = Triangulation(X, Y) interp = LinearTriInterpolator(tri, Z) zi = interp(xi, yi) # 将区域外的插值结果设为空值,不参与绘制 zi[~in_region_mask] = np.nan # 绘制图形 plt.figure(figsize=(7,7), dpi=100) # 绘制平滑热力图 heatmap = plt.pcolormesh(xi, yi, zi, cmap='viridis', shading='gouraud') # 绘制白色星形边界 bound_x, bound_y = zip(*coords) plt.plot(bound_x, bound_y, color='white', linewidth=2) # 可选:叠加原始采样点 plt.scatter(X, Y, s=15, color='white', edgecolor='black', zorder=3) # 添加色条 plt.colorbar(heatmap, label='Z值') # 设置等比例坐标轴避免星形变形 plt.gca().set_aspect('equal') plt.xlim(x_min, x_max) plt.ylim(y_min, y_max) plt.axis('off') plt.show()
调参说明
- 配色修改:替换
pcolormesh的cmap参数即可,彩虹热力图用cmap='jet',感知均匀配色用cmap='viridis' - 平滑度调整:将线性插值器
LinearTriInterpolator替换为CubicTriInterpolator即可得到三次平滑插值结果,色彩过渡更自然 - 图形样式:需要显示坐标轴就删除
plt.axis('off'),不需要显示采样点就删除对应的scatter代码 - 等值线效果:将
pcolormesh替换为contourf,可自定义levels参数调整等值线层级 - 该方案可适配任意不规则多边形区域,包括带孔洞的复杂区域,仅需在
Path对象中补充对应孔洞的路径定义即可
内容的提问来源于stack exchange,提问作者Basilique
相关产品推荐
相关产品推荐

