說明:
遇到個需求:需要查詢事發點周圍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;