POSTGIS路径规划的简单配置(数据库配置)

欢迎关注我的博客For CR

docker安装pgrouting是最方便的方法没有之一

所以我们使用docker安装pgrouting

0:需有docker环境 没有的请自行百度

0.1:必须使用拥有amd64架构的宿主机(树莓派就只能gg)

1.安装docker镜像

1.1首先 打开浏览器搜索docker hub

image.png

在此处输入pgrouting后搜索

在已经安装了docker的任何环境中键入右侧代码

docker pull pgrouting/pgrouting

可以看到

image.png


我搜索的当前版本是基于 Postgres 13/PostGIS 3.1 的

所以必须保证负责部署传输的主机拥有 PostGIS 3.1

image.png

如果实在是有原来的版本 可以尝试一下方法:

  1. 删除原有postgis
  2. 点击docker hub中的tag并在其中找到相关版本

    image.png

2.启动镜像

根据docker中postgresql的相关操作文档
Docker Hub
我的启动命令为

 docker run --name=pgrouting -p 5432:5432 --restart=always -e POSTGRES_PASSWORD=yourpass -d pgrouting/pgrouting

由上得出我的启动密码为'yourpass'
使用任意数据库管理工具即可登录数据库

3.初始化数据

3.0 本章需要预先准备路网数据 如没有 请自行查找方法下载 此处不进行展示

3.1 将已经下载的路网数据导入arcgis中 进行要素转线

此处必须进行 否则会出现多线的道路 导致无法导入

3.2 将导出的数据放入数据库

3.2.1 登录数据库

image.png

image.png


当出现如图二中的

Connection succeeded. 

则证明连接成功
将要使用的数据拖入
需注意下图中的几个选项

image.png

4.处理数据

4.1.数据库新加字段并赋值

执行如下sql


-- 添加起点
ALTER TABLE public.road ADD COLUMN source integer;

--添加终点id

ALTER TABLE public.road ADD COLUMN target integer;

--添加道路权重值

ALTER TABLE public.road ADD COLUMN length double precision;

SELECT pgr_createTopology('public.road',0.0001, 'geom', 'gid');

-- 创建起点和终点编号的索引
CREATE INDEX source_idx ON road ("source");
CREATE INDEX target_idx ON road ("target");
-- 计算道路长度
UPDATE road SET length =st_length(geom);
-- 新建道路权重(用于后期经常修改)
ALTER TABLE road ADD COLUMN reverse_cost double precision;
-- 赋值道路权重
UPDATE road SET reverse_cost =length;

ALTER TABLE road ADD COLUMN x1 double precision;		--创建起点经度x1
ALTER TABLE road ADD COLUMN y1 double precision;		--创建起点纬度y1
ALTER TABLE road ADD COLUMN x2 double precision;		--创建起点经度x2
ALTER TABLE road ADD COLUMN y2 double precision;		--创建起点经度y2
            
UPDATE road SET x1 =ST_x(ST_PointN(geom, 1));	
UPDATE road SET y1 =ST_y(ST_PointN(geom, 1));	
UPDATE road SET x2 =ST_x(ST_PointN(geom, ST_NumPoints(geom)));	
UPDATE road SET y2 =ST_y(ST_PointN(geom, ST_NumPoints(geom)));	--给x1、y1、x2、y2赋值

4.2.添加存储过程

CREATE OR REPLACE FUNCTION public.pgr_fromctod(tbl character varying, startx double precision, starty double precision, endx double precision, endy double precision)
 RETURNS geometry
 LANGUAGE plpgsql
 STRICT
AS $function$  
 
declare 
 
    v_startLine geometry;--离起点最近的线 
 
    v_endLine geometry;--离终点最近的线 
 
     
 
    v_startTarget integer;--距离起点最近线的终点
 
    v_startSource integer;
 
    v_endSource integer;--距离终点最近线的起点
 
    v_endTarget integer;
 
 
 
    v_statpoint geometry;--在v_startLine上距离起点最近的点 
 
    v_endpoint geometry;--在v_endLine上距离终点最近的点 
 
     
 
    v_res geometry;--最短路径分析结果
 
    v_res_a geometry;
 
    v_res_b geometry;
 
    v_res_c geometry;
 
    v_res_d geometry; 
 
 
 
    v_perStart float;--v_statpoint在v_res上的百分比 
 
    v_perEnd float;--v_endpoint在v_res上的百分比 
 
 
 
    v_shPath_se geometry;--开始到结束
 
    v_shPath_es geometry;--结束到开始
 
    v_shPath geometry;--最终结果
 
    tempnode float;      
 
begin
 
    --查询离起点最近的线 
    --4326坐标系
    --找起点15米范围内的最近线
 
    execute 'select geom, source, 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_startSource ,v_startTarget; 
 
     
 
    --查询离终点最近的线 
    --找终点15米范围内的最近线
 
    execute 'select geom, source, target 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,v_endTarget; 
 
 
 
    --如果没找到最近的线,就返回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; 
 
   
 
   -- ST_Distance 
 
     
 
    --从开始的起点到结束的起点最短路径
 
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, cost FROM ' || tbl ||''',' 
 
    ||v_startSource|| ', ' ||'array['||v_endSource||'] , false, false 
    ) a, ' 
 
    ||tbl|| ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' into v_res ;
 
   
 
    --从开始的终点到结束的起点最短路径
 
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
 
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, 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_b ;
 
 
 
    --从开始的起点到结束的终点最短路径
 
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
 
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, cost FROM ' || tbl ||''',' 
 
    ||v_startSource || ', ' ||'array['||v_endTarget||'] , false, false 
    ) a, ' 
 
    || tbl || ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' into v_res_c ;
 
 
 
    --从开始的终点到结束的终点最短路径
 
    execute 'SELECT st_linemerge(st_union(b.geom)) ' ||
 
    'FROM pgr_kdijkstraPath( 
    ''SELECT gid as id, source, target, cost FROM ' || tbl ||''',' 
 
    ||v_startTarget || ', ' ||'array['||v_endTarget||'] , false, false 
    ) a, ' 
 
    || tbl || ' b 
    WHERE a.id3=b.gid   
    GROUP by id1   
    ORDER by id1' into v_res_d ;
 
 
 
    if(ST_Length(v_res) > ST_Length(v_res_b)) then
 
       v_res = v_res_b;
 
    end if;
 
   
 
    if(ST_Length(v_res) > ST_Length(v_res_c)) then
 
       v_res = v_res_c;
 
    end if;
 
   
 
    if(ST_Length(v_res) > ST_Length(v_res_d)) then
 
       v_res = v_res_d;
 
    end if;
 
             
 
 
 
    --如果找不到最短路径,就返回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; 
 
$function$
;

接下来便可以通过使用如下sql进行查询

select * from pgr_fromctod('road', startx, starty, endx, endy)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值