基于PostGIS+PgRouting的最短路径查询的实现(一):数据库篇
目录
关于最短路径查询计划分为三篇文章来记录。
本篇:主要来记录在这个方案中,要如何去准备数据及相关的数据库操作
Geoserver篇:主要记录在Geoserver中如何去创建最短路径分析图层服务。
Openlayers篇:主要记录在前端使用Openlayers如何去调用最短路径服务。
文章目录
一、软件基础
- 安装PostgreSQL数据库
- 安装Geoserver地图服务器
- 安装PostGIS数据库插件
相信做地图开发的对这几个软件的安装都不陌生,没安装过也不要害怕,因为安装极其简单。
二、准备工作
-
首先,准备要用作路径分析的数据源,几何类型一定要是线类型。如道路中心线,文件格式:.shp
-
如果你的分析结果要考虑方向,请添加通行方向字段(建议添加)。
通行情况可以分为四种情况:
1:双向通行,值:空;
2:正向通行(即实际通行方向与矢量数据的方向一致),值:FT;
3:反向通行(即实际通行方向与矢量数据的方向相反),值:TF;
4:禁止通行,值:N。
当然取值你也可以使用其它内容来标识。
可以在ArcGIS或QGIS中查看线的矢量方向,然后根据实际情况去设置值。如果嫌麻烦,只是为测试,可以均设置为正向。 -
线线相交处打断线(不要忘)
这一步操作,可以借助ArcGIS工具箱中的要素转线来完成。 -
在PostgreSQL中创建数据库
-
添加postgis、pgrouting及相关的拓展
-
将线文件导入数据库
使用PostGIS自带的pgsql2shp工具,将shp文件导入数据库。注意坐标系,选择多线转单线。
三、数据操作(重点)
假设导入后的数据表名:road
1.添加字段:source、target、length、rev_length等字段
alter table road add column source int;
alter table road add column target int;
alter table road add column length double precision;
alter table road add column rev_length double precision;
2.为了提高查询效率,给source、target字段创建索引
create index source_idx on road ("source");
create index target_idx on road ("target");
3.创建拓扑
select pgr_createTopology('road ',0.0001, 'geom', 'gid');
创建拓扑后会在数据库中生成以 vertices_pgr 结尾的表,用于记录线文件中所有交叉点和端点。
4.更新length 、rev_length字段
update road set length=ST_Length(ST_TransForm(geom,4326),true),rev_length=ST_Length(ST_TransForm(geom,4326),true) where oneway is null;
update road set length=st_length(ST_TransForm(geom,4326),true),rev_length=99999999999 where oneway='FT';
update road set length=99999999999,rev_length=st_length(ST_TransForm(geom,4326),true) where oneway='TF';
update road set length=99999999999,rev_length=99999999999 where oneway='N';
因为我们要查询的是最短路径,因此路段的长度实际上就是我们要评估权重的参数。这一段的意义,可以理解为:
- 如果道路是双向通行,则将正反向的路段长度设置为实际长度;
- 如果是正向单向通行,则正向通行设置为实际长度,反向通行距离设置为99999999999(距离过大,不可取);
- 如果是反向单向通行,则与正向单向相反;
- 如果是禁止通行,则正反向长度均99999999999。
5.上面这些操作完成了以后,就可以进行最短路径查询了
查询最短路径
如果忽略方向问题,则
select seq, id1 as node, id2 as edge, cost, geom from pgr_dijkstra('
select gid as id,
source::integer,
target::integer,
length::double precision as cost
from road ',
7,12,false,false) as di
join road pt
on di.id2 = pt.gid
如果查询结果要考虑方向,则
select seq, id1 as node, id2 as edge, cost, geom from pgr_dijkstra('
select gid as id,
source::integer,
target::integer,
length::double precision as cost,
rev_length::double precision as reverse_cost
from road ',
7,12,true,true) as di
join road pt
on di.id2 = pt.gid
其中,7,12分别是你要查询的起点和终点的gid编号。
本文参考:
https://www.jianshu.com/p/34c8378c3da9
https://blog.csdn.net/GISuuser/article/details/78625246
http://www.cnblogs.com/weiweictgu/p/8280285.html
转载自:https://blog.csdn.net/u012413551/article/details/85084961