当前位置:   article > 正文

OpenLayer+Geoserver+postgis实现路径分析_geotools室内路线规划

geotools室内路线规划

这几天一直在研究关于路径规划的问题,postgis也是现学现用,由于SQL的语法掌握还不错,postgis仅需要熟悉常用的函数就行,关于常用的postgis函数,我已经结合网上的一些资料写了一篇文章,关于做一些GIS的空间分析,我们有两种选择,一是选择geotools,二结合postgis,两者选一个即可,我发现postgis+geoserver组合,本质上还是通过geotools来实现的,废话不多说,进入正题

一、路网shapfile文件导入数据库

1、创建数据空间数据库

具体做法在这里不再叙述,网上有许多的教程关于空间数据创建

2、导入shapfile文件

选择插件中的PostGIS shapfile and DBF Loader工具,点击出现如下对话框:

 

点击Add File按钮添加,所要导入的shapfile文件(注意:这里存放shapfile文件的路径必须为纯英文,路径中不能含有汉字,SRD必须设置,这里我设置为4326)

在Options点选下面对号

注意最后一个复选框必须打勾,以此来生成LineString类型,否则无法进行路径规划。

3、查看导入数据

选中roa_4m表格,点击上面的按钮可以查看表格数据。

二、路径规划函数生成

1、添加字段、

  1. --添加起点id
  2. ALTER TABLE roa_4m ADD COLUMN source integer;
  3. --添加终点id
  4. ALTER TABLE roa_4m ADD COLUMN target integer;
  5. --添加道路权重值
  6. ALTER TABLE roa_4m ADD COLUMN length double precision;

2、创建拓扑结构

  1. --为sampledata表创建拓扑布局,即为source和target字段赋值
  2. SELECT pgr_createTopology('roa_4m',0.0001, 'geom', 'gid');

3、创建索引

  1. --为source和target字段创建索引
  2. CREATE INDEX source_idx ON roa_4m("source");
  3. CREATE INDEX target_idx ON roa_4m("target");
  4. ALTER TABLE roa_4m ADD COLUMN x1 double precision; --创建起点经度x1
  5. ALTER TABLE roa_4m ADD COLUMN y1 double precision; --创建起点纬度y1
  6. ALTER TABLE roa_4m ADD COLUMN x2 double precision; --创建起点经度x2
  7. ALTER TABLE roa_4m ADD COLUMN y2 double precision; --创建起点经度y2
  8. UPDATE roa_4m SET x1 =ST_x(ST_PointN(geom, 1));
  9. UPDATE roa_4m SET y1 =ST_y(ST_PointN(geom, 1));
  10. UPDATE roa_4m SET x2 =ST_x(ST_PointN(geom, ST_NumPoints(geom)));
  11. UPDATE roa_4m SET y2 =ST_y(ST_PointN(geom, ST_NumPoints(geom))); --给x1、y1、x2、y2赋值

4、给索引赋值

  1. --为length赋值
  2. --设置为双向
  3. update roa_4m set length =st_length(geom);
  4. --将长度值赋给reverse_cost,作为路线选择标准
  5. ALTER TABLE roa_4m ADD COLUMN reverse_cost double precision;
  6. UPDATE roa_4m SET reverse_cost = st_length(geom);

5、路径函数的生成

  1. -- Function: pgr_fromctod(character varying, double precision, double precision, double precision, double precision)
  2. -- DROP FUNCTION pgr_fromctod(character varying, double precision, double precision, double precision, double precision);
  3. CREATE OR REPLACE FUNCTION pgr_fromctod(
  4. tbl character varying,
  5. startx double precision,
  6. starty double precision,
  7. endx double precision,
  8. endy double precision)
  9. RETURNS geometry AS
  10. $BODY$
  11. declare
  12. v_startLine geometry;--离起点最近的线
  13. v_endLine geometry;--离终点最近的线
  14. v_startTarget integer;--距离起点最近线的终点
  15. v_startSource integer;
  16. v_endSource integer;--距离终点最近线的起点
  17. v_endTarget integer;
  18. v_statpoint geometry;--在v_startLine上距离起点最近的点
  19. v_endpoint geometry;--在v_endLine上距离终点最近的点
  20. v_res geometry;--最短路径分析结果
  21. v_res_a geometry;
  22. v_res_b geometry;
  23. v_res_c geometry;
  24. v_res_d geometry;
  25. v_perStart float;--v_statpoint在v_res上的百分比
  26. v_perEnd float;--v_endpoint在v_res上的百分比
  27. v_shPath_se geometry;--开始到结束
  28. v_shPath_es geometry;--结束到开始
  29. v_shPath geometry;--最终结果
  30. tempnode float;
  31. begin
  32. --查询离起点最近的线
  33. --4326坐标系
  34. --找起点15米范围内的最近线
  35. execute 'select geom, source, target from ' ||tbl||
  36. ' where ST_DWithin(geom,ST_Geometryfromtext(''point('||startx ||' ' || starty||')'',4326),15)
  37. order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1'
  38. into v_startLine, v_startSource ,v_startTarget;
  39. --查询离终点最近的线
  40. --找终点15米范围内的最近线
  41. execute 'select geom, source, target from ' ||tbl||
  42. ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),15)
  43. order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1'
  44. into v_endLine, v_endSource,v_endTarget;
  45. --如果没找到最近的线,就返回null
  46. if (v_startLine is null) or (v_endLine is null) then
  47. return null;
  48. end if ;
  49. select ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')',4326)) into v_statpoint;
  50. select ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint;
  51. -- ST_Distance
  52. --从开始的起点到结束的起点最短路径
  53. execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
  54. 'FROM pgr_kdijkstraPath(
  55. ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','
  56. ||v_startSource|| ', ' ||'array['||v_endSource||'] , false, false
  57. ) a, '
  58. ||tbl|| ' b
  59. WHERE a.id3=b.gid
  60. GROUP by id1
  61. ORDER by id1' into v_res ;
  62. --从开始的终点到结束的起点最短路径
  63. execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
  64. 'FROM pgr_kdijkstraPath(
  65. ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','
  66. ||v_startTarget|| ', ' ||'array['||v_endSource||'] , false, false
  67. ) a, '
  68. ||tbl|| ' b
  69. WHERE a.id3=b.gid
  70. GROUP by id1
  71. ORDER by id1' into v_res_b ;
  72. --从开始的起点到结束的终点最短路径
  73. execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
  74. 'FROM pgr_kdijkstraPath(
  75. ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','
  76. ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false
  77. ) a, '
  78. || tbl || ' b
  79. WHERE a.id3=b.gid
  80. GROUP by id1
  81. ORDER by id1' into v_res_c ;
  82. --从开始的终点到结束的终点最短路径
  83. execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
  84. 'FROM pgr_kdijkstraPath(
  85. ''SELECT gid as id, source, target, length as cost FROM ' || tbl ||''','
  86. ||v_startTarget || ', ' ||'array['||v_endTarget||'] , false, false
  87. ) a, '
  88. || tbl || ' b
  89. WHERE a.id3=b.gid
  90. GROUP by id1
  91. ORDER by id1' into v_res_d ;
  92. if(ST_Length(v_res) > ST_Length(v_res_b)) then
  93. v_res = v_res_b;
  94. end if;
  95. if(ST_Length(v_res) > ST_Length(v_res_c)) then
  96. v_res = v_res_c;
  97. end if;
  98. if(ST_Length(v_res) > ST_Length(v_res_d)) then
  99. v_res = v_res_d;
  100. end if;
  101. --如果找不到最短路径,就返回null
  102. --if(v_res is null) then
  103. -- return null;
  104. --end if;
  105. --将v_res,v_startLine,v_endLine进行拼接
  106. select st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res;
  107. select ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart;
  108. select ST_Line_Locate_Point(v_res, v_endpoint) into v_perEnd;
  109. if(v_perStart > v_perEnd) then
  110. tempnode = v_perStart;
  111. v_perStart = v_perEnd;
  112. v_perEnd = tempnode;
  113. end if;
  114. --截取v_res
  115. --拼接线
  116. SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath;
  117. return v_shPath;
  118. end;
  119. $BODY$
  120. LANGUAGE plpgsql VOLATILE STRICT
  121. COST 100;
  122. ALTER FUNCTION pgr_fromctod(character varying, double precision, double precision, double precision, double precision)
  123. OWNER TO postgres;

(上面函数是不是不知道怎么定义,基本套路在这里postgresql存储过程)生成后的函数,可以在public中函数中查看。

三、PostGIS连接Geoserver发布数据,以及发布视图

1、geoserver连接postgis

点击数据存储---->添加新的数据存储

选择新建数据源 点击postgis

j将红线框选中部分,填写

数据名称--->要连接的数据库名称----->用户名------->密码------->保存

2、发布roa_4m表格为服务

点击图层----->添加新的资源----新建图层(下拉框中选择刚才上面所间的资源)

 

选择我们在postgis中数据表,点击发布即可

3、创建sql视图

方法和上述发布roa_4m表格类似,只不过在一步,选择 配置新的SQL视图。

编辑视图

1)填写视图名称(自己自定义)

2)SQL语句

select * from pgr_fromctod('roa_4m',%x1%, %y1%, %x2%, %y2%)

3)点击从SQL猜想的参数,D的默认值,全部为0,验证的正则表达式全部为^-?[\d.]+$

4)点击刷新,类型选为LineString类型,SRD为4326

5)点击保存,然后发布

四、OL调用demo

  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>室内路径规划</title>
  6. <link href="../script/ol4/ol.css" rel="stylesheet" />
  7. <style>
  8. #id {
  9. width:1000px;
  10. height:1000px;
  11. }
  12. </style>
  13. <script src="../script/ol4/ol.js"></script>
  14. </head>
  15. <body>
  16. <div id="map"></div>
  17. <script>
  18. var roadLayer = new ol.layer.Tile({
  19. source: new ol.source.TileWMS({
  20. url: 'http://localhost:8080/geoserver/cite/wms',
  21. params: { 'LAYERS': 'cite:roa_4', 'TILED': true },
  22. serverType: 'geoserver'
  23. })
  24. })
  25. var map = new ol.Map({
  26. target: document.getElementById("map"),
  27. layers: [
  28. roadLayer
  29. ],
  30. view: new ol.View({
  31. center: [117.34211730957, 49.6271781921387],
  32. projection: 'EPSG:4326',
  33. zoom: 4
  34. })
  35. });
  36. var startCoord = [117.34211730957, 49.6271781921387]
  37. var destCoord = [127.216133117676, 45.7485237121582]
  38. var params = {
  39. LAYERS: 'cite:testSqlView',
  40. FORMAT: 'image/png',
  41. };
  42. var viewparams = [
  43. 'x1:' + startCoord[0], 'y1:' + startCoord[1],
  44. 'x2:' + destCoord[0], 'y2:' + destCoord[1]
  45. //'x1:' + 12952117.2529, 'y1:' + 4836395.5717,
  46. //'x2:' + 12945377.2585, 'y2:' + 4827305.7549
  47. ];
  48. console.log(viewparams);
  49. params.viewparams = viewparams.join(';');
  50. result = new ol.layer.Image({
  51. source: new ol.source.ImageWMS(
  52. {
  53. url: 'http://localhost:8080/geoserver/cite/wms',
  54. params: params
  55. })
  56. });
  57. console.info(result);
  58. map.addLayer(result);
  59. </script>
  60. </body>
  61. </html>

五、效果图(蓝色线段)

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小舞很执着/article/detail/867748
推荐阅读
相关标签
  

闽ICP备14008679号