今天要來寫GIS與路網相關的(當然只要跟graph有關的都可以使用,例如管線)一些應用。
在GIS及LBS應用中少不了路徑規劃,這些路網資料的應用路主要基於graph,networkX
可以用來建立及操作graph的工具,它可以產生各種garph,也包含了很多graph演算法。
大綱:
- 路網圖資
- 建立garph
- graph操作
路網圖資
路網系統有很多應用,今天將使用台中市數位地圖館的台中市路網資料來做測試。
建立garph
networkX
有支援將shp格式的node與edge轉為garph,然而我們原始拿到的路網資料並無node,需要拆解,這邊我們簡單使用一套s2g(shape2graph)的工具(產生無向圖)
我們先切一小塊來看1
2
3import geopandas as gpd
road = gpd.read_file('data/Road/road.shp',encoding='utf-8')
road
這邊發現這份路網是linestring Z,我們先把它轉為linestring,並轉坐標系統1
2
3
4
5
6
7from shapely.geometry import shape,LineString,Point
geoms =road['geometry']
geoms = [LineString([xy[0:2] for xy in list(geom.coords)]) for geom in geoms]
road['geometry']=geoms
road.to_file('data/Road/road2.shp',encoding='utf-8')
road
確認為linestring後,
使用sg ShapeGraph 把shp丟進去1
2
3
4
5from s2g import ShapeGraph
import networkx as nx
sg = ShapeGraph(shapefile='data/Road/road2.shp', to_graph=True)
g_nw = sg.to_networkx()
s2g產生要計算一段時間,產生下列訊息
拿到的g_nw就是networkX的graph格式
graph操作
graph可以算node間的最短路徑,使用`shortest_path’1
nearest_path= nx.shortest_path(graph, source=start_id, target=end_id)
其中input的是node的id
這邊我們先用sg物件內存的節點來手動給1
sg.node_xy
我們先手動給start_id=1, end_id=30
1 | nearest_path= nx.shortest_path(g_nw, source=5, target=19) |
回傳結果:[5, 11, 14, 3, 18, 19]
繪圖:1
2
3
4
5
6
7base=road.plot()
geoms=[]
for item in nearest_path:
geoms.append(sg.node_xy[item])
train_lines = gpd.GeoDataFrame(crs= {'init' :'epsg:3826'},geometry=[LineString(geoms)])
train_lines.plot(ax=base,color='red')