When adding data (points, lines, text) to a GeoAxes, you must specify the coordinate system of your data using the transform keyword.
By default, Matplotlib assumes your data is in the same coordinate system as the map projection. However, most geographic data is provided in standard latitude/longitude coordinates. To plot this correctly, use an appropriate cartopy.crs.CRS instance (such as ccrs.PlateCarree() or ccrs.Geodetic()) in the transform argument of Matplotlib functions like plt.plot() or plt.text().
Key distinction:
ccrs.PlateCarree(): Represents a standard lat/lon projection where lines are drawn as straight lines in 2D Cartesian space.ccrs.Geodetic(): Represents a truly spherical coordinate system where lines are drawn as the shortest path (great circle) on the globe.
import cartopy.crs as ccrs
import matplotlib.pyplot as plt
ax = plt.axes(projection=ccrs.PlateCarree())
ax.stock_img()
ny_lon, ny_lat = -75, 43
delhi_lon, delhi_lat = 77.23, 28.61
# Plotting a great circle path (curved on a flat map)
plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
color='blue', linewidth=2, marker='o',
transform=ccrs.Geodetic(),
)
# Plotting a straight line in lat/lon space
plt.plot([ny_lon, delhi_lon], [ny_lat, delhi_lat],
color='gray', linestyle='--',
transform=ccrs.PlateCarree(),
)
plt.text(ny_lon - 3, ny_lat - 12, 'New York',
horizontalalignment='right',
transform=ccrs.Geodetic())
plt.text(delhi_lon + 3, delhi_lat - 12, 'Delhi',
horizontalalignment='left',
transform=ccrs.Geodetic())
plt.show()