使用底图的readshapefile 进行绘制时,如果所定义的地图的中心位于shapefile的纵向中心以外的其他位置,则仅会绘制其中的一部分。这是一个使用Natural Earth's海岸线的示例:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
shpf = './NaturalEarth/ne_50m_land/ne_50m_land'
fig, ax = plt.subplots(nrows=1, ncols=1, dpi=100)
m = Basemap(
ax = ax,
projection = 'cyl',
llcrnrlon = 0, llcrnrlat = -90,
urcrnrlon = 360, urcrnrlat = 90
)
m.readshapefile(shpf,'ne_50m_land')
m.drawmeridians(np.arange(0,360,45),labels=[True,False,False,True])
哪个会产生:
使用底图或Python是否有解决方法?我知道有人在QGIS或类似工具中将shapefile重新居中,但是每次创建新地图时都这样做并不可行,而且我的QGIS技能非常基础。
答案 0 :(得分:1)
一种方法是告诉readshapefile
不要直接绘制海岸线,然后在自己绘制之前先操纵线段。这里是一个基于您的用例的示例:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
shpf = 'shapefiles/ne_50m_land'
fig, ax = plt.subplots(nrows=1, ncols=1, dpi=100)
m = Basemap(
ax = ax,
projection = 'cyl',
llcrnrlon = 0, llcrnrlat = -90,
urcrnrlon = 360, urcrnrlat = 90
)
m.readshapefile(shpf,'ne_50m_land', drawbounds = False)
boundary = 0.0
for info, shape in zip(m.ne_50m_land_info, m.ne_50m_land):
lons, lats = map(np.array, zip(*shape))
sep = (lons <= boundary).astype(int)
roots = np.where(sep[:-1]+sep[1:] == 1)[0]+1
lower = np.concatenate([[0],roots]).astype(int)
upper = np.concatenate([roots,[len(lons)]]).astype(int)
for low, high in zip(lower,upper):
lo_patch = lons[low:high]
la_patch = lats[low:high]
lo_patch[lo_patch<0] += 360
x,y = m(lo_patch,la_patch)
ax.plot(x,y,'k',lw=0.5)
m.drawmeridians(np.arange(0,360,45),labels=[True,False,False,True])
plt.show()
在上面的示例中,按照Basemap documentation中说明的方式遍历形状文件的线段。首先,我认为将360度添加到经度小于0的每个点就足够了,但是每当一条海岸线经过0度线时,您就会得到一条水平线。因此,每当出现这种交叉时,都必须将线切割成较小的段。使用numpy
可以很容易地做到这一点。然后,我使用plot
命令绘制海岸线。如果您想做更复杂的事情,请查看Basemap documentation。
最终结果如下:
希望这会有所帮助。