如何用底图绘制以太平洋为中心的shapefile?

时间:2018-06-22 16:28:33

标签: python python-3.x shapefile matplotlib-basemap

使用底图的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])

哪个会产生:

Image output

使用底图或Python是否有解决方法?我知道有人在QGIS或类似工具中将shapefile重新居中,但是每次创建新地图时都这样做并不可行,而且我的QGIS技能非常基础。

1 个答案:

答案 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

最终结果如下:

result of the above code

希望这会有所帮助。