PyPlot ConnectionPatch между CartoPy GeoAxes - PullRequest
0 голосов
/ 17 июня 2020

ConnectionPatch - это удобный способ провести линию между двумя точками на двух разных осях ( демонстрация ). Можно ли использовать этот класс, когда одна (или обе) оси относятся к типу Cartopy GeoAxes? Ответ, связанный с , предлагает обходной путь, но я бы предпочел этого избежать.

1 Ответ

1 голос
/ 19 июня 2020

Не могу ответить на ваш вопрос об использовании этой классной штуки. Но если вы заинтересованы в построении линий между двумя разными геоосями Cartopy или между осями matplotlib и геоосями, этого можно достичь с помощью некоторого преобразования координат. Вот исполняемый код и выходной график. Я написал несколько комментариев в коде, чтобы помочь объяснить важные шаги.

Для получения дополнительной информации о системе координат и преобразовании:

Cartopy https://scitools.org.uk/cartopy/docs/latest/tutorials/understanding_transform.html

Так как Cartopy построен поверх Matplotlib, вам необходимо изучить связанную тему в Matplotlib.

Matplotlib https://matplotlib.org/3.2.1/tutorials/advanced/transforms_tutorial.html

import cartopy
import cartopy.mpl.geoaxes
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid1.inset_locator import inset_axes

fig, ax = plt.subplots()
fig.set_size_inches([8,8])  # 9,6; 8,9; 8,3 all OK

# Plot simple line on main axes
ax.plot([4,5,3,1,2])

p1 = [0.5,3.0]  # Bangkok text location
p2 = [0.5,2.75] # Himalaya text location
# Plot texts (Bangkok, Himalaya) on the main axes
ax.text(*p1, "Bangkok", ha='right')
ax.text(*p2, "Himalaya", ha='right')

# Ploting on UR inset map (cartopy) on the main axes (ax)
bkk_lon, bkk_lat = 100, 13       # Bangkok
hml_lon, hml_lat = 83.32, 29.22  # Everest peak

# Create cartopy geoaxes inset axes as part of the main axes 'ax'
axins = inset_axes(ax, width="40%", height="30%", loc="upper right", 
                   axes_class = cartopy.mpl.geoaxes.GeoAxes, 
                   axes_kwargs = dict(map_projection = cartopy.crs.PlateCarree()))

# Set map limits on that axes (for Thailand)
llx, lly = 95, 0
urx, ury = 110, 25
axins.set_xlim((llx, urx))
axins.set_ylim((lly, ury))
# Plot coastlines
axins.add_feature(cartopy.feature.COASTLINE)

# Plot line across the inset mao, LL to UR; OK
#ll_p, ur_p = [llx,urx], [lly,ury]
#axins.plot(ll_p, ur_p, "r--")

axins.plot(bkk_lon, bkk_lat, 'ro', transform=cartopy.crs.PlateCarree()) # OK!

# Create another inset map on the main axes (ax)
axins2 = inset_axes(ax, width="40%", height="30%", loc="lower left", 
               axes_class = cartopy.mpl.geoaxes.GeoAxes, 
               axes_kwargs = dict(map_projection = cartopy.crs.PlateCarree()))

# Set map limits on that axes (second inset map)
llx2, lly2 = -60, -20
urx2, ury2 = 120, 90
axins2.set_xlim((llx2, urx2))
axins2.set_ylim((lly2, ury2))
axins2.add_feature(cartopy.feature.COASTLINE)

# Plot line from UK to BKK, OK
#p21, p22 = [0, 100], [40, 13]
#axins2.plot(p21, p22, "r--")

# Plot blue dot at Himalaya
axins2.plot(hml_lon, hml_lat, "bo")

plt.draw() # Do this to get updated position

# Do coordinate transformation to get BKK, HML locations in display coordinates
# from axins_data_xy to dp_xy
dpxy_bkk_axins = axins.transData.transform((bkk_lon, bkk_lat)) # get display coordinates
# from axins2_data_xy to dp_xy
dpxy_bkk_axins2 = axins2.transData.transform((hml_lon, hml_lat)) # get display coordinates

# Do coordinate transformation to get BKK, HML locations in data coordinates of the main axes 'ax'
# from both dp_xy to main_ax_data
ur_bkk = ax.transData.inverted().transform( dpxy_bkk_axins )
ll_hml = ax.transData.inverted().transform( dpxy_bkk_axins2 )

# Prep coordinates for line connecting BKK to HML
xs = ur_bkk[0], ll_hml[0]
ys = ur_bkk[1], ll_hml[1]


xs = ur_bkk[0], ll_hml[0]
ys = ur_bkk[1], ll_hml[1]
ax.plot(xs, ys, 'g--') # from Bkk to Himalaya of different inset maps

# Plot lines from texts (on main axes) to locations on maps
ax.plot([p1[0], ur_bkk[0]], [p1[1], ur_bkk[1]], 'y--')
ax.plot([p2[0], ll_hml[0]], [p2[1], ll_hml[1]], 'y--')

# Set cartopy inset background invisible
axins.background_patch.set_visible(False)
axins2.background_patch.set_visible(False)

plt.show()

Выходной график : -

bkk to hml

...