如何使用PostGIS计算连接所有点的最小网络?


13

我有一组postgis脚本,它们生成两个表-一个是一组点,第二个是围绕它们的道路。所有数据都在同一投影中,并且两个输出都存储在带有postgis 2.1的postgres 9.2表中

道路网的注浆拓扑已创建,点表中的列包含最近的路段。

然后,我想生成道路网的一个子集,该子集代表使用最小生成树之类的东西连接所有点的最小网络。道路网络是无方向性的,成本只是路线长度。

我可以使用v.net系列模块在QGIS / Grass中执行此操作,但理想情况下,我也希望在SQL中保留最后一步。

我已经看过新的apspWarshall postgis函数,但是对于如何鼓励它将精力集中在连接点而不是整个网络上,我感到困惑。

这是我编写的简短脚本,试图创建一个框架来解决此问题,但我看不到在哪里可能集中功能从边缘的子集开始。

SELECT seq, id1 AS node, id2 AS edge, cost, the_geom
FROM   pgr_apspWarshall('SELECT gid AS id, 
                                source, 
                                target, 
                                st_length(the_geom) AS cost 
                         FROM   road_network
                        ',
                        false, false
                       ) AS tree
JOIN   road_network As roads
ON     tree.id2 = roads.gid

在单路径最短路径问题中,该功能要求起点和终点,但显然不是在所有问题上都要求。同样在草丛中,v.net.spanningtree和v.net.steiner期望将一组点和线作为组合网络使用。

有没有人对如何在PostGIS中做到这一点提出建议?


我不确定我是否理解问题,但是 docs.pgrouting.org/2.0/en/src/tsp/doc/index.html#pgr-tsp旅行销售人员算法对您有帮助吗?
simplexio 2014年

1
谢谢。我真的不担心。旅行推销员以线性方式假设从a到b到c等等的旅程。我想要的是将每个点有效地链接在一起的最小网络,这样任何点都可以在没有任何多余路径迷失的情况下开始到其他任何点的旅程。在其他平台上,通常使用最小生成树功能Steiner Tree(en.wikipedia.org/wiki/Steiner_tree_problem)或类似功能来完成。如果您愿意,TSP非常适合物流公司,但是我想计划他们要使用的道路。
阿德里安

Answers:


2

该答案尚未完成或未通过测试,但请尝试以下操作:

根据问题/ 39210

with index_query as (
SELECT
        ,ST_Distance(i.geom, i.b_geom) AS dist
        ,ST_MakeLine(i.geom, i.b_geom) as geom
FROM(
SELECT
        ,a.geom
        ,b.geom AS b_geom
        ,rank() OVER (PARTITION BY a.id ORDER BY ST_Distance(a.centroid_geom, b.the_geom)) AS pos
FROM points a, points b 
WHERE a.id <> b.id) i
WHERE pos = 1
) select ST_Union(geom) from index_query;

我认为这不是很有效。


非常感谢您-谢谢。这给了我一些我从未想到过的新视角。此代码将从点表中找到最近的未连接邻居。我所增加的复杂性是,在我的情况下,这些点是沿着线串网络连接的,但是我想知道是否可以用pgRouting道路距离替换ST_Distance查询,尽管它会比未路由的点查询慢得多。
阿德里安

2

@Adrian,我真的不了解灌浆的结果,但是文档非常详细。我的答案基于一个两步函数,该函数在SQL中将是非常无用的,但是[可能]会产生结果。此[未测试]解决方案不会优化哪个是最佳起点,但是会将整个路线网络缩小到仅连接所有站点的边缘,然后有效地路由到所有站点。

第1步(连接所有站点的道路网络子集的子选择)这使用多目标(K Dijkstr路径)路由功能返回一组路径(当成本<> -1时)确实连接了所有停止。

SELECT id1 as path, st_astext(st_linemerge(st_union(b.the_geom))) as the_geom
FROM pgr_kdijkstraPath(
SELECT id, source, target, cost FROM edge_table’,
min(all_your_stop_ids), [array_of_all_your_stop_ids], false, false
) a,
edge_table b
WHERE a.id3=b.id
GROUP by id1
ORDER by id1

我这里的问题是从停止表组装数组的语法,因为在问题中并未真正描述。但是,我们假设SQL语法可以汇编该数组,并且最小id停止应该是到其余目标停止的所有K条路径的起点。

第2步(根据连接所有站点的上述子集道路网络路径,最终选择最小路径)这实际上是您开始的工作,但是我建议您将道路网络与id1(路径)的初始结果等价加入这样在最终的“实战”路线中仅使用道路的一部分

SELECT seq, id1 AS node, id2 AS edge, cost, the_geom
FROM   pgr_apspWarshall('SELECT R.gid AS id, 
                                R.source, 
                                R.target, 
                                st_length(R.the_geom) AS cost 
             FROM   road_network AS R JOIN
                   (SELECT id1 as path
                     FROM pgr_kdijkstraPath(
                            ’SELECT id, source, target, cost FROM edge_table’,
                            min(all_your_stop_ids), 
                            [array_of_all_your_stop_ids], false, false
                           ) a,
                     edge_table b
                    WHERE a.id3=b.id
                    GROUP by id1
                    ORDER by id1
                        ',
                        false, false
                  ) AS  Just_K_Paths
         on R.id1 = just_K_paths.id1',       /* this join reduces R down to K paths */
         false, false
        ) AS tree
  JOIN   road_network As roads
  ON     tree.id2 = roads.gid

因此,总而言之...内部的k_dijkstra_path路由查询将整个道路网络减少到仅连接所有站点的路径,然后外部的fField_Warshal路由仅使用那些边缘ID来解决路径优化查询....也许。


谢谢-这对我很有帮助,也是我的第一个新领导。我正在看。我只是试图找出如何生成最小停止ID和数组。我有一张必需ID的表,但是“ SELECT min(id)FROM node_table”和“ SELECT ARRAY [id] FROM node_table”在插入您的代码时会产生语法错误,但会作为独立代码工作(我的理解很差,当然)
Adrian
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.