shapefile的使用和地理信息的獲得


Shapefile文件是美國ESRI公司發布的文件格式,因其ArcGIS軟件的推廣而得到了普遍的使用,是現在GIS領域使用最為廣泛的矢量數據格式。官方稱Shapefile是一種用於存儲地理要素的幾何位置和屬性信息的非拓撲簡單格式。

一般地,Shapefile文件是多個文件的集合,至少包括一個shp,shx以及dbf文件。

shp主文件使用變長記錄存儲空間幾何數據,支持點,線,面等多種幾何類型。
shx索引文件用於存儲幾何數據的索引信息,包含對主文件中每個記錄長度的描述(注意不是空間索引)
dbf表文件是使用dBase數據庫表文件進行空間屬性數據存儲的文件
所以,我們如果要自己完全從底層寫代碼解析Shapefile文件的話,需要根據shx文件中的信息讀取shp中的二進制數據並轉化為幾何對象,然后再讀取dbf表格,將屬性添加到幾何對象上就完成了對一個Shapefile文件的解析.

其實現在,如果給定一個地點的經度和維度,現在讓你想判斷一下,這個地點是算什么區域,正常做法是,我們調用百度地圖或者谷歌地圖的API里面的接口就可以了。但是其實,如果當這些接口不能調用的時候,我們該怎么辦呢。

這里我們可以考慮下用shapefile來完成這個任務。

1. 首先在shapefile里面,文件數據提供了信息,這個信息可以幫助我們繪制一個地區區域的多邊形。

2. 接着我們需要把我們的目標點繪制成一個點

3. 剩下的任務就是,我們來判斷,目標區域的點是不是在地形繪制的多邊形里面。

判斷任務3的時候,我們可以用一個景點的 point in ploygon 理論,大概是這個樣子

判斷的算法我就直接引用了:

1) Draw a horizontal line to the right of each point and extend it to infinity

1) Count the number of times the line intersects with polygon edges.

2) A point is inside the polygon if either count of intersections is odd or
   point lies on an edge of polygon.  If none of the conditions is true, then 
   point lies outside.

那這樣,我們有我們目標點的坐標,我們又有我們區域的大概的形狀,那這樣我們就可以確定,我們的目標點的所在區域了

 

下面是代碼,用python實現的

# Library
# 這個是用來判斷點在不在多邊形里面的庫,同時繪制點和多邊形
from shapely.geometry import Point
from shapely.geometry.polygon import Polygon
# 這里是用這個來讀取shapefile文件
import shapefile

接着我們讀入數據

1 # Load the shapefile information
2 sf = shapefile.Reader("./vic_suburb_boundary/VIC_LOCALITY_POLYGON_shp") # note, no suffix, all 3 files are used
3 recs = sf.records()
4 shapes = sf.shapes()

這時候我們先看下,shapefile里面有哪些信息

recs[0]

這里我們發現,基本上可能是與這個區域有關的一些文字信息,我們看到第7個元素是我們這次需要的,是這個區域的名字,接着我們看下shapes里面的內容

 shapes[0].points 

這里我們發現是一系列坐標點,這些坐標點可以幫助我們來繪制這個區域的的多邊形

# Build a list to hold the name of the suburb
subsurb_name = []
for item in recs:
    # Extract the 7th element:subsurb name
    subsurb_name.append(item[6])
# Check the extraction result
print(subsurb_name[:5])

# Build a list to hold the ploygon represent the subsurb
sub_plon = []
for item in shapes:
    # Using the points information to draw the ploygon
    polygon = Polygon(item.points)
    sub_plon.append(polygon)
# Drow one of the subsurb
sub_plon[0]

在上面兩步,我們把shape中的區域名字信息以及區域性質信息都提取了出來,接着,我們就可以用這個信息,來判斷,我們的目標點,相應都在哪里了

# Combine name and ploygon list together
sub_info = list(zip(subsurb_name,sub_plon))

# lat information for all the lats
lat_list = list(df_house.lat)
# lng information 
lng_list = list(df_house.lng)
# Zip them in the list of tuples
position_list = zip(lng_list, lat_list)

# A list for holding the subsurb information for each house property
sub_for_house = []
# Loop through all the house 
for item in position_list:
    # Build a point to represent the house property
    point = Point(item[0],item[1])
    # Check where the point is located
    for sub in sub_info:
        # Return true if the point is in the ploygon
        if sub[1].contains(point):
            # Collect the result
            sub_for_house.append(sub[0])

# Check the result
sub_for_house[:5]

根據我們之前的算法,我們把每個我們的目標地址都便利了一遍,並且計算出相應的位置點。

這里我們可以驗證一下,比如第一個地址,是

“120 Power Road”,根據谷歌地圖的搜索,他的區域確實是DOVETON,那和我們計算的結果一致。https://www.google.com/search?q=120+Power+Road&oq=120+Power+Road&aqs=chrome..69i57.540j0j4&sourceid=chrome&ie=UTF-8

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM