如何用底图绘制以太平洋为中心的shapefile? [英] How to plot a shapefile centered in the Pacific with Basemap?

查看:147
本文介绍了如何用底图绘制以太平洋为中心的shapefile?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在使用底图的readshapefile 进行绘制时,如果所定义的贴图位于shapefile的纵向中心以外的其他任何地方,则仅会绘制一部分.这是使用天然地球的海岸线的示例:

When plotting with Basemap's readshapefile, if the defined map is centered anywhere else than the longitudinal center of the shapefile, only a portion of it it's plotted. Here's an example using Natural Earth's coastlines:

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技能非常基础.

Is there a workaround for this with Basemap or Python? I know some people re-center the shapefile in QGIS or similar, but it seems unpractical to do so every time you create a new map, and my QGIS skills are extremely basic.

推荐答案

一种方法是告诉readshapefile不要直接绘制海岸线,然后在自己绘制线段之前操纵线段.这里是一个基于您的用例的示例:

One way to do it would be to tell readshapefile not to plot the coastlines directly and then to manipulate the line segments before plotting them yourself. Here an example based on your use case:

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()

在上面的示例中,我按照底图文档.首先,我认为将360度添加到经度小于0的每个点就足够了,但是每当一条海岸线经过0度线时,您就会得到一条水平线.因此,每当出现这种交叉时,都必须将线切割成较小的段.使用numpy可以很容易地做到这一点.然后,我使用plot命令绘制海岸线.如果您想做更复杂的事情,请参阅底图文档.

In the example above, I iterate through the line segments of the shape file the way it is explained in the Basemap documentation. First I thought it would be enough to just add 360 to each point with a longitude smaller 0, but then you would get horizontal lines whenever a coast line crosses the 0 degree line. So, instead, one has to cut the lines into smaller segments whenever such a crossing appears. This is quite easily accomplished with numpy. I then use the plot command to draw the coast lines. If you want to do something more complex have a look at the Basemap documentation.

最终结果如下:

希望这会有所帮助.

这篇关于如何用底图绘制以太平洋为中心的shapefile?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆