使用PostGis存储路线数据,在GeoServer中发布路网图层和最短路径图层,通过OpenLayers建立路网和展示图层。

1、PostGis:PostgreSQL 12.4,
2、GeoServer:geoserver-2.17.2
3、OpenLayers:6.4.3

一、做成路网数据

1、在PostGis建立路网数据表,主键使用sequence,路网geom 使用geometry(LineString,4326)

CREATE SEQUENCE public.my_roads_id_seqINCREMENT 1START 1MINVALUE 1MAXVALUE 2147483647CACHE 1;ALTER SEQUENCE public.my_roads_id_seq OWNER TO postgres;CREATE TABLE public.my_roads
(id integer NOT NULL DEFAULT nextval('my_roads_id_seq'::regclass),name character varying(32) COLLATE pg_catalog."default",geom geometry(LineString,4326),CONSTRAINT my_roads_pkey PRIMARY KEY (id)
)TABLESPACE pg_default;ALTER TABLE public.my_roads OWNER to postgres;

2、在GeoServer中发布路网图层

建立工作区,建立postgis的数据存储,发布my_roads图层。

EPSG使用4326,边框及经纬度为:【-180,-90 】【180,90】即可。

3、OpenLayers中建立路网

使用vue开发路网编辑画面。

实现方式,请参考:OpenLayers 在Vue中增删改

注意点:新增的线不再是newFeature.setGeometry(new MultiLineString([geometry.getCoordinates()]))

// 转换坐标let geometry = this.drewFeature.getGeometry().clone();geometry.applyTransform(function (flatCoordinates, flatCoordinates2, stride) {for (let j = 0; j < flatCoordinates.length; j += stride) {let y = flatCoordinates[j];let x = flatCoordinates[j + 1];flatCoordinates[j] = x;flatCoordinates[j + 1] = y;}});// 设置feature对应的属性,这些属性是根据数据源的字段来设置的let newFeature = new Feature();newFeature.setId('nyc_roads.new.' + this.newId);newFeature.setGeometryName('the_geom');newFeature.set('the_geom', null);newFeature.set('name', newFeature.getId());newFeature.setGeometry(new MultiLineString([geometry.getCoordinates()]));

而是newFeature.setGeometry(geometry);

// 转换坐标
let geometry = this.drewFeature.getGeometry().clone();
geometry.applyTransform(function (flatCoordinates, flatCoordinates2, stride) {for (let j = 0; j < flatCoordinates.length; j += stride) {let y = flatCoordinates[j];let x = flatCoordinates[j + 1];flatCoordinates[j] = x;flatCoordinates[j + 1] = y;}
});// 设置feature对应的属性,这些属性是根据数据源的字段来设置的
let newFeature = new Feature();
newFeature.setId('am_roads.new.' + this.newId);
newFeature.setGeometryName('geom');
newFeature.set('geom', null);
newFeature.set('name', newFeature.getId());
newFeature.setGeometry(geometry);

编辑好的路网如下:

二、路径分析基础数据

1、路网拓扑生成

-- 创建拓扑布局,即为source和target字段赋值
select pgr_createTopology('my_roads',0.001, 'geom', 'id');--为cost 赋值
update my_roads set cost =st_length(geom);
--为双向reverse_cost 赋值
UPDATE my_roads SET reverse_cost = st_length(geom);--为线的起点和终点坐标赋值
UPDATE my_roads SET x1 =ST_x(ST_PointN(geom, 1));
UPDATE my_roads SET y1 =ST_y(ST_PointN(geom, 1));
UPDATE my_roads SET x2 =ST_x(ST_PointN(geom, ST_NumPoints(geom)));
UPDATE my_roads SET y2 =ST_y(ST_PointN(geom, ST_NumPoints(geom)));

2、最短路径函数

此函数参考网上路径分析函数,解决了计算不准确问题和MultiLineString问题。

  • 建立根据拓扑后节点,计算最短路径函数pgr_shortestpath_edge。
CREATE  OR REPLACE FUNCTION pgr_shortestpath_edge (tbl CHARACTER VARYING,fromNode INTEGER,toNode INTEGER,startLine geometry,endLine geometry)
RETURNS geometry
AS $BODY$
DECLAREv_res geometry;--最短路径分析结果v_linemerge geometry;--合并线后结果v_shPath geometry;--最终结果
BEGIN--从开始的节点到结束的节点最短路径EXECUTE'SELECT st_linemerge(st_union(b.geom)) ' || 'FROM pgr_dijkstra( ''SELECT id, source, target, cost FROM ' || tbl || ''',' || fromNode || ', ' || toNode || ', false ) aLEFT JOIN  ' || tbl || ' b  ON a.edge = b.id ' INTO v_res;-- 合并线select  st_linemerge(ST_Union(array[startLine, v_res, endLine])) into v_linemerge; RETURN v_linemerge;
END; $BODY$ LANGUAGE plpgsql VOLATILE STRICT COST 100;
ALTER FUNCTION pgr_shortestpath_edge ( CHARACTER VARYING, INTEGER, INTEGER, geometry, geometry ) OWNER TO postgres;
  • 建立最短路径函数
CREATE  OR REPLACE FUNCTION pgr_shortestpath ( tbl CHARACTER VARYING, startx DOUBLE PRECISION, starty DOUBLE PRECISION, endx DOUBLE PRECISION, endy DOUBLE PRECISION ) RETURNS geometry
AS $BODY$ DECLAREv_startLine geometry;--离起点最近的线v_endLine geometry;--离终点最近的线v_startPoint geometry;--在v_startLine上距离起点最近的点v_endPoint geometry;--在v_endLine上距离终点最近的点v_startLine_pre geometry; --起点到v_startPoint的线  v_endLine_next geometry; --终点到v_endPoint的线  v_startPoint_pre geometry;  --起点v_endPoint_pre geometry;  --终点v_startTarget INTEGER;--距离起点最近线的目标节点v_startSource INTEGER;--距离起点最近线的源节点v_endSource INTEGER;--距离终点最近线的源节点v_endTarget INTEGER;--距离起点最近线的目标节点v_start_x1 double precision;v_start_y1 double precision;v_start_x2 double precision;v_start_y2 double precision;v_end_x1 double precision;v_end_y1 double precision;v_end_x2 double precision;v_end_y2 double precision;v_startLine_Source geometry;v_startLine_Target geometry;v_endLine_Source geometry;v_endLine_Target geometry;v_res geometry;--最短路径分析结果v_res_a geometry;v_res_b geometry;v_res_c geometry;v_res_d geometry;v_shPath geometry;--最终结果BEGIN--查询离0.01度(大约1000米)范围内起点的最近线EXECUTE'select geom, source, target,x1,y1,x2,y2  from ' || tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point(' || startx || ' ' || starty || ')'',4326),0.01)order by ST_Distance(geom,ST_GeometryFromText(''point(' || startx || ' ' || starty || ')'',4326))  limit 1'INTO v_startLine,v_startSource,v_startTarget,v_start_x1,v_start_y1,v_start_x2,v_start_y2;--查询离终点0.01度(大约1000米)范围内的最近线EXECUTE'select geom, source, target,x1,y1,x2,y2 from ' || tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point(' || endx || ' ' || endy || ')'',4326),0.01)order by ST_Distance(geom,ST_GeometryFromText(''point(' || endx || ' ' || endy || ')'',4326))  limit 1' INTO v_endLine,v_endSource,v_endTarget,v_end_x1,v_end_y1,v_end_x2,v_end_y2;--如果没找到最近的线,就返回nullIF ( v_startLine IS NULL )  OR ( v_endLine IS NULL ) THENRETURN NULL;END IF;--创建查询的起点和终点  SELECT ST_SetSRID( ST_MakePoint(startx , starty),4326 )INTO v_startPoint_pre;  SELECT ST_SetSRID( ST_MakePoint(endx , endy),4326 )INTO v_endPoint_pre;  --查询线上最接近某点的点(此点在线上)SELECT ST_ClosestPoint ( v_startLine, v_startPoint_pre) INTO v_startPoint;SELECT ST_ClosestPoint ( v_endLine, v_endPoint_pre) INTO v_endPoint;--根据最近点,把最近线分为source和target两段SELECT ST_MakeLine( v_startPoint,ST_SetSRID( ST_MakePoint(v_start_x1 , v_start_y1),4326 )) INTO v_startLine_Source;SELECT ST_MakeLine( v_startPoint,ST_SetSRID( ST_MakePoint(v_start_x2 , v_start_y2),4326 )) INTO v_startLine_Target;SELECT ST_MakeLine( v_endPoint,ST_SetSRID( ST_MakePoint(v_end_x1 , v_end_y1),4326 )) INTO v_endLine_Source;SELECT ST_MakeLine( v_endPoint,ST_SetSRID( ST_MakePoint(v_end_x2 , v_end_y2),4326 )) INTO v_endLine_Target;--计算最短路径(开始的起点/终点 --- 结束的起点/终点)SELECT pgr_shortestpath_edge (tbl, v_startSource, v_endSource, v_startLine_Source, v_endLine_Source) INTO v_res_a;SELECT pgr_shortestpath_edge (tbl, v_startTarget, v_endSource, v_startLine_Target, v_endLine_Source) INTO v_res_b;SELECT pgr_shortestpath_edge (tbl, v_startSource, v_endTarget, v_startLine_Source, v_endLine_Target) INTO v_res_c;SELECT pgr_shortestpath_edge (tbl, v_startTarget, v_endTarget, v_startLine_Target, v_endLine_Target) INTO v_res_d;v_res = v_res_a;IF( ST_Length ( v_res ) > ST_Length ( v_res_b )) THENv_res = v_res_b;END IF;IF(ST_Length ( v_res ) > ST_Length ( v_res_c )) THENv_res = v_res_c;END IF;IF(ST_Length ( v_res ) > ST_Length ( v_res_d )) THENv_res = v_res_d;END IF;--创建查询起点和终点到最近的线之间的线SELECT ST_MakeLine( v_startPoint,v_startPoint_pre) INTO v_startLine_pre;  SELECT ST_MakeLine( v_endPoint,v_endPoint_pre) INTO v_endLine_next;  select st_union(array[v_endLine_next, v_res, v_startLine_pre]) into v_shPath; return v_shPath;
END; $BODY$ LANGUAGE plpgsql VOLATILE STRICT COST 100;
ALTER FUNCTION pgr_shortestpath ( CHARACTER VARYING, DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION, DOUBLE PRECISION ) OWNER TO postgres;

三、显示最短路径

1、GeoServer建立创建sql视图



D的默认值全部为0,
验证的正则表达式全部为^-?[\d.]+$
类型选为 Geometry类型,SRD为4326

2、OpenLayer中传参并加载最短路径图层

VUE中增加加载最短路径图层方法:

querypath(){let startCoord = [116.43442149206543,39.927703206481944]let destCoord = [116.410648020996,39.9069321798706]let params = {LAYERS: 'postgis:shortestpath',FORMAT: 'image/png',};let viewparams = ['x1:' + startCoord[0], 'y1:' + startCoord[1],'x2:' + destCoord[0], 'y2:' + destCoord[1]];params.viewparams = viewparams .join(';');let imageLayer = new ImageLayer({source: new ImageWMS({url: 'http://localhost:8088/geoserver/postgis/wms',params: params}),});this.map.addLayer(imageLayer);
},

3、最终结果显示

PostGis+GeoServer+OpenLayers最短路径分析相关推荐

  1. postgis+geoserver+openlayers最短路径分析-学习记录bug

    学习postgis+geoserver+openlayers最短路径分析,记录遇到的奇奇怪怪的问题. 主要参考: https://www.cnblogs.com/giser-s/p/11599562. ...

  2. PostGIS 结合Openlayers以及Geoserver实现最短路径分析(二)

    前文讲述了怎么用ArcMap制作了测试数据,并导入了PostGIS,接下来我们需要结合PgRouting插件,对入库的数据再进行一下处理. 1.在pgAdmin中,执行下面的sql语句 --添加起点字 ...

  3. postgis+geoserver最短路径

    postgis+geoserver最短路径 1 安装软件 2 数据预处理 3 操作postgres 4 操作Geoserver 5 计算最短路径 6 问题记录 1 安装软件 安装PostgreSQL与 ...

  4. 最短路径分析之两点之间的k条最短路径

    目录 前言 Yen算法 数据准备 求取k条最短路径(KSP) 预览结果 前言 在用高德地图导航的时候都会发现,高德会推荐多条线路.我们之前做的dijkstra算法只能实现两点之间的1条最短路径的计算. ...

  5. ArcMap最短路径分析和网络数据集的构建

    打断相交点 1.单击[编辑器]工具条上的编辑工具. 2.选择要在交叉点处进行分割的线要素. 3.单击[高级编辑]工具条上的打断相交线工具. 4.默认或可输入拓扑容差. 5.单击确定. 结果:所选线在相 ...

  6. ArcGIS二次开发基础教程(11):网络分析之最短路径分析

    ArcGIS二次开发基础教程(11):网络分析之最短路径分析 最短路径分析 这里直接调用了在mdb中建立好的网络数据集 //全局变量 private INetworkDataset my_networ ...

  7. 最短路径分析+路书(详细导航信息)

    1.思路: 1.抽取路网(管网)各节点,点去重+点线关联:---根据数据及业务场景可选择线起始点/起中终点/全部节点: 2.构建路网(管网)各节点KDtree: 3.使用邻接矩阵存储点连通性:--不通 ...

  8. ArcGI Server+GP服务完成最短路径分析(实践经验)

    最近用arcgis GP服务做了几个Demo,为了不丢失自己的实践经验,我决定把过程记下来!!! (一)最短路径分析 以上为效果图,在此感谢 http://www.tzwhx.com/newOpera ...

  9. (转)PostGIS+QGIS+GeoServer+OpenLayers实现数据的存储、服务的发布以及地图的显示...

    http://blog.csdn.net/gisshixisheng/article/details/41575833 标题比较长,主要呢是实现以下几点: 1.将shp数据导入到PostGIS中: 2 ...

  10. 使用PostGIS+GeoServer+Openlayer+Vue构建简单的web地图应用

    一.将shx通过postgis导入 1.创建数据库 2.右键–>新建对象–>新建扩展 3.菜单栏点击插件–>打开postgis 也可通过开始菜单 注意点:文件路径不可有中文,文件格式 ...

最新文章

  1. 快速理解平衡二叉树、B-tree、B+tree、B*tree
  2. python宏替换_#和##在宏替换中的作用
  3. hibernate自定义_如何自定义Hibernate脏检查机制
  4. inline行内元素
  5. pv,svogi,vxgi,各自的优缺点在哪,ue4还有可能把svogi加进去吗
  6. 比穷更可怕的事情是什么?
  7. 网上看到的,关于测试用例编写粒度准则
  8. Python3.x中的三目运算实现方法
  9. 1月4日 每次安装都有新问题
  10. 双击鼠标触发了Ctrl+C事件
  11. 思科下一代模拟器EVE-NG做一个不同VLAN互通实验
  12. ESP分区引导文件修复bcdboot .exe
  13. 软件构造第一次实验感想总结
  14. mysql 把表名改成大写_mysql 把表名自动改为大写
  15. Project Server 2016 部署
  16. python羊车门问题
  17. oro什么意思_oro
  18. java把字符转成浮点_java 字符型转换成浮点型
  19. MiniUI Api 方法
  20. Python数据类型——String

热门文章

  1. Python和C++的混合编程(使用Boost编写Python的扩展包)
  2. py 的 第 12 天
  3. 如何选择最佳云托管服务提供商
  4. LeetCode刷刷记录
  5. 孔茨的现代管理理论的十一个流派
  6. 【转】wait_fences: failed to receive reply: 10004003问题的引起原因
  7. 1.性能之巅 洞悉系统、企业与云计算 --- 绪论
  8. 5.docker 命令
  9. 47.使用外部 JavaScript 和 CSS(8)
  10. 编写iPhone应用程序有何不同