2016-01-06 38 views
1

我試圖在Python中的shapefile中繪製一些區域的地圖。我的基本做法是這樣的:在shapefile中找到補丁子集的地圖邊界(Python)

shp = fiona.open("C:/Users/nils/Documents/Maps/my_shapefile.shp") 
bds = shp.bounds 
ll = (bds[0], bds[1]) 
ur = (bds[2], bds[3]) 
coords = list(ll + ur) 
w, h = coords[2] - coords[0], coords[3] - coords[1] 

# Make figure instance, add Basemap and CCG boundaries from shapefile 
fig, ax = plt.subplots(figsize=(12,10)) 
m = Basemap(projection="tmerc", lon_0 = -2., lat_0 = 49., ellps="WGS84", 
     llcrnrlon = coords[0], llcrnrlat = coords[1], 
     urcrnrlon = coords[2], urcrnrlat = coords[3], 
     lat_ts = 0, resolution="i", suppress_ticks=True) 
m.readshapefile("C:/Users/nils/Documents/Maps/my_shapefile.shp", "Regions") 

# Extract polygon coordinates of and names of regions to plot from shapefile 
to_plot = ["region_A", "region_B", "region_C"] 
poly = []; name = [] 
for coordinates, region in zip(m.Regions, m.Regions_info): 
    if any(substr in region["name"] for substr in to_plot): 
     poly.append(Polygon(coordinates)) 
     name.append(region["name"]) 

# Turn polygons into patches using descartes 
patches = [] 
for i in poly: 
    patches.append(PolygonPatch(i, facecolor='#006400', edgecolor='#787878', lw=0.25, alpha=0.5)) 

# Add PatchCollection to basemap 
ax.add_collection(PatchCollection(patches, match_original=True)) 

現在我的這個問題是,shape文件覆蓋更大的地域範圍,但我只是想繪製該區域的子集(想如我有一個英國shape文件,但希望繪製威爾士所有地區的地圖)。現在,我可以識別正確的區域,並只添加上述示例中的那些補丁,但matplotlib仍然會繪製shapefile中所有區域的邊界,並且由fiona的bounds方法標識的邊界顯然獨立於補丁I'已經選擇。

我有兩個問題與此:

  1. 我怎樣才能得到matplotlib只繪製在shape文件中定義補丁的一個子集的邊界?

  2. 如何獲得補丁子集的邊界,類似於fiona的bound方法對整個shapefile的作用?

回答

0

要(部分)回答我的第一個問題,實現這一目標的一個方法是調用readshapefiledrawbounds=False;在這種情況下,地圖上不會有任何邊界,但是在任何情況下,我所選區域的邊界都將用補丁繪製。

1

要回答的第二部分爲好,這裏是能夠實現期望結果的函數:

def get_bounds(patch_list): 

m = Basemap() 
# Read in shapefile, without drawing anything 
m.readshapefile("C:/Users/ngudat/Documents/Maps/CCG/CCG_boundaries_2015", "patches", drawbounds=False) 

# initialize boundaries (this is a bit of a manual step, might be better to intialize to boundaries of first patch or something) 
lon_min = 0. 
lon_max = -3. 
lat_min = 60. 
lat_max = 0. 

for (shape, patch_name) in zip(m.patches, m.patches_info): 
    if patches["name"] in patch_list: 
     lon, lat = zip(*shape) 
     if min(lon) < lon_min: 
      lon_min = min(lon) 
     if max(lon) > lon_max: 
      lon_max = max(lon) 
     if min(lat) < lat_min: 
      lat_min = min(lat) 
     if max(lat) > lat_max: 
      lat_max = max(lat) 

return lon_min, lat_min, lon_max, lat_max 

也許沒有這樣做的最有效的方式,並且初始化步驟可能需要改變,但理念應該適用於類似的情況很容易。