Basemap中正射投影绘制EEZ shapefile图形模糊问题求助
解决Basemap正射投影绘制全球EEZ Shapefile的模糊拖影问题
嘿,我来帮你搞定这个正射投影下EEZ shapefile的模糊拖影问题!首先得搞清楚根源:正射投影只能展示半个地球,而你用的全球EEZ数据包含了整个地球的多边形,那些位于当前视图背面的多边形,在投影转换时会被“折叠”到可见区域的边缘,从而产生模糊的拖影效果。下面给你两种可行的解决方案,先解决全量绘制的问题,之后筛选特定区域就轻松多了。
方法一:用shapefile库逐个过滤可见多边形
这种方法不需要额外依赖,直接基于你现有的工具,手动判断每个EEZ多边形是否在当前正射视图的可见范围内,只绘制符合条件的部分:
import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap import shapefile fig = plt.figure(figsize=(20,12)) ax = fig.add_subplot(111) # 创建正射投影地图 Map = Basemap(projection='ortho', lon_0=0, lat_0=0, resolution='l') Map.drawcoastlines(zorder=10) Map.drawcountries(zorder=10) Map.drawmapboundary() # 读取shapefile但不直接绘制 sf = shapefile.Reader('~/EEZ_Boundaries/EEZ_land_v2_201410') shapes = sf.shapes() records = sf.records() # 遍历每个EEZ多边形,筛选并绘制可见部分 for shape, record in zip(shapes, records): # 获取多边形的经纬度坐标 coords = shape.points # 计算多边形的中心经纬度,用来判断是否在可见半球 lon_avg = sum(p[0] for p in coords) / len(coords) lat_avg = sum(p[1] for p in coords) / len(coords) # 将中心坐标转换为投影坐标 cx, cy = Map(lon_avg, lat_avg) # 判断中心是否在当前地图的可见范围内 if Map.xmin <= cx <= Map.xmax and Map.ymin <= cy <= Map.ymax: # 将整个多边形的坐标转换为投影坐标并绘制 x, y = Map([p[0] for p in coords], [p[1] for p in coords]) ax.fill(x, y, alpha=0.5, zorder=5) # alpha调整透明度,避免遮挡海岸线 plt.show()
方法二:用Geopandas预处理数据(更高效)
如果你的环境安装了Geopandas和PyProj,可以先对全球EEZ数据做预处理,直接筛选出正射视图可见的区域,再用Basemap绘制,这种方法代码更简洁,处理大文件也更高效:
import matplotlib.pyplot as plt from mpl_toolkits.basemap import Basemap import geopandas as gpd import pyproj # 加载全球EEZ shapefile gdf = gpd.read_file('~/EEZ_Boundaries/EEZ_land_v2_201410') # 定义正射投影的坐标系(和Basemap的参数一致) ortho_crs = pyproj.CRS(f"+proj=ortho +lon_0=0 +lat_0=0 +a=6370997 +b=6370997 +units=m +no_defs") # 将EEZ数据转换为正射投影坐标系 gdf = gdf.to_crs(ortho_crs) # 筛选出中心在可见范围内的多边形(正射投影的坐标范围是±6370997米,对应地球半径) gdf = gdf[ gdf.geometry.centroid.x.between(-6370997, 6370997) & gdf.geometry.centroid.y.between(-6370997, 6370997) ] # 绘制地图 fig = plt.figure(figsize=(20,12)) ax = fig.add_subplot(111) Map = Basemap(projection='ortho', lon_0=0, lat_0=0, resolution='l') Map.drawcoastlines(zorder=10) Map.drawcountries(zorder=10) Map.drawmapboundary() # 遍历筛选后的EEZ多边形绘制 for geom in gdf.geometry: if geom.type == 'Polygon': coords = list(geom.exterior.coords) x, y = zip(*coords) ax.fill(x, y, alpha=0.5, zorder=5) elif geom.type == 'MultiPolygon': # 处理多面几何体 for poly in geom.geoms: coords = list(poly.exterior.coords) x, y = zip(*coords) ax.fill(x, y, alpha=0.5, zorder=5) plt.show()
关于位置偏移的问题
你之前手动绘制多边形出现位置偏移,大概率是因为没有正确将经纬度坐标转换为Basemap的投影坐标。上面两种方法里,我们要么用Map()函数转换经纬度到投影坐标,要么先通过Geopandas完成坐标转换,这样就能保证多边形位置准确。
等解决了全量绘制的模糊问题后,你只需要在筛选步骤里加上特定区域的条件(比如根据国家名称筛选),就能轻松绘制选定的EEZ区域啦~
内容的提问来源于stack exchange,提问作者victorO
相关产品推荐
相关产品推荐

