PostGIS 缓冲区分析(查询距离范围内要素)

23 篇文章 2 订阅


说明:
遇到个需求:需要查询事发点周围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;
 

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值