PostGIS 緩沖區分析(查詢距離范圍內要素)


說明:

遇到個需求:需要查詢事發點周圍100米內的人和車,這個通過PostGIS的ST_DWithin函數很容易實現。
但是在實現過程中,遇到了三個不同的問題,在此總結一下。

解決方案:

方案一:

這種方式適用於PostGIS庫,在庫里直接寫SQL實現,入參直接可以用PostGIS的geometry格式。

--調用方式(參數:表名,坐標系id,表主鍵ID,緩沖區半徑,中心點)
select * from enc_buffer_bygeom('fm',3857,'gid',100,'0101000020110F0000F2D24D3662CA6841480C02EB46545241');

函數如下:

-- FUNCTION: public.func_buffer_bygeom(character varying, integer, character varying, double precision, character varying)
-- DROP FUNCTION public.func_buffer_bygeom(character varying, integer, character varying, double precision, character varying);
CREATE OR REPLACE FUNCTION public.func_buffer_bygeom(
	tb character varying,
	qsrid integer,
	qid character varying,
	qbuffer double precision,
	qgeom character varying)
    RETURNS TABLE(v_gid integer, v_res geometry, v_dis double precision) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE STRICT 
    ROWS 1000
    
AS $BODY$  

declare  
    v_gid integer; --主鍵
    v_res geometry; --要素
    v_dis double precision; --與目標距離
begin 
    RETURN QUERY EXECUTE 
    'select '||qId||',geom, ST_Distance(geom,'''||qGeom||''') from ' ||tb|| ' where ST_DWithin(geom,'''||qGeom||''','||qBuffer||')' ; 

end;  

$BODY$;

ALTER FUNCTION public.func_buffer_bygeom(character varying, integer, character varying, double precision, character varying)
    OWNER TO postgres;
方案二:

這種方式適用於PostGIS庫里的查詢(有geom字段的),就可以直接用此函數查詢。
相較於方案一的話,他更適合發布到geoserver中供前端調用,因為前端獲取WKT格式較方便。

--調用方式(參數:表名,坐標系id,表主鍵ID,緩沖區半徑,中心點)
select * from func_buffer('layer_grid',3857,'id',10,'POINT(12988813.522 4798555.074)');

函數如下:

-- FUNCTION: public.func_buffer(character varying, integer, character varying, double precision, character varying)
-- DROP FUNCTION public.func_buffer(character varying, integer, character varying, double precision, character varying);
CREATE OR REPLACE FUNCTION public.func_buffer(
	tb character varying,
	qsrid integer,
	qid character varying,
	qbuffer double precision,
	qgeom character varying)
    RETURNS TABLE(v_gid integer, v_res geometry, v_dis double precision) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE STRICT 
    ROWS 1000
    
AS $BODY$  

declare  
    v_gid integer; --主鍵
    v_res geometry; --要素
    v_dis double precision; --與目標距離
begin 
    RETURN QUERY EXECUTE 
    'select '||qId||',geom, ST_Distance(geom,ST_Geometryfromtext('''||qGeom||''','||qSrid||')) from ' ||tb|| ' where ST_DWithin(geom,ST_Geometryfromtext('''||qGeom||''','||qSrid||'),'||qBuffer||')' ; 

end;  

$BODY$;

ALTER FUNCTION public.func_buffer(character varying, integer, character varying, double precision, character varying)
    OWNER TO postgres;

方案三:

這種方式適用於對外部表做緩沖區分析(外部表只有x和y字段,沒有geom字段)
這種比較常見於業務庫和GIS空間數據庫分開的情況下(我們是mysql+postgis),業務庫只有存Xy字段,並不支持postgis的geometry類型
所以操作前需要通過外表關聯,將mysql表關聯到postgis,接着根據mysql中xy字段,構造geom字段
外表關聯方法參見:https://www.cnblogs.com/giser-s/p/11208818.html

--調用方式(參數:表名,坐標系id,表主鍵ID,緩沖區半徑,中心點)
select * from func_buffer_fetable('layer_grid',3857,'id','lng','lat',10,'POINT(12988813.522 4798555.074)');

函數如下:

-- FUNCTION: public.func_buffer_fetable(character varying, integer, character varying, character varying, character varying, double precision, character varying)
-- DROP FUNCTION public.func_buffer_fetable(character varying, integer, character varying, character varying, character varying, double precision, character varying);
CREATE OR REPLACE FUNCTION public.func_buffer_fetable(
	tb character varying,
	qsrid integer,
	qid character varying,
	qxfield character varying,
	qyfield character varying,
	qbuffer double precision,
	qgeom character varying)
    RETURNS TABLE(v_gid integer, v_res geometry, v_dis double precision) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE STRICT 
    ROWS 1000
    
AS $BODY$  

declare  
    v_gid integer; --主鍵
    v_res geometry; --要素
    v_dis double precision; --與目標距離
	v_record record;
begin 
RETURN QUERY EXECUTE  
	'select '||qId||',
	ST_Geometryfromtext(''POINT( ''||'|| qxfield ||'||'' ''||'|| qyfield ||'||'')'','||qSrid||'),
	ST_Distance(ST_Geometryfromtext(''POINT( ''||'|| qxfield ||'||'' ''||'|| qyfield ||'||'')'','||qSrid||'),ST_Geometryfromtext('''||qGeom||''','||qSrid||')) 
	from ' ||tb|| 
	' where ST_DWithin(ST_Geometryfromtext(''POINT( ''||'|| qxfield ||'||'' ''||'|| qyfield ||'||'')'','||qSrid||'),ST_Geometryfromtext('''||qGeom||''','||qSrid||'),'||qBuffer||')';
end;  

$BODY$;

ALTER FUNCTION public.func_buffer_fetable(character varying, integer, character varying, character varying, character varying, double precision, character varying)
    OWNER TO postgres;
方案四:

這種方式提前將PostGIS庫中geometry格式轉成了WKT格式(geomtext字段),方便直接查詢。
測試產物,不是很推薦這么做。

--調用方式(參數:表名,坐標系id,表主鍵ID,緩沖區半徑,中心點)
select * from func_buffer_bytxt('layer_grid',3857,'id',10,'POINT(12988813.522 4798555.074)');

函數如下:

-- FUNCTION: public.func_buffer_bytxt(character varying, integer, character varying, double precision, character varying)
-- DROP FUNCTION public.func_buffer_bytxt(character varying, integer, character varying, double precision, character varying);
CREATE OR REPLACE FUNCTION public.func_buffer_bytxt(
	tb character varying,
	qsrid integer,
	qid character varying,
	qbuffer double precision,
	qgeom character varying)
    RETURNS TABLE(v_gid integer, v_res geometry, v_dis double precision) 
    LANGUAGE 'plpgsql'

    COST 100
    VOLATILE STRICT 
    ROWS 1000
    
AS $BODY$  

declare  
    v_gid integer; --主鍵
    v_res geometry; --要素
    v_dis double precision; --與目標距離
begin 
    RETURN QUERY EXECUTE 
    'select '||qId||',geom, ST_Distance(st_geomfromtext(geomtext,'||qSrid||'),ST_Geometryfromtext('''||qGeom||''','||qSrid||')) from ' ||tb|| ' where ST_DWithin(geom,ST_Geometryfromtext('''||qGeom||''','||qSrid||'),'||qBuffer||')' ; 

end;  

$BODY$;

ALTER FUNCTION public.func_buffer_bytxt(character varying, integer, character varying, double precision, character varying)
    OWNER TO postgres;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM