基于pgrouting的任意两点间的最短路径查询函数

简介:

    前面文章介绍了如何利用postgresql创建空间数据库,建立空间索引和进行路径规划。但是在真实的场景中用户进行路径规划的时候都是基于经纬度数据进行路径规划的,因为用户根本不会知道道路上节点的ID。因此文本讲述如何查询任意两点间的最短路径。

    一、定义函数名及函数参数

        函数名定义为: pgr_fromAtoB

        参数设置分别为:

                 输入为数据库表名,起点和终点的经纬度坐标

                 输出为:路段序号,gid号,道路名,消耗及道路集合体。

                IN tbl varchar, --数据库表名
                IN x1 double precision, --起点x坐标
                IN y1 double precision, --起点y坐标
                IN x2 double precision, --终点x坐标
                IN y2 double precision, --终点y坐标
                OUT seq integer, --
                OUT gid integer,
                OUT name text,
                OUT heading double precision,
                OUT cost double precision,
                OUT geom geometry

    二、计算距离起点和终点距离最近的道路节点,

                 可以使用的函数为

             SELECT id::integer FROM minidata_vertices_pgr
            ORDER BY the_geom <-> ST_GeometryFromText(''POINT('
            || x1 || ' ' || y1 || ')'',900913) LIMIT 1

    三、然后根据检索到的节点再调用pgrouting的最短路径查询函数进行计算。

            可以使用的函数为:

             SELECT gid, geom, name, cost, source, target,
                ST_Reverse(geom) AS flip_geom FROM ' ||
                        'pgr_bdAstar(''SELECT gid as id, source::int, target::int, '
                                        || 'length::float AS cost,x1,y1,x2,y2 FROM '
                                        || quote_ident(tbl) || ''', '
                                        || source || ', ' || target
                                        || ' ,false, false), '
                                || quote_ident(tbl) || ' WHERE id2 = gid ORDER BY seq

    四、整合上面几个子过程,得到的最终查询sql函数如下:

--
--DROP FUNCTION pgr_fromAtoB(varchar, double precision, double precision, 
--                           double precision, double precision);

CREATE OR REPLACE FUNCTION pgr_fromAtoB(
                IN tbl varchar,
                IN x1 double precision,
                IN y1 double precision,
                IN x2 double precision,
                IN y2 double precision,
                OUT seq integer,
                OUT gid integer,
                OUT name text,
                OUT heading double precision,
                OUT cost double precision,
                OUT geom geometry
        )
        RETURNS SETOF record AS
$BODY$
DECLARE
        sql     text;
        rec     record;
        source	integer;
        target	integer;
        point	integer;
        
BEGIN
	-- 查询距离出发点最近的道路节点
	EXECUTE 'SELECT id::integer FROM minidata_vertices_pgr 
			ORDER BY the_geom <-> ST_GeometryFromText(''POINT(' 
			|| x1 || ' ' || y1 || ')'',900913) LIMIT 1' INTO rec;
	source := rec.id;
	
	-- 查询距离目的地最近的道路节点
	EXECUTE 'SELECT id::integer FROM minidata_vertices_pgr 
			ORDER BY the_geom <-> ST_GeometryFromText(''POINT(' 
			|| x2 || ' ' || y2 || ')'',900913) LIMIT 1' INTO rec;
	target := rec.id;

	-- 最短路径查询 
        seq := 0;
        sql := 'SELECT gid, geom, name, cost, source, target, 
				ST_Reverse(geom) AS flip_geom FROM ' ||
                        'pgr_bdAstar(''SELECT gid as id, source::int, target::int, '
                                        || 'length::float AS cost,x1,y1,x2,y2 FROM '
                                        || quote_ident(tbl) || ''', '
                                        || source || ', ' || target 
                                        || ' ,false, false), '
                                || quote_ident(tbl) || ' WHERE id2 = gid ORDER BY seq';


	-- Remember start point
        point := source;

        FOR rec IN EXECUTE sql
        LOOP
		-- Flip geometry (if required)
		IF ( point != rec.source ) THEN
			rec.geom := rec.flip_geom;
			point := rec.source;
		ELSE
			point := rec.target;
		END IF;

		-- Calculate heading (simplified)
		EXECUTE 'SELECT degrees( ST_Azimuth( 
				ST_StartPoint(''' || rec.geom::text || '''),
				ST_EndPoint(''' || rec.geom::text || ''') ) )' 
			INTO heading;

		-- Return record
                seq     := seq + 1;
                gid     := rec.gid;
                name    := rec.name;
                cost    := rec.cost;
                geom    := rec.geom;
                RETURN NEXT;
        END LOOP;
        RETURN;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE STRICT;


相关文章
|
2月前
|
存储 编解码 算法
【信道编码】2 卷积码、状态转移图、状态转移表、网格表示和码字路径
【信道编码】2 卷积码、状态转移图、状态转移表、网格表示和码字路径
93 1
|
2月前
|
算法 测试技术 C#
【图论 状态压缩 枚举】2959. 关闭分部的可行集合数目
【图论 状态压缩 枚举】2959. 关闭分部的可行集合数目
|
2月前
GEE——土地利用分类种两个矢量集合中不同列进行相减的方式(利用join进行连接处理)
GEE——土地利用分类种两个矢量集合中不同列进行相减的方式(利用join进行连接处理)
44 2
|
2月前
|
算法 JavaScript 测试技术
动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本
动态规划 多源路径 字典树 LeetCode2977:转换字符串的最小成本
|
11月前
|
算法 索引
算法训练Day36|435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间
算法训练Day36|435. 无重叠区间 ● 763.划分字母区间 ● 56. 合并区间
|
11月前
|
算法
算法训练Day27|39. 组合总和● 40.组合总和II● 131.分割回文串
算法训练Day27|39. 组合总和● 40.组合总和II● 131.分割回文串
|
SQL 移动开发 BI
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
怎样对数据组合重新排列并去重的问题、通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高【SQL开发实战技巧】这一系列博主当作复习旧知识来进行写作,毕竟SQL开发在数据分析场景非常重要且基础,面试也会经常问SQL开发和调优经验,相信当我写完这一系列文章,也能再有所收获,未来面对SQL面试也能游刃有余~。本篇文章主要介绍的两个方面,第一个方面曾经有好几个网友和同事问我,第二个问题真的是很多同行的通病,认为分析函数是万金油,一股脑用。
【SQL开发实战技巧】系列(二十三):数仓报表场景☞ 如何对数据排列组合去重以及通过如何找到包含最大值和最小值的记录这个问题再次用执行计划给你证明分析函数性能不一定高
【集合论】序关系 ( 偏序集元素之间的关系 | 可比 | 严格小于 | 覆盖 | 哈斯图 )
【集合论】序关系 ( 偏序集元素之间的关系 | 可比 | 严格小于 | 覆盖 | 哈斯图 )
357 0
【集合论】序关系 ( 偏序集元素之间的关系 | 可比 | 严格小于 | 覆盖 | 哈斯图 )
集合的查、并运算,即简化版运算方法,按秩归并,压缩路径
集合的查、并运算,即简化版运算方法,按秩归并,压缩路径
|
人工智能
LeetCode 1389. 按既定顺序创建目标数组
给你一个字符串 s,它由数字('0' - '9')和 '#' 组成。我们希望按下述规则将 s 映射为一些小写英文字符
67 0