Почему аннотирование сработало неожиданно здесь, в картопаде?
Код первый:
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.Mercator())
ax.set_extent([72, 135, 18, 53])
ax.annotate('hello', xy=(100, 49), xycoords='data',
transform=ccrs.PlateCarree(), zorder=12)
plt.show()
Результат не ожидаемый, и у меня есть другие сомнения относительно моего подхода. Итак, мои вопросы:
Если я хочу построить карту, она выглядит как веб-карта (например, карта Google). Область карты, возможно, такая же большая, как Китай, в основном не глобальная. После поиска в Интернете эти сайты в основном используют проекцию "веб-меркатора". Так что я полагаю, я должен использовать
plt.axes(projection=ccrs.Mercator()
здесь я прав? Или что мне использовать, если я не прав?Данные координат, которые я хочу построить, похожи на 121°E, 49°N(преобразуют градус в десятичную перед построением курса), не проецируются, система координат WGS84, вероятно, из GPS. Так что я прав, чтобы использовать
transform=ccrs.PlateCarree()
? Или что мне использовать, если я не прав?annotate
выше ничего не показывает. После комментарияax.set_extent
строка, текст "привет" отображается в нулевой (0, 0) точке. Что я хочу, это в точке (100°E, 49°N) Как это исправить?
1 ответ
Во-первых, спасибо за код, это намного облегчает задачу.
Честно говоря, я не думаю, что аннотирование использовалось всерьез с Cartopy раньше, поэтому, вероятно, именно поэтому вы сталкиваетесь с этой проблемой - вы тратите время;)
Похоже, что Matplotlib Axes.annotate
здесь виноват метод - он уничтожает преобразование, переданное через https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/axes/_axes.py. Это происходит главным образом потому, что у annotate есть специальные ключевые слова для независимого определения преобразования как координаты, так и позиции текста (см. xycoords
а также textcoords
в http://matplotlib.org/users/annotations_intro.html).
Когда мы углубимся в класс Annotate, мы обнаружим, что Annotate _get_xy_transform
( https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/text.py) может обрабатывать различные (некоторые недокументированные) формы как значения для textcoords
, включая экземпляры преобразования.
Хорошо, пока, все хорошо. Казалось бы, вы можете просто через систему координат xycoords
и все должно быть неуклюжим К сожалению, однако, annotate не знает, как преобразовать систему координат Cartopy в преобразование matplotlib так, как это делает большая часть остальной части matplotlib, поэтому мы собираемся сделать это для функции annotate заранее.
Чтобы создать преобразование matplotlib из любой картографической системы координат для любых осей, мы можем просто сделать:
ax = plt.axes(projection=ccrs.Mercator())
crs = ccrs.PlateCarree()
transform = crs._as_mpl_transform(ax)
Теперь мы можем передать это преобразование методу annotate, и мы должны получить текст и стрелку в ожидаемом месте. Я взял несколько свобод, чтобы выделить некоторые функциональные возможности аннотирования, пока я в нем:
import cartopy.feature
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.Mercator())
ax.set_extent([65, 125, 5, 40])
ax.add_feature(cartopy.feature.OCEAN)
ax.add_feature(cartopy.feature.LAND)
ax.add_feature(cartopy.feature.BORDERS, linestyle=':', edgecolor='gray')
ax.coastlines()
ax.plot(116.4, 39.95, 'ob', transform=ccrs.PlateCarree())
transform = ccrs.PlateCarree()._as_mpl_transform(ax)
ax.annotate('Beijing', xy=(116.4, 39.9), xycoords=transform,
ha='right', va='top')
ax.annotate('Delhi', xy=(113, 40.5), xytext=(77.23, 28.61),
arrowprops=dict(facecolor='gray',
arrowstyle="simple",
connectionstyle="arc3,rad=-0.2",
alpha=0.5),
xycoords=transform,
ha='right', va='top')
plt.show()
В ответ на другие ваши вопросы:
Если я хочу построить карту выглядит как веб-карта (например, карта Google)
В cartopy.crs появилась новая константа, которая точно определила Google Mercator (cartopy.crs.GOOGLE_MERCATOR
). Это просто пример проекции Меркатора с несколькими настройками, чтобы сделать его в точности как Google Mercator ( https://github.com/SciTools/cartopy/blob/master/lib/cartopy/crs.py).
Данные координат, которые я хочу построить, похожи на 121°E, 49°N(преобразуют градус в десятичную перед построением курса), не проецируются, система координат WGS84, вероятно, из GPS. Так правильно ли я использовать transform=ccrs.PlateCarree()? Или что мне использовать, если я не прав?
Я бы посоветовал вам лучше использовать геодезическую систему координат - эта система координат по умолчанию использует базовую точку WGS84, которая даст вам наиболее точное представление ваших широт и долгот WGS84. Хотя в масштабе, который вы сейчас рисуете, я полагаю, вам будет трудно заметить разницу (максимальная разница составляет около 22 км в средних широтах).
НТН,