這個算法算是被摒棄了,可是不少本身思考事後留下的成果,雖然不用了,留着作記錄。算法
算法目的是爲了發生爆管後找到總閥門,這裏分了幾個步驟:sql
一、找到爆管點所在管段數組
二、經過遍歷找到爆管點全部影響的閥門app
三、找到影響閥門中的上游閥門post
四、在上游閥門中進行遍歷,看相互關係,與其餘閥門都聯通的則視爲總閥門spa
五、找出閥門中的總閥門code
#考慮了一下,全部與爆點相連的上游閥門其實在爆管發生後都須要關閉。因此算法中四、5步,不須要了。blog
-- Function: test_getpoint7(character varying, double precision, double precision) -- DROP FUNCTION test_getpoint7(character varying, double precision, double precision); CREATE OR REPLACE FUNCTION test_getpoint7( IN tbl character varying, IN startx double precision, IN starty double precision) RETURNS TABLE(v_gid integer, v_res geometry, v_type integer) AS $BODY$ declare v_startLine geometry;--離起點最近的線 v_startTarget integer;--距離起點最近線的終點 v_startSource integer; v_statpoint geometry;--在v_startLine上距離起點最近的點 v_endpoint geometry;--在v_endLine上距離終點最近的點 v_up_source integer;--遊標,記錄是否有記錄 v_up_idx integer;--記錄遍歷到多少層級 v_uptap_gid integer;--上游閥門gid v_uptap_geom geometry;--上游閥門要素 v_all_where integer[];--記錄全部查詢過的管段 v_up_where integer[];--where條件,將遍歷到閥門的管段gid排除 v_down_where integer[];--where條件,將遍歷到閥門的管段gid排除 up_temprow record ; --v_cost record;--記錄閥門管段source(用於計算消耗,判斷方向) m_cost integer; m_cost_value integer; temprow record; v_cost integer[]; res_source integer; res_tap_pipe text[]; m_tap_pipe text; idx_tap_pipe integer; --遍歷結果遊標 m_up_cost integer;--上游閥門 v_up_cost integer[];--上游閥門集合 res_main_pipe integer[];--總閥門集合 m_main_pipe integer;--總閥門 begin --查詢離起點最近的線 --3857座標系 --找起點15米範圍內的最近線 execute 'select geom, source, target, ST_StartPoint(geom) as startpoint,ST_EndPoint(geom) as endpoint from ' ||tbl|| ' where ST_DWithin(geom,ST_Geometryfromtext(''point('|| startx ||' ' || starty ||')'',3857),15) order by ST_Distance(geom,ST_GeometryFromText(''point('|| startx ||' '|| starty ||')'',3857)) limit 1' into v_startLine, v_startSource ,v_startTarget, v_statpoint ,v_endpoint; IF(v_startLine is not null) THEN --查找上游閥門 v_up_idx = 0; v_up_source = 1; --尋找上游閥門 SELECT array_append(v_up_where, v_startSource) into v_up_where; --若是沒有下級節點須要遍歷 WHILE array_length(v_up_where,1) > 0 LOOP --遊標歸零 v_up_source = 0; --記錄層級 v_up_idx = v_up_idx + 1; --獲取當前層級節點 FOR up_temprow IN select zy1.gid,zy1.source,zy1.target from zy zy1 where source = any(v_up_where) or target = any(v_up_where) --select zy1.gid,zy1.source,zy1.target from zy zy1 where target = any(v_up_where)--找上游 LOOP --清空須要查的點 IF(v_up_source = 0) THEN v_up_where = null; END IF; --清空初始執行節點 v_startSource = 0; --標誌執行有數據 v_up_source = 1; --查詢管網上的點 select t.gid,t.geom from fm t where t.gid in ( select a.gid from fm a,(select c.* from zy c where c.gid = up_temprow.gid) b where ST_intersects(a.geom,b.geom) ) into v_uptap_gid, v_uptap_geom; raise notice '%' , 'UP---'||up_temprow.gid; --若是沒查找到閥門,則繼續往下查 IF(v_uptap_gid is null) then --source去重,判斷若是數組中已有,則不添加 IF (v_up_where @> ARRAY[up_temprow.source::integer] OR v_all_where @> ARRAY[up_temprow.source::integer]) THEN ELSE SELECT array_append(v_up_where,up_temprow.source) into v_up_where; SELECT array_append(v_all_where,up_temprow.source) into v_all_where; END IF; --target去重,判斷若是數組中已有,則不添加 IF (v_up_where @> ARRAY[up_temprow.target::integer] OR v_all_where @> ARRAY[up_temprow.target::integer]) THEN ELSE SELECT array_append(v_up_where,up_temprow.target) into v_up_where; SELECT array_append(v_all_where,up_temprow.target) into v_all_where; END IF; ELSE raise notice '%' , up_temprow.source; --記錄閥門所在管段source IF (v_cost @> ARRAY[up_temprow.source::integer]) THEN ELSE SELECT array_append(v_cost,up_temprow.source) into v_cost; SELECT array_append(v_cost,up_temprow.target) into v_cost; END IF; --insert into v_cost values (up_temprow.gid,up_temprow.source,v_uptap_gid,v_uptap_geom ); --insert into v_cost values (up_temprow.gid,up_temprow.target,v_uptap_gid,v_uptap_geom ); --insert into v_cost values (up_temprow.gid,v_uptap_geom ,v_uptap_gid); --return next v_cost; --insert into v_taps values (v_uptap_gid, v_uptap_geom, up_temprow.source); --v_cost = up_temprow; --執行返回結果 --閥門id,閥門圖形要素,閥門類型(上游/下游) --return query --select v_uptap_gid as res_uptap_gid,v_uptap_geom as res_uptap_geom ,up_temprow.source as res_source; --raise notice '%' , 'res_tap_pipe---'||cast(res_tap_pipe as text); IF (res_tap_pipe is not null) THEN --SELECT array_append(res_tap_pipe,ARRAY[v_uptap_gid,up_temprow.source]) into res_tap_pipe; --select cast(res_tap_pipe as text); select res_tap_pipe || ARRAY[v_uptap_gid||','||cast(v_uptap_geom as text)||','||up_temprow.source] into res_tap_pipe; ELSE select ARRAY[v_uptap_gid||','||cast(v_uptap_geom as text)||','||up_temprow.source] into res_tap_pipe; END IF; END IF; --return next; END LOOP; END LOOP; --raise notice '%' , v_cost; raise notice '%' , 'res_tap_pipe---'||cast(res_tap_pipe as text); --return query select * from v_cost; raise notice '%' , 'v_cost---'||cast(v_cost as text); --查找上游閥門 FOREACH m_cost IN ARRAY v_cost LOOP SELECT count(*) FROM pgr_dijkstraCost('select gid as id, source, target, length as cost, reverse_cost from zy',m_cost, ARRAY[v_startSource,v_startTarget], true) where agg_cost >= 9999999 into m_cost_value; raise notice '%' , 'm_cost_value---'||cast(m_cost_value as text); --若是沒有消耗大於9999999的(閾值),則認爲是上游閥門 IF(m_cost_value = 0) THEN --判斷上游閥門間是否有上下游關係 SELECT array_append(v_up_cost,m_cost) into v_up_cost; END IF; --IF(m_cost_value = array_length(v_cost,1)/2 - 1) THEN ----return query ---- select * from v_taps where source = m_cost; ----raise notice '%' , 'res_tap_pipe---'||cast(unnest(res_tap_pipe) as text); --FOREACH m_tap_pipe IN ARRAY res_tap_pipe --LOOP --raise notice '%' , 'm_cost---'||cast(m_cost as text) ; --IF (split_part(m_tap_pipe, ',', 3)::integer = m_cost) THEN ----閥門id,閥門圖形要素,閥門類型(上游/下游) --return query --select split_part(m_tap_pipe, ',', 1)::integer as res_uptap_gid,split_part(m_tap_pipe, ',', 2)::geometry as res_uptap_geom ,split_part(m_tap_pipe, ',', 3)::integer as res_source; --END IF; --idx_tap_pipe = idx_tap_pipe+1; --END LOOP; --END IF; END LOOP; raise notice '%' , '上游閥門---'||cast(v_up_cost as text); --循環遍歷找主閥門 FOREACH m_up_cost IN ARRAY v_up_cost LOOP SELECT count(*) FROM pgr_dijkstraCost('select gid as id, source, target, length as cost, reverse_cost from zy',m_up_cost, v_up_cost, true) where agg_cost >= 9999999 into m_cost_value; IF(m_cost_value = 0) THEN SELECT array_append(res_main_pipe,m_up_cost) into res_main_pipe; END IF; END LOOP; raise notice '%' , 'res_main_pipe---'||cast(res_main_pipe as text); IF(res_main_pipe IS NULL OR array_length(res_main_pipe,1)=0) THEN res_main_pipe = v_up_cost; END IF; FOREACH m_main_pipe IN ARRAY res_main_pipe LOOP FOREACH m_tap_pipe IN ARRAY res_tap_pipe LOOP raise notice '%' , 'm_cost---'||cast(m_cost as text) ; IF (split_part(m_tap_pipe, ',', 3)::integer = m_main_pipe) THEN --閥門id,閥門圖形要素,閥門類型(上游/下游) return query select split_part(m_tap_pipe, ',', 1)::integer as res_uptap_gid,split_part(m_tap_pipe, ',', 2)::geometry as res_uptap_geom ,split_part(m_tap_pipe, ',', 3)::integer as res_source; END IF; END LOOP; END LOOP;
END IF;
--查找總閥門 --FOR temprow IN -- select * from v_cost --LOOP -- SELECT count(*) FROM pgr_dijkstraCost('select gid as id, source, target, length as cost, reverse_cost from zy',m_cost, v_cost, true) where agg_cost <9999999 into m_cost_value; -- if(m_cost_value == ) --END LOOP;
end; $BODY$ LANGUAGE plpgsql VOLATILE STRICT COST 100 ROWS 1000; ALTER FUNCTION test_getpoint7(character varying, double precision, double precision) OWNER TO postgres;