代码之家  ›  专栏  ›  技术社区  ›  lanadaquenada

如何用basemap绘制以太平洋为中心的形状文件?

  •  0
  • lanadaquenada  · 技术社区  · 6 年前

    当使用 basemap的readshapefile进行绘图时,如果定义的地图在shapefile的纵向中心以外的任何位置居中,则只绘制其中的一部分。下面是一个使用 natural earth's的示例 海岸线:

    导入numpy as np 将matplotlib.pyplot导入为plt 从mpl_toolkits.basemap导入basemap shpf='./naturalearth/ne_50m_land/ne_50m_land' 图,ax=plt.子批次(nrows=1,ncols=1,dpi=100) M=基线图( ax=ax, 投影='cyl', llcrnrlon=0,llcrnrlat=-90, urcrnlon=360,urcrnlat=90 ) m.readshapefile(shpf,'ne_50m_land') m.drawMeridians(np.arange(0360,45),labels=[真、假、假、真])

    生产:

    对于basemap或python,是否有解决方法?我知道有些人在qgis或类似工具中重新定位形状文件的中心,但每次创建新地图时,这样做似乎并不实际,而且我的qgis技能非常基本。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

    对于basemap或python,是否有解决方法?我知道有些人把形状文件放在qgis或类似工具的中心,但是每次你创建一个新的地图时,这样做似乎是不现实的,我的qgis技能非常基础。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Thomas Kühn    6 年前

    一种方法是告诉 readshapefile not to plot the coastline directly and then to operate the line segments before plotting them yourself.这里有一个基于您的用例的示例:

    导入numpy as np 将matplotlib.pyplot导入为plt 从mpl_toolkits.basemap导入basemap shpf='shapefiles/ne_50m_land' 图,ax=plt.子批次(nrows=1,ncols=1,dpi=100) M=基线图( ax=ax, 投影='cyl', llcrnrlon=0,llcrnrlat=-90, urcrnlon=360,urcrnlat=90 ) m.readshapefile(shpf,'ne_50m_land',drawbounds=false) 边界=0.0 如需了解信息,请使用拉链(M.NE_50M_Land_Information,M.NE_50M_Land): lons,lats=地图(np.array,zip(*shape)) sep=(lons<=边界).astype(int) 根=np.其中(sep[:-1]+sep[1:]==1)[0]+1 lower=np.concatenate([[0],roots]).astype(int) upper=np.concatenate([根,[len(lons)]]).astype(int) 对于低、高拉链(下、上): lo_patch=lons[低:高] la_patch=lats[低:高] Lo_补丁[Lo_补丁<0]+=360 x,y=m(lo_补丁,la_补丁) ax.图(x,y,'k',lw=0.5) m.drawMeridians(np.arange(0360,45),labels=[真、假、假、真]) 请显示())

    在上面的示例中,我迭代形状文件的各行段,其解释方式见basemap documentation。首先,我认为只要在经度小于0的每个点上加上360就足够了,但是当海岸线穿过0度线时,你就会得到水平线。因此,只要出现这样的交叉点,就必须将这些线切割成更小的段。这很容易通过numpy>code>完成。然后,我使用绘图命令绘制海岸线。如果您想做更复杂的事情,请查看basemap文档

    最终结果如下:

    希望这有帮助。

    自己动手。下面是一个基于您的用例的示例:

    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.首先,我认为只要在经度小于0的每个点上加上360就足够了,但是当海岸线穿过0度线时,你就会得到水平线。因此,只要出现这样的交叉点,就必须将这些线切割成更小的段。这很容易用numpy.然后我用plot命令绘制海岸线。如果你想做更复杂的事情,看看基线图文件.

    最终结果如下:

    result of the above code

    希望这有帮助。