球面非结构化经纬度网格Delaunay三角化绘图间隙问题求助
解决北极立体投影下Delaunay三角化的0°/360°间隙问题
你的问题核心是:在PlateCarree(经纬度)坐标系下做Delaunay三角化时,0°/360°经线在平面上是断开的(-180°和180°为平面两端),导致跨该经线的点无法被三角化连接,投影到北极立体投影后出现间隙。以下两种方法可以解决这个问题:
方法1:复制边界点扩展经度范围
通过复制0°经线附近的点,将其经度偏移±360°,让这些点在平面坐标系下相邻,从而让Delaunay生成跨边界的三角形。
修改后的代码:
import numpy as np import pandas as pd from scipy.spatial import Delaunay import geoviews as gv import holoviews as hv import cartopy.crs as ccrs def triangulate(vertices, x="Longitude", y="Latitude"): triang = Delaunay(vertices[[x, y]].values) return pd.DataFrame(triang.simplices, columns=['v0', 'v1', 'v2']) # 原数据处理 x = ((np.rad2deg(data.clon) - 180) % 360) - 180 y = np.rad2deg(data.clat) value = data[attr][t][i] # 生成原始顶点 verts = pd.DataFrame({'Longitude': x, 'Latitude': y, 'value': value}) # 复制0°经线附近的点(可根据数据密度调整阈值,这里用±10°) boundary_mask = verts['Longitude'].abs() < 10 boundary_verts = verts[boundary_mask].copy() # 生成经度偏移±360°的副本 boundary_verts_plus = boundary_verts.assign(Longitude=lambda df: df['Longitude'] + 360) boundary_verts_minus = boundary_verts.assign(Longitude=lambda df: df['Longitude'] - 360) # 合并扩展顶点集 extended_verts = pd.concat([verts, boundary_verts_plus, boundary_verts_minus], ignore_index=True) # 执行三角化 tris = triangulate(extended_verts) # 绘图:投影时偏移后的点会与原边界点重合,自动填补间隙 trimesh = rasterize(gv.TriMesh((tris, hv.Points(extended_verts, vdims='value')), crs=ccrs.PlateCarree())) trimesh.opts( cmap='Greys', fig_size=180, aspect=1, projection=ccrs.NorthPolarStereo() )
方法2:在目标投影坐标系下做三角化(推荐)
直接将经纬度转换为北极立体投影的平面坐标,再执行Delaunay三角化,彻底避开经度周期性问题。
修改后的代码:
import numpy as np import pandas as pd from scipy.spatial import Delaunay import geoviews as gv import holoviews as hv import cartopy.crs as ccrs def triangulate_proj(vertices, x="proj_x", y="proj_y"): triang = Delaunay(vertices[[x, y]].values) return pd.DataFrame(triang.simplices, columns=['v0', 'v1', 'v2']) # 原数据处理 x = ((np.rad2deg(data.clon) - 180) % 360) - 180 y = np.rad2deg(data.clat) value = data[attr][t][i] # 转换到北极立体投影坐标系 target_crs = ccrs.NorthPolarStereo() proj_coords = target_crs.transform_points(ccrs.PlateCarree(), x.values, y.values) # 提取投影后的平面坐标 verts_proj = pd.DataFrame({ 'proj_x': proj_coords[:, 0], 'proj_y': proj_coords[:, 1], 'value': value }) # 在投影坐标下执行三角化 tris_proj = triangulate_proj(verts_proj) # 绘图 trimesh_proj = rasterize(gv.TriMesh((tris_proj, hv.Points(verts_proj, vdims='value')))) trimesh_proj.opts( cmap='Greys', fig_size=180, aspect=1, projection=target_crs )
方法对比
- 复制边界点:保留经纬度坐标系的三角化结果,适合后续需要基于经纬度的操作,但需手动调整边界阈值。
- 投影后三角化:彻底规避经度周期性问题,三角化结果更贴合北极投影的空间关系,是更可靠的方案。
内容的提问来源于stack exchange,提问作者menaiseen
相关产品推荐
相关产品推荐

