我试图在Python中生成一个可以显示的图形(除其他外):
A)从墨卡托投影图像转换的底图
B)标记的网格线
我希望这个数字在横轴墨卡托(或其他球形)投影中。
我已尝试过Matplotlib Basemap和Cartopy。 Cartopy可以做(A),Basemap可以做(B),但Cartopy只能在PlateCarree图上标记网格线,而Basemap不支持使用imshow()
转换图像。
除非有人可以提出另一种选择,否则我认为最简单的方法是在重新投影的图像上覆盖底图图中的网格线和标签。但是我不能让这两个地块相互排列。到目前为止我所拥有的:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
import cartopy.crs as ccrs
#Setup figure
fig = plt.figure(figsize=(20, 20))
#Set figure limits (lat long)
xlimits = [25, 42]
ylimits = [25, 40]
#Where the projection is centred
centre = [33, 33]
#Image limits in Mercator Eastings and Northings
imxlimits = [25, 42]
imylimits = [25, 40]
#Transform image Limits
imextent = tuple(ccrs.Mercator().transform_points(ccrs.Geodetic(),
np.array(imxlimits), np.array(imylimits))[:, 0:2].T.flatten())
#Load image
image = plt.imread(Dir + 'topo.png')
tm = ccrs.TransverseMercator(central_longitude=centre[0], central_latitude=centre[1])
ll = ccrs.Geodetic()
#Setup image axies
ax = fig.add_subplot(111, projection=tm)
ax.set_extent(xlimits + ylimits, ll) #<--Limits defined here
#Plot image transformed
ax.imshow(image, origin='upper', extent=imextent, transform=ccrs.Mercator())
#Create axes for gridlines
axl = fig.add_subplot(111)
#Make the figure background transparent
axl.patch.set_alpha(0)
#Make basemap instance
m = Basemap(projection='tmerc', resolution='h', ax=axl,
lat_0=centre[1], lon_0=centre[0],
llcrnrlon=xlimits[0], llcrnrlat=ylimits[0], #<--Limits defined here
urcrnrlon=xlimits[1], urcrnrlat=ylimits[1])
m.drawcoastlines() #to check if the images match up
#Draw gridlines
m.drawparallels(np.arange(20, 50), labels=[False, True, False, False])
m.drawmeridians(np.arange(20, 50), labels=[False, False, False, True])
plt.show()
这会产生大致相互重叠的图,但是会出现错位。我认为这是因为可以为顶部和底部边缘设置第一个绘图的限制,并且为第二个绘图给出的(相同)限制是针对右上角和左下角。
有关如何解决此问题的任何提示?
谢谢!
答案 0 :(得分:0)
所以我设法通过替换Cartopy限制的定义来实现它,而不是:
ax.set_extent(xlimits + ylimits, ll)
我首先转换为Transverse Mercator坐标:
tmlims = tm.transform_points(ll, np.array(xlimits), np.array(ylimits))
然后将范围设置为:
ax.set_extent([tmlims[0][0], tmlims[1][0], tmlims[0][1], tmlims[1][1]], tm)
由于情节已经在横轴墨卡托坐标中,我不知道为什么手动转换会产生差异(因为定义ll
而不是tm
应该进行相同的转换)。也许我误解了它如何转换限制。
在找到这个解决方案的过程中,我还发现了一些代码,这些代码可能会帮助其他地图的用户不排队等候。问题:
ax.get_extent(crs) #Return the extents of the Cartopy axies in the given co-ordinates
#
#These work with any matplotlib axies
ax.set_anchor('W') #Anchor the plot to the left (in this case) of the canvas
ax.set_aspect('equal') #Distort (or not) the aspects of the plot
请参阅http://matplotlib.org/api/axes_api.html和http://scitools.org.uk/cartopy/docs/v0.4/matplotlib/geoaxes.html