postgresql+pgrouting 最短路線sql (4)
阿新 • • 發佈:2018-12-06
CREATE EXTENSION postgis; --新增postgis功能 CREATE EXTENSION pgrouting; --新增pgRouting函式 CREATE EXTENSION postgis_topology; CREATE EXTENSION fuzzystrmatch; CREATE EXTENSION postgis_tiger_geocoder; CREATE EXTENSION address_standardizer; --新增起點id ALTER TABLE public.route5 ADD COLUMN source integer; --新增終點id ALTER TABLE public.route5 ADD COLUMN target integer; --新增道路權重值 ALTER TABLE public.route5 ADD COLUMN length double precision; --為sampledata表建立拓撲佈局,即為source和target欄位賦值 SELECT pgr_createTopology('public.route5',0.00001, 'geom', 'gid'); --為source和target欄位建立索引 CREATE INDEX source_idx ON route5("source"); CREATE INDEX target_idx ON route5("target"); --為length賦值 update route5 set length =st_length(geom); --為beijingmodified表新增reverse_cost欄位並用length的值賦值 ALTER TABLE route5 ADD COLUMN reverse_cost double precision; UPDATE route5 SET reverse_cost =length; --使用pgr_dijkstra演算法查詢 SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_dijkstra(' SELECT gid AS id, source::integer, target::integer, length::double precision AS cost FROM route5', 1, 6, false, false); --為表格beijingmodified新增x1,y1,x2,y2欄位 ALTER TABLE route5 ADD COLUMN x1 double precision; ALTER TABLE route5 ADD COLUMN y1 double precision; ALTER TABLE route5 ADD COLUMN x2 double precision; ALTER TABLE route5 ADD COLUMN y2 double precision; --為新新增的屬性欄位賦值 UPDATE route5 SET x1 =ST_x(ST_PointN(geom, 1)); UPDATE route5 SET y1 =ST_y(ST_PointN(geom, 1)); UPDATE route5 SET x2 =ST_x(ST_PointN(geom, ST_NumPoints(geom))); UPDATE route5 SET y2 =ST_y(ST_PointN(geom, ST_NumPoints(geom))); SELECT seq, id1 AS node, id2 AS edge, cost FROM pgr_astar(' SELECT gid AS id, source::integer, target::integer, length::double precision AS cost, x1, y1, x2, y2 FROM route5',1, 6, false,false); CREATE OR REPLACE function pgr_fromAtoB(tbl varchar,startx float, starty float,endx float,endy float) returns geometry as $body$ declare v_startLine geometry;--離起點最近的線 v_endLine geometry;--離終點最近的線 v_startTarget integer;--距離起點最近線的終點 v_endSource integer;--距離終點最近線的起點 v_statpoint geometry;--在v_startLine上距離起點最近的點 v_endpoint geometry;--在v_endLine上距離終點最近的點 v_res geometry;--最短路徑分析結果 v_perStart float;--v_statpoint在v_res上的百分比 v_perEnd float;--v_endpoint在v_res上的百分比 v_shPath geometry;--最終結果 tempnode float; begin --查詢離起點最近的線 execute 'select geom ,target from ' ||tbl|| ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty||')'', 4326),15) order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'', 4326)) limit 1' into v_startLine ,v_startTarget; --查詢離終點最近的線 execute 'select geom,source from ' ||tbl|| ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| endx || ' ' || endy ||')'', 4326),15) order by ST_Distance(geom,ST_GeometryFromText(''point('|| endx ||' ' || endy ||')'', 4326)) limit 1' into v_endLine,v_endSource; --如果沒找到最近的線,就返回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; --最短路徑 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, ' || tbl || ' b WHERE a.id3=b.gid GROUP by id1 ORDER by id1' into v_res ; --如果找不到最短路徑,就返回null --if(v_res is null) then -- return null; --end if; --將v_res,v_startLine,v_endLine進行拼接 select st_linemerge(ST_Union(array[v_res,v_startLine,v_endLine])) into v_res; select ST_Line_Locate_Point(v_res, v_statpoint) into v_perStart; select ST_Line_Locate_Point(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_shPath; return v_shPath; end; $body$ LANGUAGE plpgsql VOLATILE STRICT