基于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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
©️2022 CSDN 皮肤主题:大白 设计师:CSDN官方博客 返回首页
评论 23

打赏作者

此爱如少年

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值