博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
GeoServer+PostgreSQL+PostGIS+pgRouting实现最短路径查询
阅读量:5158 次
发布时间:2019-06-13

本文共 7391 字,大约阅读时间需要 24 分钟。

一、软件安装

GeoServer下载地址:

PostgreSQL下载地址:

paAdmin3下载地址:

PostGIS下载地址:

pgRouting已经包含在安装程序中。

所有下载程序如下:

 

安装过程不再详述。

 

二、数据制作

我使用的是ArcMap来绘制路网数据,也可以使用其它的GIS软件,但好像没有这么方便,地理坐标系使用GCS_WGS_1984,编号为:4326。

 

注意:所有线段连接的地方都需要断开,这样便于以后的分析。

 

三、数据处理

使用paAdmin3连接PostgreSQL,并执行以下语句,在新的空间数据库里添加空间扩展:

CREATE EXTENSION postgis;

CREATE EXTENSION pgrouting;

CREATE EXTENSION postgis_topology;

CREATE EXTENSION fuzzystrmatch;

CREATE EXTENSION postgis_tiger_geocoder;

CREATE EXTENSION address_standardizer;

制作完路网数据后,需要使用 来把路网数据导入到PostgreSQL中去。

 

点击“View connection details....”在弹出的窗口中填入PostgreSQL的账号和密码,以及Database。

连接成功后,需要设置一下“Optionns...”

 

需要使用GBK编码,并勾选最下面一个选项。

添加路网数据,并设置SRID为:4326

 

导入完成后,会在数据库中创建一个对应的表:

 

在查询表中分别执行下列SQL,对表结构进行修改:

1.修改表结构

--添加起点id

ALTER TABLE public.road_xblk ADD COLUMN source integer;

--添加终点id

ALTER TABLE public.road_xblk ADD COLUMN target integer;

--添加道路权重值

ALTER TABLE public.road_xblk ADD COLUMN length double precis

 

2.创建拓扑结构                  

--为sampledata表创建拓扑布局,即为source和target字段赋值

SELECT pgr_createTopology('public.road_xblk',0.0001, 'geom', 'gid');

 

3.创建索引

--为source和target字段创建索引

CREATE INDEX source_idx ON road_xblk("source");

CREATE INDEX target_idx ON road_xblk("target");

 

4.给长度赋值

--为length赋值

update road_xblk set length =st_length(geom);

--为road_xblk表添加reverse_cost字段并用length的值赋值

ALTER TABLE road_xblk ADD COLUMN reverse_cost double precision;

UPDATE road_xblk SET reverse_cost =length;

 

5.创建最短路径函数

---创建查询随意两点之前的最短路径的函数

1 DROP FUNCTION pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float);  2   3 CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float)    4   5 returns geometry as   6   7 $body$    8   9 declare  10  11     v_startLine geometry;--离起点最近的线  12  13     v_endLine geometry;--离终点最近的线  14  15       16  17     v_startTarget integer;--距离起点最近线的终点 18  19     v_startSource integer; 20  21     v_endSource integer;--距离终点最近线的起点 22  23     v_endTarget integer; 24  25   26  27     v_statpoint geometry;--在v_startLine上距离起点最近的点  28  29     v_endpoint geometry;--在v_endLine上距离终点最近的点  30  31       32  33     v_res geometry;--最短路径分析结果 34  35     v_res_a geometry; 36  37     v_res_b geometry; 38  39     v_res_c geometry; 40  41     v_res_d geometry;  42  43   44  45     v_perStart float;--v_statpoint在v_res上的百分比  46  47     v_perEnd float;--v_endpoint在v_res上的百分比  48  49   50  51     v_shPath_se geometry;--开始到结束 52  53     v_shPath_es geometry;--结束到开始 54  55     v_shPath geometry;--最终结果 56  57     tempnode float;       58  59 begin 60  61     --查询离起点最近的线  62  63     execute 'select geom, source, target  from ' ||tbl|| 64  65                             ' where ST_DWithin(geom,ST_Geometryfromtext(''point('||         startx ||' ' || starty||')'',4326),15) 66  67                             order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326))  limit 1' 68  69                             into v_startLine, v_startSource ,v_startTarget;  70  71       72  73     --查询离终点最近的线  74  75     execute 'select geom, source, target from ' ||tbl|| 76  77                             ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),15) 78  79                             order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326))  limit 1' 80  81                             into v_endLine, v_endSource,v_endTarget;  82  83   84  85     --如果没找到最近的线,就返回null  86  87     if (v_startLine is null) or (v_endLine is null) then  88  89         return null;  90  91     end if ;  92  93   94  95     select  ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')',4326)) into v_statpoint;  96  97     select  ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint;  98  99    100 101    -- ST_Distance 102 103      104 105     --从开始的起点到结束的起点最短路径 106 107     execute 'SELECT st_linemerge(st_union(b.geom)) ' ||108 109     'FROM pgr_kdijkstraPath( 110 111     ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 112 113     ||v_startSource || ', ' ||'array['||v_endSource||'] , false, false 114 115     ) a, ' 116 117     || tbl || ' b 118 119     WHERE a.id3=b.gid   120 121     GROUP by id1   122 123     ORDER by id1' into v_res ;124 125    126 127     --从开始的终点到结束的起点最短路径128 129     execute 'SELECT st_linemerge(st_union(b.geom)) ' ||130 131     'FROM pgr_kdijkstraPath( 132 133     ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 134 135     ||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false 136 137     ) a, ' 138 139     || tbl || ' b 140 141     WHERE a.id3=b.gid   142 143     GROUP by id1   144 145     ORDER by id1' into v_res_b ;146 147  148 149     --从开始的起点到结束的终点最短路径150 151     execute 'SELECT st_linemerge(st_union(b.geom)) ' ||152 153     'FROM pgr_kdijkstraPath( 154 155     ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 156 157     ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false 158 159     ) a, ' 160 161     || tbl || ' b 162 163     WHERE a.id3=b.gid   164 165     GROUP by id1   166 167     ORDER by id1' into v_res_c ;168 169  170 171     --从开始的终点到结束的终点最短路径172 173     execute 'SELECT st_linemerge(st_union(b.geom)) ' ||174 175     'FROM pgr_kdijkstraPath( 176 177     ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''',' 178 179     ||v_startTarget || ', ' ||'array['||v_endTarget||'] , false, false 180 181     ) a, ' 182 183     || tbl || ' b 184 185     WHERE a.id3=b.gid   186 187     GROUP by id1   188 189     ORDER by id1' into v_res_d ;190 191  192 193     if(ST_Length(v_res) > ST_Length(v_res_b)) then194 195        v_res = v_res_b;196 197     end if;198 199    200 201     if(ST_Length(v_res) > ST_Length(v_res_c)) then202 203        v_res = v_res_c;204 205     end if;206 207    208 209     if(ST_Length(v_res) > ST_Length(v_res_d)) then210 211        v_res = v_res_d;212 213     end if;214 215              216 217  218 219     --如果找不到最短路径,就返回null 220 221     --if(v_res is null) then 222 223     --    return null; 224 225     --end if; 226 227      228 229     --将v_res,v_startLine,v_endLine进行拼接 230 231     select  st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res;232 233  234 235     select  ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart; 236 237     select  ST_Line_Locate_Point(v_res, v_endpoint) into v_perEnd; 238 239         240 241     if(v_perStart > v_perEnd) then 242 243         tempnode =  v_perStart;244 245         v_perStart = v_perEnd;246 247         v_perEnd = tempnode;248 249     end if;250 251         252 253     --截取v_res 254 255     SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath;256 257  258 259     return v_shPath; 260 261  262 263 end; 264 265 $body$ 266 267 LANGUAGE plpgsql VOLATILE STRICT;

 

四、数据发布

数据准备完成后,就需要用GeoServer来进行发布:

启动GeoServer,在浏览器中输入,http://localhost:8080/geoserver/web/,登录到GeoServer。

1.创建工作区

 

添加xblk名称的工作区。

2.添加数据存储:

 

填入对应的连接信息:

 

3.添加图层:

 

注意红框中的内容。

4.添加路径查询服务,添加图层,选择“配置新的SQL视图”:

 

 

视图名称:navigation

SQL语句:

SELECT * FROM pgr_fromAtoB('road_xblk', %x1%, %y1%, %x2%, %y2%)

验证的正则表达式:^-?[\d.]+$

类型:LingString

SRID:4326

点击保存后,填入SRS,并自动计算范围:

 

 

 

五、结果展示

使用OpenLayer进行结果展示,代码请直接下载,结果如下:

 

 

说明:这个最短路径的算法有一定的问题,在特定的条件下,查找的不一定是最短的路径,需要对数据进行再处理,或者对算法进行优化。

 

 

转载于:https://www.cnblogs.com/liongis/p/7692477.html

你可能感兴趣的文章
Android应用开发-网络编程①
查看>>
input中的name,value以及label中的for
查看>>
静态库制作-混编(工程是oc为基础)
查看>>
jQuery 显示加载更多
查看>>
代理模式
查看>>
Confluence 6 系统运行信息中的 JVM 内存使用情况
查看>>
Confluence 6 升级以后
查看>>
用JS实现版面拖拽效果
查看>>
二丶CSS
查看>>
《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript
查看>>
Hibernate主键生成策略
查看>>
Crushing Machinery - Strong Support of Cement Enterprise
查看>>
AsyncTask
查看>>
Django框架(十九)—— drf:序列化组件(serializer)
查看>>
JS一些概念知识及参考链接
查看>>
关于JS中&&和||用法技巧
查看>>
suoi14 子树查找 (dfs)
查看>>
作业5 四则运算 测试与封装 5.1
查看>>
实验7
查看>>
双系统更改启动顺序
查看>>