14. 应用举例: 基于矢量的区域最优化问题

[sec:optalloc]

本章将介绍一个简短的、具有代表性的练习,涉及网络分析模块。

从预定的点(医院)出发,确定这样的区域:在紧急情况下各急救队能够以最快的速度到达。因此,首先要为各矢量和节点(道路和交叉口)分配不同的、涉及方向的影响因子(速度、道路状况、单行道…)。该应用受制于一个通行距离的分析。

14.1. 导入示例数据

[netimport]

和前面的一些例子一样,我们使用FRIDA项目的数据:http://frida.intevation.org/,包含了Osnabrueck(德国)市的矢量数据。除了现有的路网,还有水系和公园,以及一些重要地点(医院、学校等)的信息。数据格式为ESRI的Shapefile。

在将数据导入新的FRIDA区域时,GRASS会自动创建一个必需的高斯-克吕格区域(请参阅[sec:vectimport])。

数据的导入由模块来完成:

# STARTING ONE grass SESSION (e.g. Spearfish dataset):
grass60 ~/grassdata/spearfish60/user1/

# IMPORTING ROADNET INCLUDING CREATION OF THE NEW LOCATION:
v.in.ogr dsn=frida-1.0.1-shp-joined/strassen-joined.shp \
output=roads loc=frida
exit

# RESTART WITH NEW LOCATION:
grass60 ~/grassdata/frida/PERMANENT

# IMPORTING SITES (hospitals, ...):
v.in.ogr dsn=frida-1.0.1-shp-joined/poi-joined.shp output=points

[H]

image [abb:basemap]

在用导入的时候,拓朴问题通常会被更正。如果出现失败信息,如it can be found in the polygone datasets (FRIDA V),那么请尝试用来更正(请参阅[vclean])。

在开始将路网中的节点分配到各个医院之前,需要创建一个内部的字段。这样就可以通过分配将不同的属性表连接到同一幅矢量地图上。

# Entry of a 2nd layer:
v.category points out=points_2f layer=2 op=add

# Control:
v.category points_2f layer=1,2 op=print # -> layer 1 == layer 2

14.2. 从点文件中提取医院

[extr]

接下来,从底图points_2f中将Osnabrueck的医院提取出来:

# Extracting hospitals:
v.extract in=points_2f out=hospitals_pre type=point\
where="poiTypName='Klinik/Hospital'"

v.select ainput=points_2f binput=hospitals_pre out=hospitals

# Control:
v.info hospitals # -> one dblink

v.category hospitals layer=1,2 op=print # -> 2 layers

d.erase
d.vect roads
d.vect hospitals disp=attr attr=poiNameID bgcolor=white bcolor=black
d.vect hospitals col=red icon=basic/diamond

14.3. 将医院分配到路网中

[stuetz]

在图 [abb:basemap]中显示了计算最优区域的初始情况。在将医院分配到道路之前,需要将它们集成到路网里。同时也添加了一个类别值,在后面的计算中会通过用到它。

这一赋值过程由两个操作完成。首先,点数据由线数据扩展为新的地图,并通过连接属性表。

# Intersection of the data:
v.patch in=roads,hospitals out=roads_hospitals

# Control:
v.info roads_hospitals # -> dblinks = 0

d.erase
d.vect roads_hospitals
d.vect roads_hospitals type=point col=red

# Define database (if necessary)
db.connect dr=dbf database='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/'

# Display attribute columns of the maps
db.describe -c roads
ncols:7
Column 1: cat
Column 2: strShapeID
Column 3: strID
Column 4: strTypID
Column 5: strSpuren
Column 6: strEbene
Column 7: strName
# -> The 'cat' column has been added during the import via 'v.in.ogr'.

# Connect the attributes of the lines with the extended map
v.db.connect roads_hospitals dr=dbf \
data='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/' \
table=roads layer=1 key=cat

# Connect the attributes of the points with the extended map
v.db.connect roads_hospitals dr=dbf \
data='$GISDBASE/$LOCATION_NAME/$MAPSET/dbf/' \
table=hospitals layer=2 key=cat

# Control
v.db.connect -p roads_hospital

注意:

如果在此处删除了地图,那么所有与之相连的属性表都会被删除,包括属性表和(请参阅[subsec:vectatt])。备份连接的属性表可以避免这个风险。

接下来,医院和路网自动连接,并且保存在新地图中:

# Create connecting lines between hospitals and roads:
v.distance -p from=hospitals to=roads output=roads_hospitals_connect\
upload=dist column=dist

# Patch connecting lines with roads and hospitals:
v.patch in=roads_hospitals,roads_hospitals_connect out=hospitals_net_pre

# correct topology
v.clean in=hospitals_net_pre out=hospitals_net tool=break,snap

# clean up
g.remove vect=hospitals_net_pre,hospitals_pre

地图现在包含了路网,医院以及连接二者的线。此外,类别值通过内部的分配给了医院。这些类别值是计算可达性的起点。

14.4. 最优可达区域的分配

[optarea]

在基础数据准备好后,就可以完成区域的计算了。由于是沿着路网的距离,所以要尽可能快地到达医院。

正如前面提到的那样,分配的最简单的方法是考虑额外的影响因素,如速度或行使方向。在本例中额外的参数是可以想得到的,它们可以用来分配给额外的属性字段。

v.net.alloc input=hospitals_net output=hospitals_alloc ccats=40-215

最后的子网络是通过计算路网得到的,它依靠确定的通行成本分配到医院。因此每一条道路都分配到相应的医院,并且沿着路网的通行成本是最低的。如果需要,可以在矢量中设置新的”节点”,来定义确切的边界。

[H]

image1 [fig:optarea]

本例的结果能够在图 [fig:optarea]中看到。用或显示结果。

d.vect map=hospitals_alloc color=red cats=40
d.vect map=hospitals_alloc color=green cats=41
d.vect map=hospitals_alloc color=blue cats=69
...
d.vect map=hospitals_alloc color=black cats=215

总而言之,GRASS提供了七种不同的网络模块,在 [shpath]中我们作了简单的介绍。它们的用法十分相似,所以这个示例对其它模块来说很有代表性。