如何用Cartopy生成适配海报尺寸的旅行路线地图PDF
解决方案:适配画布比例的旅行地图海报生成
核心思路
要让地图填满固定尺寸的画布,关键是调整地理范围的宽高比,使其与画布的宽高比完全匹配,同时确保所有旅行点都被包含在内。避免使用bbox_inches='tight',因为它会篡改预设的画布尺寸。
具体操作逻辑:
- 先计算旅行点的原始地理边界,添加适当缓冲
- 对比地理范围宽高比与画布宽高比,扩展较小的维度(经度或纬度),使两者比例一致
- 保持旅行点在地图中心,确保所有点都在视野内
修改后的完整代码
import matplotlib.pyplot as plt import cartopy.crs as ccrs import numpy as np # 1. 定义旅行点(经度,纬度) points = np.array([ (18.4241, -33.9249), (9.5375, 33.8869), (-16.3151, 28.4682), (-9.1393, 38.7223), (-3.7038, 40.4168), (2.3522, 48.8566), (10.7522, 59.9139), ]) # 2. 自动选择横/竖版画布(也可手动固定尺寸) # 先计算原始地理范围的宽高比 lon_min_raw, lat_min_raw = points.min(axis=0) lon_max_raw, lat_max_raw = points.max(axis=0) geo_aspect_raw = (lon_max_raw - lon_min_raw) / (lat_max_raw - lat_min_raw) # 预设基础宽度,自动计算匹配的高度 base_width = 10 if geo_aspect_raw > 1: # 地理范围更宽,用横版 fig_width, fig_height = base_width, base_width / geo_aspect_raw else: # 地理范围更高,用竖版 fig_width, fig_height = base_width * geo_aspect_raw, base_width # 若需固定尺寸,直接替换上面的宽高设置即可,比如: # fig_width, fig_height = 12, 8 # 3. 创建画布与Mercator投影地图 fig, ax = plt.subplots(figsize=(fig_width, fig_height), subplot_kw={'projection': ccrs.Mercator()}) # 4. 计算带缓冲的初始地理范围 buffer = 1.0 # 给地图边缘留1度缓冲 lon_min = lon_min_raw - buffer lon_max = lon_max_raw + buffer lat_min = lat_min_raw - buffer lat_max = lat_max_raw + buffer # 5. 调整地理范围以适配画布比例 canvas_aspect = fig_width / fig_height geo_range_lon = lon_max - lon_min geo_range_lat = lat_max - lat_min geo_aspect = geo_range_lon / geo_range_lat if geo_aspect > canvas_aspect: # 地理范围过宽,扩展纬度范围 new_lat_range = geo_range_lon / canvas_aspect lat_mid = (lat_min + lat_max) / 2 lat_min = lat_mid - new_lat_range / 2 lat_max = lat_mid + new_lat_range / 2 else: # 地理范围过高,扩展经度范围 new_lon_range = geo_range_lat * canvas_aspect lon_mid = (lon_min + lon_max) / 2 lon_min = lon_mid - new_lon_range / 2 lon_max = lon_mid + new_lon_range / 2 # 6. 设置地图显示范围 ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=ccrs.PlateCarree()) # 7. 绘制旅行点与路线 ax.scatter(points[:, 0], points[:, 1], marker='o', color='red', s=50, transform=ccrs.Geodetic()) # 可选:添加旅行路线 ax.plot(points[:, 0], points[:, 1], color='blue', linewidth=2, transform=ccrs.Geodetic()) # 添加海岸线参考 ax.coastlines(resolution='10m') # 8. 保存PDF,严格保持画布尺寸 plt.savefig("travel_map.pdf", dpi=300, bbox_inches=None, pad_inches=0) plt.close()
关键细节说明
- 自动横竖版切换:通过原始地理范围的宽高比,自动计算画布尺寸,让地图方向自然适配旅行路线的分布
- 比例适配逻辑:始终以旅行点为中心扩展范围,确保所有点不会被移出视野,同时填满整个画布
- 输出控制:
pad_inches=0消除额外边距,dpi=300保证海报清晰度,bbox_inches=None强制使用预设的画布尺寸,完全避免尺寸偏差
内容的提问来源于stack exchange,提问作者Johannes_Sathre
相关产品推荐
相关产品推荐

