如何在Basemap中绘制圆形?基于经纬度的绘图技术问询
嘿,我来帮你搞定Basemap里绘制圆形(基于经纬度)和添加Artist组件的问题!下面分两部分详细说明,附代码示例:
在Basemap中用经纬度+半径绘制圆形
因为Basemap是地理投影系统,直接用像素画圆会因为投影变形导致形状不对,所以需要结合投影转换来实现。这里有两种常用方法:
方法1:用matplotlib的Circle补丁(适合等距投影)
这种方法适合墨卡托(Mercator)这类等距投影,步骤是:
- 将圆心的经纬度转换为地图投影的x、y坐标
- 将半径(通常是千米)转换为投影坐标系的单位(比如米,墨卡托投影默认单位是米)
- 创建
Circle补丁并添加到Basemap的axes中
代码示例:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from matplotlib.patches import Circle # 初始化Basemap(墨卡托投影) bm = Basemap(projection='merc', llcrnrlat=-80, urcrnrlat=80, llcrnrlon=-180, urcrnrlon=180, resolution='l') # 绘制基础地图元素 bm.drawcoastlines(linewidth=0.5) bm.drawcountries() # 定义参数:圆心经纬度 + 半径(千米) center_lon, center_lat = 116.4, 39.9 # 北京坐标 radius_km = 500 # 经纬度转投影坐标 x_center, y_center = bm(center_lon, center_lat) # 半径转米(墨卡托投影单位为米) radius_m = radius_km * 1000 # 创建圆形补丁并添加到地图 circle = Circle((x_center, y_center), radius_m, color='crimson', fill=False, linewidth=2) bm.ax.add_patch(circle) plt.title('Circle on Basemap (Mercator Projection)') plt.show()
方法2:生成圆形经纬度点后绘制(适合所有投影)
如果用的是兰伯特、阿尔伯斯这类非等距投影,用Circle画出来的会是椭圆,这时候可以先计算圆上的经纬度点,再转换为投影坐标绘制,这样更贴合球面地理:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt import numpy as np # 初始化兰伯特投影的Basemap bm = Basemap(projection='lcc', lat_1=30, lat_2=60, lon_0=105, llcrnrlat=10, urcrnrlat=55, llcrnrlon=70, urcrnrlon=140, resolution='l') bm.drawcoastlines() bm.drawcountries() center_lon, center_lat = 116.4, 39.9 radius_km = 500 # 生成圆上的角度数组 theta = np.linspace(0, 2*np.pi, 100) # 计算圆上的经纬度(考虑球面曲率:经度方向1度≈111.32km,纬度方向需乘以cos(lat)) lon_points = center_lon + (radius_km / 111.32) * np.cos(theta) lat_points = center_lat + (radius_km / (111.32 * np.cos(np.radians(center_lat)))) * np.sin(theta) # 转换为投影坐标并绘制 x_points, y_points = bm(lon_points, lat_points) bm.plot(x_points, y_points, color='navy', linewidth=2) plt.title('Circle on Basemap (Lambert Projection)') plt.show()
给Basemap添加Artist组件
Basemap本质上是基于matplotlib的,它的bm.ax就是matplotlib的Axes对象,所以所有matplotlib的Artist组件(文本、矩形、箭头、补丁等)都可以直接添加,和普通matplotlib绘图逻辑一致:
示例代码:
from mpl_toolkits.basemap import Basemap import matplotlib.pyplot as plt from matplotlib.patches import Rectangle bm = Basemap(projection='merc', llcrnrlat=-80, urcrnrlat=80, llcrnrlon=-180, urcrnrlon=180, resolution='l') bm.drawcoastlines() # 1. 添加文本Artist x, y = bm(0, 0) # 赤道与本初子午线交点 bm.ax.text(x, y, 'Prime Meridian\nEquator', fontsize=10, ha='center', va='center', color='darkgreen') # 2. 添加矩形补丁 rect = Rectangle((bm(100, 20)), 2e6, 1.5e6, color='orange', alpha=0.3) bm.ax.add_patch(rect) # 3. 添加箭头Artist bm.ax.arrow(bm(-120, 30)[0], bm(-120, 30)[1], 1.5e6, 0, head_width=5e5, head_length=8e5, fc='purple', ec='purple') plt.show()
简单来说,只要拿到bm.ax,你就能用matplotlib的所有Artist工具来丰富你的地图啦!
内容的提问来源于stack exchange,提问作者Nazime Lakehal
相关产品推荐
相关产品推荐

