总体思路是用geoserver发布图层,图层为 sql,视图是利用存储过程分析出的路径结果,node
路网通常为shp数据,若是有多个图层,建议利用arcgis或其余工具合并为一个图层,方便处理web
使用paAdmin3链接PostgreSQL,并执行如下语句,在新的空间数据库里添加空间扩展:ajax
CREATE EXTENSION postgis; CREATE EXTENSION pgrouting; CREATE EXTENSION postgis_topology; CREATE EXTENSION fuzzystrmatch; CREATE EXTENSION postgis_tiger_geocoder; CREATE EXTENSION address_standardizer;
添加路网数据,设置表名,并设置SRID为:4326
须要使用GBK编码,并勾选最下面一个选项。正则表达式
1.修改表结构sql
--添加起点id ALTER TABLE lproad ADD COLUMN source integer; --添加终点id ALTER TABLE lproad ADD COLUMN target integer; --添加道路权重值 ALTER TABLE lproad ADD COLUMN length double precision
2.建立拓扑结构 数据库
--为lproad表建立拓扑布局,即为source和target字段赋值 SELECT pgr_createTopology('lproad ',0.0001, 'geom', 'gid');
3.建立索引json
--为source和target字段建立索引 CREATE INDEX source_idx ON lproad ("source"); CREATE INDEX target_idx ON lproad ("target");
4.给长度赋值浏览器
--为length赋值 update lproad set length =st_length(geom); --为lproad 表添加reverse_cost字段并用length的值赋值 ALTER TABLE lproad ADD COLUMN reverse_cost double precision; UPDATE lproad SET reverse_cost =length;
-- DROP FUNCTION public.pgr_fromatoe(double precision, double precision, double precision, double precision); CREATE OR REPLACE FUNCTION pgr_fromatoe( tbl varchar, startx double precision, starty double precision, endx double precision, endy double precision) RETURNS geometry LANGUAGE 'plpgsql' COST 100 VOLATILE STRICT AS $BODY$ declare v_startLine geometry;--离起点最近的线 v_endLine geometry;--离终点最近的线 v_startTarget integer;--距离起点最近线的终点 v_startSource integer; v_endSource integer;--距离终点最近线的起点 v_endTarget integer; v_statpoint geometry;--在v_startLine上距离起点最近的点 v_endpoint geometry;--在v_endLine上距离终点最近的点 v_res geometry;--最短路径分析结果 v_res_a geometry; v_res_b geometry; v_res_c geometry; v_res_d geometry; v_start_temp geometry; v_start_temp1 geometry; v_start_temp2 geometry; v_end_temp geometry; v_end_temp1 geometry; v_end_temp2 geometry; v_perStart float;--v_statpoint在v_res上的百分比 v_perEnd float;--v_endpoint在v_res上的百分比 v_shPath_se geometry;--开始到结束 v_shPath_es geometry;--结束到开始 v_shPath geometry;--最终结果 tempnode float; startpoint geometry; endpoint geometry; v_shPath1 geometry;--一次结果 v_shPath2 geometry;--二次结果 star_line geometry; --起点到最近点的线 end_line geometry; --终点到最近点的线 geoARR geometry[]; begin --查询离起点最近的线 --4326坐标系 --找起点15米范围内的最近线 execute 'select geom, source, target from '|| tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty||')'',4326),3000) order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',4326)) limit 1' into v_startLine, v_startSource ,v_startTarget; raise notice '%', v_startSource; raise notice '%', v_startTarget; --查询离终点最近的线 --找终点15米范围内的最近线 execute 'select geom, source, target from '|| tbl || ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'',4326),3000) order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'',4326)) limit 1' into v_endLine, v_endSource,v_endTarget; raise notice '%', v_endSource; raise notice '%', v_endTarget; --若是没找到最近的线,就返回null if (v_startLine is null) or (v_endLine is null) then return null; end if ; select ST_ClosestPoint(v_startLine, ST_Geometryfromtext('point('|| startx ||' ' || starty ||')',4326)) into v_statpoint; select ST_ClosestPoint(v_endLine, ST_GeometryFromText('point('|| endx ||' ' || endy ||')',4326)) into v_endpoint; -- ST_Distance --从开始的起点到结束的起点最短路径 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 'FROM pgr_kdijkstraPath( ''SELECT gid as id, source, target, length as cost FROM '|| tbl ||' '',' ||v_startSource || ', ' ||'array['||v_endSource||'] , false, false ) a, lproad b WHERE a.id3=b.gid GROUP by id1 ORDER by id1' into v_res ; --从开始的终点到结束的起点最短路径 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 'FROM pgr_kdijkstraPath( ''SELECT gid as id, source, target, length as cost FROM '|| tbl ||' '',' ||v_startTarget || ', ' ||'array['||v_endSource||'] , false, false ) a, lproad b WHERE a.id3=b.gid GROUP by id1 ORDER by id1' into v_res_b ; --从开始的起点到结束的终点最短路径 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 'FROM pgr_kdijkstraPath( ''SELECT gid as id, source, target, length as cost FROM '|| tbl ||' '',' ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false ) a, lproad b WHERE a.id3=b.gid GROUP by id1 ORDER by id1' into v_res_c ; --从开始的终点到结束的终点最短路径 execute 'SELECT st_linemerge(st_union(b.geom)) ' || 'FROM pgr_kdijkstraPath( ''SELECT gid as id, source, target, length as cost FROM '|| tbl ||' '',' ||v_startTarget || ', ' ||'array['||v_endTarget||'] , false, false ) a, lproad b WHERE a.id3=b.gid GROUP by id1 ORDER by id1' into v_res_d ; if(ST_Length(v_res) > ST_Length(v_res_b)) then v_res = v_res_b; end if; if(ST_Length(v_res) > ST_Length(v_res_c)) then v_res = v_res_c; end if; if(ST_Length(v_res) > ST_Length(v_res_d)) then v_res = v_res_d; end if; --若是找不到最短路径,就返回null if(v_res is null) then return null; end if; --将v_res,v_startLine,v_endLine进行拼接 --select st_linemerge(ST_Union(array[v_startLine,v_res,v_endLine])) into v_res; select ST_LineLocatePoint(v_startLine, v_statpoint) into v_perStart; select ST_LineLocatePoint(v_endLine, v_endpoint) into v_perEnd; SELECT ST_Line_SubString(v_startLine,v_perStart, 1) into v_start_temp1; SELECT ST_Line_SubString(v_startLine,0,v_perStart) into v_start_temp2; SELECT ST_Line_SubString(v_endLine,v_perEnd, 1) into v_end_temp1; SELECT ST_Line_SubString(v_endLine,0,v_perEnd) into v_end_temp2; raise notice '%', v_perStart; raise notice '%', v_perEnd; raise notice '%', ST_Distance(v_res,v_start_temp1); raise notice '%', ST_Distance(v_res,v_start_temp2); raise notice '%', ST_Distance(v_res,v_end_temp2); raise notice '%', ST_Distance(v_res,v_end_temp1); v_start_temp=v_start_temp1; if(ST_Distance(v_res,v_start_temp1) > ST_Distance(v_res,v_start_temp2)) then v_start_temp=v_start_temp2; end if; v_end_temp=v_end_temp1; if(ST_Distance(v_res,v_end_temp1) > ST_Distance(v_res,v_end_temp2)) then v_end_temp=v_end_temp2; end if; --return ST_AsGeoJSON(v_res); --return v_res; -- select ST_LineLocatePoint(v_res, v_statpoint) into v_perStart; -- select ST_LineLocatePoint(v_res, v_endpoint) into v_perEnd; --if(v_perStart > v_perEnd) then -- tempnode = v_perStart; -- v_perStart = v_perEnd; -- v_perEnd = tempnode; --end if; --截取v_res --拼接线 --SELECT ST_Line_SubString(v_res,v_perStart, v_perEnd) into v_shPath1; select st_linemerge(ST_Union(array[v_start_temp,v_res,v_end_temp])) into v_shPath1; return v_shPath1; --后续为将起点终点与路网链接起来,因发布时有点问题,暂不使用 --找线的端点 select ST_SetSRID( ST_MakePoint(startx , starty),4326 )into startpoint; select ST_SetSRID( ST_MakePoint(endx , endy),4326 )into endpoint; select ST_MakeLine( v_statpoint,startpoint) into star_line; select ST_MakeLine( v_endpoint,endpoint) into end_line; geoARR :=array[end_line,v_shPath1,star_line]; select st_union(geoARR) into v_shPath; raise notice '%', '返回数据'; --raise notice '%', ST_AsGeoJSON(v_shPath); return v_shPath; end; $BODY$;
数据准备完成后,就须要用GeoServer来进行发布:app
启动GeoServer,在浏览器中输入,http://localhost:8080/geoserver/web/,登陆到GeoServer。函数
配置数据库链接
选择“配置新的SQL视图”,输入SQL语句:
SELECT * FROM pgr_fromAtoB('road_xblk', %x1%, %y1%, %x2%, %y2%)
验证的正则表达式:^-?[d.]+$
类型:LingString
SRID:4326
点击保存后,填入SRS,并自动计算范围
var viewparams = [ 'x1:' + startCoord[0], 'y1:' + startCoord[1], 'x2:' + destCoord[0], 'y2:' + destCoord[1] ]; params.viewparams = viewparams.join(';'); result = new ol.layer.Image({ source: new ol.source.ImageWMS({ url: ServerUrl + '/geoserver/Routing/wms', params: params }) }); map.addLayer(result);
var vectorSource = new ol.source.Vector({ format: new ol.format.GeoJSON(), url: function (extent) { return ServerUrl + '/geoserver/wfs?service=WFS&' + 'version=1.1.0&request=GetFeature&typename=Routing:lproute&' + 'outputFormat=application/json&srsname=EPSG:4326&' + 'bbox=' + extent.join(',') + ',EPSG:4326&' + 'viewparams=' + viewparams.join(';'); }, strategy: ol.loadingstrategy.bbox }); var vector = new ol.layer.Vector({ source: vectorSource, }); map.addLayer(vector);
var wfsurl = ServerUrl + '/geoserver/wfs?service=WFS&' + 'version=1.1.0&request=GetFeature&typename=Routing:lproute&' + 'outputFormat=application/json&srsname=EPSG:4326&' + 'viewparams=' + viewparams.join(';'); $.ajax({ url: wfsurl, success: function (result) { console.log(result); } });
效果如图: