基于PostGIS+PgRouting的最短路径查询的实现(一):数据库篇


关于最短路径查询计划分为三篇文章来记录。
本篇:主要来记录在这个方案中,要如何去准备数据及相关的数据库操作
Geoserver篇:主要记录在Geoserver中如何去创建最短路径分析图层服务。
Openlayers篇:主要记录在前端使用Openlayers如何去调用最短路径服务。

一、软件基础

  • 安装PostgreSQL数据库
  • 安装Geoserver地图服务器
  • 安装PostGIS数据库插件

相信做地图开发的对这几个软件的安装都不陌生,没安装过也不要害怕,因为安装极其简单。

二、准备工作

  1. 首先,准备要用作路径分析的数据源,几何类型一定要是线类型。如道路中心线,文件格式:.shp

  2. 如果你的分析结果要考虑方向,请添加通行方向字段(建议添加)。
    通行情况可以分为四种情况:
    1:双向通行,值:空;
    2:正向通行(即实际通行方向与矢量数据的方向一致),值:FT;
    3:反向通行(即实际通行方向与矢量数据的方向相反),值:TF;
    4:禁止通行,值:N。
    当然取值你也可以使用其它内容来标识。
    可以在ArcGIS或QGIS中查看线的矢量方向,然后根据实际情况去设置值。如果嫌麻烦,只是为测试,可以均设置为正向。

  3. 线线相交处打断线(不要忘)
    这一步操作,可以借助ArcGIS工具箱中的要素转线来完成。

  4. 在PostgreSQL中创建数据库

  5. 添加postgis、pgrouting及相关的拓展

  6. 将线文件导入数据库
    使用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

You may also like...

退出移动版