13. 矢量数据处理

[sec:vectdat]

GRASS 和GRASS 的矢量数据的不同文件结构已在[sec:grassdata]中的图[abb:datenbank]里表明。正由于结构的不同,所以新、旧矢量数据可以在相同的区域/地图集中一起创建和管理。 此外,数据从GRASS 转换到GRASS 时文件名称保持不变。模块将GRASS 的老的矢量数据转换为新的矢量格式:

v.convert in=grass5old_vector out=grass60_vector
g.region -p vect=grass60_vector
v.info grass60_vector
v.db.connect -p grass60_vector
d.vect grass60_vector

如果需要,也可以通过ASCII或Shapefile格式(推荐后者)将GRASS 的矢量数据转换为旧的矢量格式。注意,GRASS 的旧的矢量格式只能够存储一个属性和一个标签。在使用的时候,GRASS 能够用参数显示属性字段:

# EXPORTING VECTOR MAP FROM GRASS AS SHAPE
v.out.ogr in=grassnew_vector dsn=. layer=vector_areas type=area

# IMPORTING SHAPE INTO GRASS 5.0/5.4
v.in.shape -d in=vector_areas.shp

Attribute layers available in vector_areas.shp:
1: ShapeID [int4:4]
2: TypID [int4:2]
3: Name [text:50]
4: TypName [text:50]

v.in.shape in=vector_areas.shp out=vector attr=TypID label=TypName
...

13.1. 网络分析

[shpath]

通常,网络分析基于矢量的拓朴关系。由于GRASS是拓朴型GIS(这由DGLib(Directed Graph Library)提供),所以有多种网络分析模块:

  • 最短路径分析(和)
  • 子网络(Subnets)分析()
  • 最小Steiner树()
  • 旅行商问题()
  • 成本分析()

作为一个例子,医院蓄水池最佳位置的选择将在第[sec:optalloc]章中说明。

13.1.1. 最短路径分析

两点间的最短路径可以用两种不同的方式来确定。默认情况下,矢量的长度用作成本源。其它的属性,像道路的限速或道路的状况,也能够用来计算路径。成本信息可以赋给矢量的两个方向。节点的属性(如道路交叉口的红绿灯时间)也可以考虑。

直接计算GRASS监视器上两点间的最短距离。在此过程中,通过鼠标控制模块,并且在屏幕上直接显示结果。

该模块只适用于两点(起点和终点)的情况,如果想使用更多的点或者想保存生成的地图,那么就必须使用模块。

与相似,但需要更多的参数。另一个不同是,它会生成一个新的包含结果的矢量地图。因此,该模块允许用户将生成的路径单独保存在矢量数据集中。

该模块的一个应用是基于路网计算最短路径。FRIDA的Osnabrueck数据可以作为示例数据。下面的命令可以找到点40和点71间的最短路径。

echo "1 40 71" | v.net.path mygraph out=mypath

为了使用行驶方向,在计算中可以加入’’forward’’和’’backwards’’字段。

输出地图被创建,它包含了给定点间的最短路径。

13.1.2. 子网络分析

模块能够在给定的网络中计算出子网络。例如,它能够用来计算一个城市中几个警察局的服务范围,然后可以利用这些信息使他们满足特殊的情况。这一应用将在第[sec:optalloc]章中详细地说明。

13.1.3. 最小Steiner树

最小Steiner树(Minimum Steiner Tree)描述了网络节点的最优连接。下面的例子可以帮助我们理解:

假定一个城市分布着几个医院,他们需要新的网络来提供电视医疗服务。目标就是要沿着公路尽可能好地铺设必需的管线,使得所需管线最少并且所有的医院连成新的网络。模块可以完成该任务。

13.1.4. 旅行商问题

旅行商问题(Travelling-Salesman-Problem)是要确定不同点间的最优路径。例如,一个城市中分布着几个医院,一个医药公司的代表团要访问这些医院。 模块能够为旅行者计算出最优路径 – 可能是是距离最短,也可能是时间最少。

v.net.salesman in=hospital_net out=pharmarepresentative ccats=40-215

13.1.5. 成本分析

模块可以在矢量网络上进行成本分析。这意味着等距离的计算,也可以看作一个点周围的同心距离的计算。因此,可以基于矢量长度或其它属性计算”运行长度”(如排水管线系统)。

13.2. 数据的相交、叠置和合并

[overlay:sub:main]

在GRASS中可以通过进行矢量数据的相交、叠置或合并。

image [abb:vmapd]

我们将用一个简单的例子来说明这些步骤,使用德国的VMAP0数据。该数据集包含了德国的政区界线、内陆航道、道路、铁路以及高程数据,已将它们重新投影并且准备好了。数据可以从下面列出的站点下载: http://www.gdf-hannover.de/download

首先,需要导入必需的shapefile数据。GRASS会用shapefile自带的投影信息为它自动创建一个新的区域。

# create location from within a GRASS session:
v.in.ogr pol_borders.shp out=pol_borders location=germany
exit


# Re-start with the newly created location:
grass60 /home/user/grassdata/germany/PERMANENT
v.in.ogr -e dsn=./inlandwaterways .shp out=inlandwaterways
v.in.ogr -e dsn=./roads.shp out=roads
v.in.ogr -e dsn=./railways.shp out=railways
v.in.ogr -e dsn=./heightpoints.shp out=heightpoints

13.2.1. 数据的合并

[union]

只有将多边形地图当作输入地图(参数)时才能够进行数据的合并。作为例子,我们将政区界线与内陆航道合并在一起:

v.overlay ainput=pol_borders binput=inlandwaterways \
output=lakeinborders operator=or

在控制结果地图的属性表时,两个输入地图的类别值都得以保留。GRASS会创建一个联合表,每个字段都会有一个相应的前缀(或)来表明源数据集。

13.2.2. 数据的相交

[intersect]

当两幅矢量地图相交时,最终的地图只保留两幅输入地图中共有的区域,其它的区域全部丢弃:

v.overlay ainput=pol_borders binput=inlandwaterways \
output=borderswherelakes operator=and

本例中,最后的地图只显示内陆航道所在的区域。

13.2.3. 数据的裁切

[cutout]

数据的裁切与数据的合并相反,最终的地图显示了中没有被覆盖的要素:

v.overlay ainput=pol_borders binput=inlandwaterways \
output=borderswherenolakes operator=not

13.2.4. 数据的叠置

[overlay]

在叠置的过程中,只要不被覆盖,那么或的要素都会保留。下面的例子表明,只要不被覆盖,那么和的要素都会出现在结果图上。

v.overlay ainput=inlandwaterways binput=pol_borders \
output=bordersoverlakes operator=xor

13.3. 数据的提取

[extract]

模块能够从地图中提取几何形状和属性,并把它们存储为新的地图。在接下来的例子中,下萨克森联邦州的政区界限将从中提取出来。

v.extract in=pol_borders out=pol_borders_nds type=area new=-1 \
where="nam='NIEDERSACHSEN'"

13.4. 数据的选择

[select]

地图包含了整个德国最为重要的道路,假定下萨克森联邦州的道路是工程中感兴趣的部分。为了将它们提取出来,需要基于下萨克森联邦州的政区界线(地图)将这些道路从地图中选择出来。为此我们要使用模块:

13.5. 拓朴的管理

[vclean]

要创建、分析、修复矢量的拓朴信息,可以使用和。

v.build

模块是GRASS 中的后继版本。它可以重组拓朴信息,通常会自动地完成。此外,它还有DUMP功能,能够将拓朴或’空间索引’信息传到标准输出上。

v.clean

模块允许用户改变或修复矢量的拓朴。现在有12中拓朴操作,下面简要地介绍一下。

break: 在线的交点处将线打断,并以节点替代交点。

rmdupl: 删除重复的线。请小心处理属性。

rmdangle: 删除悬挂边。请考虑容限值。

chdangle: 改变悬挂边的数据类型,由边界(boundary)改为线(line)。请考虑容限值。

rmbridge: 删除面与岛或岛之间的,拓朴上非法的连接。

chbridge: 改变面与岛或岛之间的连接的数据类型,由边界改为线。

snap: 依据容限值,将线连接起来。

rmdac: 删除多边形中重复的质心。

bpol: ’拓朴清理’,用于不带拓朴信息的数据(如Shapefile)。创建一个新的拓朴,有清晰的顶点到线的关系。

prune: 依据线和边界的容限值删除顶点,不改变或破坏原有的拓朴关系。

rmarea: 依据容限值删除小区域,并将它们归入邻近的最大的面中。

rmsa: 消除线和节点间的小角度。

13.6. GRASS中的数字化

[vdigit]

在重新设计矢量要素的过程中,数字化模块也被重写了。该模块实现为单独的图形菜单,大多数重要的功能都以按钮集成其中。

[H]

image1 [abb:vdigit]

在介绍简短的例子,说明新的数字化模块的用法之前,我们先简要介绍一下所有重要的功能和它们的属性,对照着图[abb:vdigit](从左往右)。

数字化新的点:用来数字化一个新的矢量点。该功能的选项是的分配和点的类别值。本例中有下列的可能性:、和。如果数据库中有合适的属性表,那么在要素数字化完以后它会自动打开(见图[abb:digatt])。这些选项也同样适用于下面的、和。

数字化新的线:用来数字化一个新的矢量线。

数字化新的边界:用来数字化一个新的封闭的边界(矢量线)。如果数据库中有合适的属性表,那么在要素数字化完以后它会自动打开。一个面数字化以后,分配到该面的属性不与边界相关,而与质心相关。因此,会在新的面中插入质心(请参阅)。 所以,在并且想完成面时,需要将类别的模式设置为。

数字化新的质心:用来在新的面中数字化一个新的质心。如果数据库中有合适的属性表,那么在要素数字化完以后它会自动打开。属性通过质心与面相关。

移动顶点:允许用户移动顶点。属性无法关联到顶点上,同时注意顶点(vertex)不是节点(node)。矢量点和质心不是顶点,不能用该功能修改。这同样适用于和。

添加顶点:允许用户添加顶点。

删除顶点:允许用户删除顶点。

分割线:可以在线的任何位置将其打断。这里会插入一个新的节点用来连接两条线,同时会关联额外的属性。

移动点、线、边界或质心:允许用户移动矢量点、矢量线和质心。如果一个面被许多节点断开,那么整个面无法移动,只能移动相应的边界。

删除点、线、边界或质心:允许用户删除矢量点、矢量线和质心。如果一个面被许多节点断开,那么整个面无法删除,只能删除相应的边界。

随意放大:用过鼠标在地图上拉框来放大地图。相应地,鼠标键分配的改变会同时在菜单中显示出来。鼠标键的分配与模块的一致。

缩小:以预定义的增量自动缩小地图。

漫游:允许用户在地图上漫游。移动的增量是内部定义的,无法改变。目前,漫游模块和数字化模块之间的关联依然没有,’橡皮条’功能也没有。

缩放到默认范围:将项目的范围设置为默认的范围(),并重新显示地图。

缩放到某一范围:将项目的范围设置为以前保存过的范围。用命令和参数可以保存一个范围。

重绘:删除监视器中的内容并重绘。这个功能是必需的,例如,在改变背景地图的时候。

显示类别:通过鼠标选择,来显示和改变类别值以及单个要素(点、线、边界和质心)的分配。

显示属性:通过鼠标选择,来显示和改变单个要素(点、线、边界和质心)的属性值。分配、类别值和关键字段也会作为额外信息来显示。在保存属性的时候可以选择相应的’编码’,当前可用的有和。

设置:允许用户为数字化过程定义不同的基本设置,包括改变监视器上显示的符号颜色(),设置’捕捉容限’(),用户能够创建属性表(),确定数字化地图(),它能处理多幅矢量或栅格格式的地图。

退出:数字化完成后,点退出模块。所有的编辑都会保存在地图中,并且会自动重构拓朴信息。

[digiexamp]

作为例子,我们不打算数字化过多的Spearfish地区的地形信息,基于TK 1:24000的地图(见图[abb:tkspear])。地形图(作为GRASS的示例数据集)已经由South Dakota Geological Survey (SDGS)明确地、以教学为目的随GRASS一起发布了。它们可以在下面的站点下载到http://grass.itc.it/download/data.php。

# Download Spearfish demonstration location and TK24
wget http://grass.itc.it/sampledata/spearfish_grass57data.tar.gz
wget http://grass.itc.it/sampledata/spearfish_toposheet.tar.gz

# Unpack Spearfish location in grassdata and start GRASS
tar xvzf spearfish_grass57data.tar.gz /home/user/grassdata/
grass60 /home/user/grassdata/spearfish57/PERMANENT

# Importing TK24 (GeoTiff) into the location
tar xvzf spearfish_toposheet.tar.gz
r.in.gdal -e in=spearfish_topo24.tif out=tk24

# Visual control
g.region rast=tk24 -ap
d.mon x0 d.rast tk24

出于训练的目的,我们假定Spearfish东部的’Lookout Peak’周围的休闲区为数字化区域。为了采集到点、线和面数据,我们将POI(point of interest) ’Lookout Peak’、高程信息和森林数字化为三个专题图(见图[abb:tkspear])。

[H]

image2 [abb:tkspear]

将新创建的矢量数据存入单独的、用户指定的地图集中。您需要退出GRASS(为了退出PERMANENT),并以一个新的地图集重新启动:

# Exit GRASS
exit

# Start GRASS again and create a new mapset
grass60 (indicate the new name of the mapset in GUI or in the console)
[STRG][ESC]

为了数字化POI ’Lookout Peak’,我们需要启动模块,并用参数创建一个新的地图。将导入的地形图以底图加载:

# Start digitizing module and create new blank map
d.mon x0
g.region rast=tk24
v.digit -n map=lookout bgcmd="d.rast tk24"

(见图 [abb:vdigit])的GUI自动启动,并且TK24作为底图加载到GRASS监视器中。现在创建一个新的属性表,包含一个额外的字段,使用按钮(见图[abb:cretab])。

[H]

image3 [abb:cretab]

然后,放大到Spearfish的东部,在’Lookout Peak’的位置数字化一个点(见图 [abb:tkspear])。要完成这一过程,先点击按钮,在地图上找到合适的位置,然后以鼠标左键点击这个位置。

这时一个图形窗口会自动打开,在这里您可以为点输入属性值。本练习中类别值为视点的名称。在窗口中点击鼠标,在字段中输入’Lookout Peak’,然后点击按钮将新记录添加到属性表中。消息可以确认添加已成功。

现在,点击按钮关闭模块。这样,新创建的地图会自动保存,拓朴也会建立:

Building topology ...
1 primitives registered
0 areas built      0%
0 isles built
Topology was built.
Number of nodes     :   1
Number of primitives:   1
Number of points    :   1
Number of lines     :   0
Number of boundaries:   0
Number of centroids :   0
Number of areas     :   0
Number of isles     :   0

接下来的练习是数字化POI周围的100米高程的等高线。和前面的练习一样,需要重新启动并用参数自动创建一个新地图。重要的地形图以底图加载:

# Start the digitizing module and create new blank map
d.mon x0
g.region rast=tk24
v.digit -n map=contour_lines bgcmd="d.rast tk24"

(见图 [abb:vdigit])的GUI自动启动,并且TK24作为底图加载到GRASS监视器中。现在创建一个新的属性表,包含一个额外的字段,使用按钮(见图[abb:cretab])。

下一步再次放大到Spearfish的东部(见图 [abb:tkspear]),点击开始数字化线。接着在监视器上选择一条主要的线,以鼠标左键在监视器上数字化。鼠标按钮的分配可以在GUI中找到。这里也可以确定和类别值的分配。

[H]

image4 [abb:digatt]

线的数字化一完成,就会打开一个图形窗口,这里您可以输入属性值(见图 [abb:digatt])。本练习中类别值为线的高程值。点击窗口,在字段中输入高程(如4200),然后点击按钮将新记录添加到属性表中。消息可以确认添加已成功。

一旦数字化完成,就使用按钮退出。这样,地图会自动保存,拓朴也会建立:

Building topology ...
825 primitives registered
0 areas built
0 isles built
Topology was built.
Number of nodes     :   203
Number of primitives:   249
Number of points    :   0
Number of lines     :   249
Number of boundaries:   0
Number of centroids :   0
Number of areas     :   0
Number of isles     :   0

最后数字化林区。和前面一样,启动,并以参数创建一个新地图。重要的地形图以底图加载:

# Start the digitizing module and create new blank map
g.region rast=tk24
d.mon x0
v.digit -n map=forest bgcmd="d.rast tk24"

(见图 [abb:vdigit])的GUI自动启动,并且TK24作为底图加载到GRASS监视器中。创建一个新的属性表,包含一个额外的字段,使用按钮(见图[abb:cretab])。

然后放大到Spearfish的东部地区(见图 [abb:tkspear]),点击按钮开始林区的数字化,并在监视器上选择一个初始区域。鼠标按钮的分配可以在GUI中找到。这里也可以确定和类别值的分配。数字化林区时,将模式从改为。原因是面的属性不与边界相关,而与质心相关。

正确的设置很重要,这样线就能够适当地捕捉到一起。默认的是10个屏幕像素,但您也可以用按钮 -> 改为您需要的值(见图 [abb:thres])。

[H]

image5 [abb:thres]

数字化完一个边界,就会为这个面提供一个质心,这样属性就能够与面相关联。为了这个目的,点击按钮,将由改为,并且在新创建的面中寻找合适的点来放置质心。如果用鼠标左键设置了质心,那么一个图形窗口就会打开,这里可以为设置的点输入属性(见图 [abb:digatt])。本练习中类别值为线的土地利用类型。点击窗口,在字段中输入土地利用类型,然后点击按钮将新记录添加到属性表中。消息可以确认添加已成功。

一旦数字化完成,就使用按钮退出。这样,地图会自动保存,拓朴也会建立:

Building topology ...
478 primitives registered
46 areas built
 isles built
Topology was built.
Number of nodes     :   357
Number of primitives:   478
Number of points    :   0
Number of lines     :   0
Number of boundaries:   367
Number of centroids :   46
Number of areas     :   46
Number of isles     :   0