问题
I have a map figure rendered with Cartopy and Matplotlib. I have a specific geometric coordinate (in lat/lon) and I would like to know the pixel coordinate closest to this geometric coordinate's projection (if it is visible), for instance to draw a graphic over the coordinate on the map.
(Note I don't want to draw with Matplotlib; I'm exporting the figure as a bitmap image and drawing in a different part of the pipeline.)
This documentation suggests it might be something like this:
import cartopy, matplotlib.pyplot
fig = matplotlib.pyplot.figure()
ax = fig.add_axes([0, 0, 1, 1], projection=cartopy.crs.Orthographic())
ax.add_feature(cartopy.feature.LAND, facecolor='black')
# Print the location of New York City in display coordinates
lon, lat = -74.0060, 40.7128
trans = cartopy.crs.Geodetic()._as_mpl_transform(ax)
x, y = trans.transform((lon, lat))
print(x, y)
# Or this way
projx, projy = ax.projection.transform_point(lon, lat, cartopy.crs.Geodetic())
x, y = ax.transData.transform((projx, projy))
print(x, y)
Though interestingly, if I plot this point, the figure centers on and zooms into Manhattan, and then the output display coordinates are indeed in the center of the figure at (640, 480).
matplotlib.pyplot.plot(lon, lat, marker='o', color='red', markersize=12,
alpha=0.7, transform=cartopy.crs.Geodetic())
回答1:
I just found that the transforms are not properly set until the figure is in its final state. So the key is to first draw the figure,
fig.canvas.draw()
or at least apply the aspect properly.
ax.apply_aspect()
Then you will get the correct pixel coordinates out,
import matplotlib.pyplot as plt
import cartopy
import cartopy.crs as ccrs
fig = plt.figure()
ax = fig.add_axes([0, 0, 1, 1], projection=ccrs.PlateCarree())
ax.add_feature(cartopy.feature.LAND, facecolor='black')
ax.set_global()
# before being able to call any of the transforms, the figure needs to be drawn
fig.canvas.draw()
# or
# ax.apply_aspect()
# Print the location of New York City in display coordinates
lon, lat = -74.0060, 40.7128
trans = ccrs.PlateCarree()._as_mpl_transform(ax)
x, y = trans.transform_point((lon, lat))
print(x,y)
plt.show()
This prints:
188.43377777777778 312.3783111111111
Note that those coordinates refer to the pixels from the lower left corner.
回答2:
In my sample code I failed to specify the extent of the map. If I add
ax.set_global()
then the transformed coordinates are sensible.
I presented two ways to compute the transformed coordinates, but the way with _as_mpl_transform()
seems to return the center point when New York City is not visible. The way with ax.projection.transform_point()
returns NaN when off-screen.
来源:https://stackoverflow.com/questions/55998371/get-projected-coordinates-from-geometric-coordinates