pgrouting是postgresql的路径规划拓展插件。支持用户使用数据库中的路网数据构建拓扑,并基于拓扑路网数据进行最短路径查询或耗费成本计算,并支持矩阵运算。
pgrouting的官方文档见:
docs.pgrouting.org/3.0/en/inde…
使用pgrouting构建完路径规划服务后,可以结合geoserver进行展示。
Pgrouting官网写得很详细,这里仅仅是整理一下,以作备份。
一、插件安装: pgrouting安装详细说明见:
要注意的是,pgrouting依赖postgis,要确保postgis已经安装了。
如果使用云主机,并已经安装过postgresql与postgis,使用如下语句进行pgrouting安装即可。
sudo apt install postgresql-9.3-pgrouting
如果使用window系统,下载安装文件:
download.osgeo.org/postgis/win…
二、创建扩展: pgrouting要依赖postgis。
新建数据库后,运行:
CREATE EXTENSION PostGIS
CREATE EXTENSION pgRouting
三、样例数据: pgrouting官网提供了一个很简单的样例数据,讲拓扑路网数据如何构建:
docs.pgrouting.org/3.0/en/samp…
乍一看,好像很多表,有点不明就里,但没关系,把所有sql都运行一遍就可以,pgrouting的所有查询都基于这些表。
1.edge_table 新建数据表edge_table,这张表存储所有道路线信息,查询大部分都是基于这张表:
CREATE TABLE edge_table ( id BIGSERIAL, dir character varying, source BIGINT, target BIGINT, cost FLOAT, reverse_cost FLOAT, capacity BIGINT, reverse_capacity BIGINT, category_id INTEGER, reverse_category_id INTEGER, x1 FLOAT, y1 FLOAT, x2 FLOAT, y2 FLOAT, the_geom geometry ); 插入数据,都是两点线段:
INSERT INTO edge_table ( category_id, reverse_category_id, cost, reverse_cost, capacity, reverse_capacity, x1, y1, x2, y2) VALUES (3, 1, 1, 1, 80, 130, 2, 0, 2, 1), (3, 2, -1, 1, -1, 100, 2, 1, 3, 1), (2, 1, -1, 1, -1, 130, 3, 1, 4, 1), (2, 4, 1, 1, 100, 50, 2, 1, 2, 2), (1, 4, 1, -1, 130, -1, 3, 1, 3, 2), (4, 2, 1, 1, 50, 100, 0, 2, 1, 2), (4, 1, 1, 1, 50, 130, 1, 2, 2, 2), (2, 1, 1, 1, 100, 130, 2, 2, 3, 2), (1, 3, 1, 1, 130, 80, 3, 2, 4, 2), (1, 4, 1, 1, 130, 50, 2, 2, 2, 3), (1, 2, 1, -1, 130, -1, 3, 2, 3, 3), (2, 3, 1, -1, 100, -1, 2, 3, 3, 3), (2, 4, 1, -1, 100, -1, 3, 3, 4, 3), (3, 1, 1, 1, 80, 130, 2, 3, 2, 4), (3, 4, 1, 1, 80, 50, 4, 2, 4, 3), (3, 3, 1, 1, 80, 80, 4, 1, 4, 2), (1, 2, 1, 1, 130, 100, 0.5, 3.5, 1.999999999999,3.5), (4, 1, 1, 1, 50, 130, 3.5, 2.3, 3.5,4);
更新数据,根据x1、y1、x2、y2构建两点间线段,并指定线段的通达性:
UPDATE edge_table SET the_geom = st_makeline(st_point(x1,y1),st_point(x2,y2)), dir = CASE WHEN (cost>0 AND reverse_cost>0) THEN 'B' -- both ways,双向通行 WHEN (cost>0 AND reverse_cost<0) THEN 'FT' -- direction of the LINESSTRING,沿路通行 WHEN (cost<0 AND reverse_cost>0) THEN 'TF' -- reverse direction of the LINESTRING,反向通行 ELSE '' END; -- unknown,未知
构建拓扑,这个比较关键,必须得构建拓扑之后,才能进行路径规划,0.001是拓扑容差:
SELECT pgr_createTopology('edge_table',0.001); 2. pointsOfInterest 生成兴趣点,pointsOfInterest存放兴趣点:
CREATE TABLE pointsOfInterest( pid BIGSERIAL, x FLOAT, y FLOAT, edge_id BIGINT, side CHAR, fraction FLOAT, the_geom geometry, newPoint geometry );
插入数据:
INSERT INTO pointsOfInterest (x, y, edge_id, side, fraction) VALUES (1.8, 0.4, 1, 'l', 0.4), (4.2, 2.4, 15, 'r', 0.4), (2.6, 3.2, 12, 'l', 0.6), (0.3, 1.8, 6, 'r', 0.3), (2.9, 1.8, 5, 'l', 0.8), (2.2, 1.7, 4, 'b', 0.7);
更新数据,创建兴趣点:
UPDATE pointsOfInterest SET the_geom = st_makePoint(x,y); newPoint是在edge上添加的临时节点。
UPDATE pointsOfInterest SET newPoint = ST_LineInterpolatePoint(e.the_geom, fraction) FROM edge_table AS e WHERE edge_id = id;
表edge_table和表pointsOfInterest,构建的点和路网如下图。
一般来说,这两张表就可以用作路径规划查询了,但是因为实际情况中,路径规划要考虑到很多其他因素,所以样例数据中还有restrictions、new_restrictions、customer等表。
四、数据查询 就看最简单的dijkstra算法:
从节点2到节点3,有向通行。
SELECT * FROM pgr_dijkstra(
'SELECT id, source, target, cost, reverse_cost FROM edge_table',
2, 3);
结果:
从节点2出发,依次通过节点5、6、9、4,最后抵达节点3,根据上图对比,的确如此。
结果字段中,node是通过节点编号,edge是边的编号,edge最后一个是-1,因为edge比node少一个。
seq | path_seq | node | edge | cost | agg_cost
-----+----------+------+------+------+----------
1 | 1 | 2 | 4 | 1 | 0
2 | 2 | 5 | 8 | 1 | 1
3 | 3 | 6 | 9 | 1 | 2
4 | 4 | 9 | 16 | 1 | 3
5 | 5 | 4 | 3 | 1 | 4
6 | 6 | 3 | -1 | 0 | 5
(6 rows)
更多解释,参见:
docs.pgrouting.org/3.0/en/pgr_…
五、几何对象获取 不难发现,pgr_dijkstra函数并不返回几何对象,如果我们想把线串拼出来,还需要使用其他函数。
例如,我们要取edge编号为4的边。
SELECT st_astext(the_geom) FROM edge_table WHERE id=4
六、捕获最近节点
更不难发现,pgr_dijkstra函数入参,需要输入节点编号,并不支持坐标入参。
但是大多数情况下,路径规划的起终点都不在节点上。
这时候需要做的是,先获取节点的编号。
根据坐标x,y从pointsOfInterest中获取一个在点(x,y)半径0.1内的点,并返回该点的edge_id属性。
SELECT edge_id FROM pointsOfInterest WHERE st_dwithin(the_geom, st_makePoint(x,y),0.1)=true limit 1 根据edge_id再去查节点编号,就可以使用pgr_dijkstra了。
如果把edge_table的节点建立一张表,用st_dwithin直接查节点表,也可以。
七、使用OSM数据
Pgrouting有一个osm2pgrouting工具,直接加载osm数据。
当然也可以从数据源获取数据,写脚本导入数据库,download.geofabrik.de/。
OSM数据,也可以通过QGIS下载。
使用OSM数据,有两个注意事项:
1.保证数据结构,数据量不要太大。
2.要先打断路网数据的相交节点,再入库。