You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Cartopy绘制大圈出现分裂问题求助

解决Shapely多边形在PlateCarree投影中填充分裂的问题

问题原因

当cgeod.Geodesic().circle()生成的圆形多边形跨越180°经线(或投影的中央经线边界)时,Shapely多边形的点列顺序会导致Matplotlib的填充逻辑出错,表现为图形沿纬线分裂并填充了错误的区域(实际填充了圆形外部而非内部)。

解决方案

方法1:调整投影中央经线,避免多边形跨边界

将投影的中央经线设置为丹佛的经度,让生成的圆形完全处于投影的可视范围内,避免跨边界导致的填充异常:

cm = -104.985  # 使用丹佛的经度作为投影中央经线
proj = crs.PlateCarree(central_longitude=cm)

方法2:修复多边形并选择正确的填充区域

若必须使用中央经线为0的投影,可通过修复多边形环方向、判断面积来选择需要填充的圆形内部区域:

# 生成圆形点后处理多边形
circle_points = cgeod.Geodesic().circle(lon=site_lon, lat=site_lat, radius=dFOV, n_samples=1000, endpoint=False)
# 修复无效的多边形环
geom = shapely.geometry.Polygon(circle_points).buffer(0)
# 筛选出面积较小的区域(即圆形内部,大的是地球剩余区域)
if geom.area > 1e10:
    full_earth = shapely.geometry.box(-180, -90, 180, 90)
    geom = full_earth.difference(geom)

完整修正代码(方法1示例)

import numpy as np
import cartopy.geodesic as cgeod
import cartopy.crs as crs
import cartopy.feature as cfeature
import shapely
import matplotlib.pyplot as plt

# SET CONSTANTS
RE = 6371008.8 # meters, WGS84 Sphere
h = 35786000.0 # meters, GEO

def arc_dist_to_FOV(h, ah):
    a = (np.pi/180)*(90 + ah) # radians
    b = np.arcsin(RE * np.sin(a)/(RE + h)) # radians
    g = np.pi - a - b # radians
    d = (180/np.pi)*g*RE
    return d

# 用丹佛经度作为中央经线,避免多边形跨投影边界
cm = -104.985
proj = crs.PlateCarree(central_longitude=cm)
fig = plt.figure(figsize=(10,8))
ax = fig.add_subplot(1,1,1, projection=proj)

ax.set_global()

ax.add_feature(cfeature.COASTLINE, edgecolor='black')
ax.add_feature(cfeature.BORDERS, edgecolor='black')
ax.add_feature(cfeature.STATES, edgecolor='black')

ax.stock_img()
ax.gridlines(draw_labels=True, crs=proj)
lat, lon = 39.7392, -104.985

plt.scatter(x=lon, y=lat, color='blue', s=10, transform=proj)

# COMPUTE FOV
ah = 20 # degrees above horizon
dFOV = arc_dist_to_FOV(h, ah)
site_lat = lat
site_lon = lon
    
# ADD SHAPES TO MAP
circle_points = cgeod.Geodesic().circle(lon=site_lon, lat=site_lat, radius=dFOV, n_samples=1000, endpoint=False)
geom = shapely.geometry.Polygon(circle_points)
ax.add_geometries((geom,), crs=proj, alpha=0.5, facecolor='red', edgecolor='black', linewidth=1)

plt.show()

内容的提问来源于stack exchange,提问作者DoomedJupiter

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 00:00:25