使用PostGIS优化最近邻计算


13

我正在使用PostGIS计算多边形的最近邻居。我要计算的是从每个多边形到最近的多边形的最小距离。

到目前为止,我在这里得到了Mike Toews的答案的帮助(我引用了一个小的更改):

SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_Distance(a.the_geom, b.the_geom) AS distance_between_a_and_b
FROM 
  public."TestArea" AS a, public."TestArea" AS b
WHERE
  a.hgt !=  b.hgt AND ST_Distance(a.the_geom, b.the_geom) < 400

然后,我计算出最小值:

SELECT a_hgt, MIN(distance_between_a_and_b)
FROM public."lon_TestArea"
GROUP BY a_hgt

但是,我的挑战是为大量的多边形(1,000,000)计算此值。当上述计算将每个多边形与其他每个多边形进行比较时,我想知道如何改进计算,从而不必执行10 ^ 12的计算。

我曾经想过要缓冲每个多边形,然后计算该多边形的缓冲区中所有值的最近邻居,并记录下最小值。我不确定这是最好的方法,还是不确定我应该使用的PostGIS功能。


编辑:使用尼克拉斯的建议之一,我正在尝试ST_Dwithin()

CREATE TABLE mytable_withinRange AS SELECT 
  a.hgt AS a_hgt,
  b.hgt AS b_hgt,
  ST_DWithin(a.the_geom, b.the_geom, 400)
FROM 
  public."lon_TestArea" AS a, public."lon_TestArea" AS b

在此处输入图片说明

这将返回每个多边形ID的表格,以及该表格是否在一定距离内。是否可以IF/ELSE使用SQL 构造类型语句?(我阅读了有关使用CASE条件的信息)还是应该尝试将生成的表连接到原始表,然后使用ST_Distance重新运行查询?


看一下我答案中的波士顿gis链接中的第二个示例。您应该在查询的where部分中使用st_dwithin。
NicklasAvén2011年

Answers:


7

BostonGIS页面上有一个很大的“最近的邻居”部分


编辑:

怎么样

CREATE TABLE mytable_withinRange AS SELECT 
 a.hgt AS a_hgt,
 b.hgt AS b_hgt
FROM 
 public."lon_TestArea" AS a, public."lon_TestArea" AS b
WHERE 
 ST_DWithin(a.the_geom, b.the_geom, 400)

关于CASE声明

SELECT a,
   CASE WHEN a=1 THEN 'one'
        WHEN a=2 THEN 'two'
        ELSE 'other'
   END
FROM test;

您是否知道这条线WHERE ST_DWithin(a.the_geom, b.the_geom, 400)会阻止距离大于400要计算或记录的距离?另外,案例陈述可用于数值计算吗?例如:CASE WHEN ST_DWithin(a.the_geom, b.the_geom, 400) == TRUE THEN ST_DWithin(a.the_geom, b.the_geom)
djq 2011年

1
@celenius如果距离大于400 m,则所选零件中的任何内容都不会被计算。我不明白为什么你要把箱子混在一起。
NicklasAvén2011年

@尼克拉斯好-我明白。我认为这可能意味着只存储了少于400的距离。这比我要容易得多。谢谢!
djq 2011年

3

哈罗

有一些事情确实在考虑使事情进展得更快,而某些事情将来可能会发生。

首先,您提到要考虑使用缓冲区来查找某个最小范围内的多边形,以避免计算所有组合。

正如Boston gis在另一个链接中讨论的那样,在PostGIS中执行此操作的正确方法是使用ST_Dwithin。ST_Dwithin使用索引在一定范围内查找邻居。

当然,这仅取决于数据集是否足以对所有多边形使用st_DWithin的固定值,或者是否需要执行诸如underdark和wildintellect讨论的操作。

第二件事是在这里使用PostGIS 1.5+。这是因为如果边界框不相交,则多边形到多边形的计算从1.5开始要快得多。您可以在此处了解更多信息

第三件事是未来。

在PostgreSQL 9.1中,会有一个叫做knn-gist的东西。那是一个索引,它不仅可以回答是或否,还可以直接从索引中返回排序的结果。您可以在这里阅读有关内容。

但是,在knn gist可以为此类事情提供帮助之前,在PostGIS方面仍然有很多工作要做。这里有一张票

问候

尼克拉斯


感谢您的建议,尼克拉斯;因为我发现启动和运行pgAdmin / PostGIS非常棘手,我认为目前我不会使用1.5。似乎ST_Dwithin()是解决此问题的一种方法。
djq 2011年

2
安装1.5不会影响postgresql和pgadmin之间的关系。您可以在数据库服务器中拥有多个版本的postgis,然后在数据库中加载其中之一。因此您可以在同一台数据库服务器上拥有一个1.4和一个1.5数据库。
NicklasAvén2011年

1

以下与内森·克尔(Nathan Kerr)的大师作品有关的页面对这个直接问题提供了一些很好的见解。我的同事在这里这里尝试了Bostongis方法,但是在使其正常工作方面存在一些问题。

另一个类似于缓冲区的思考方法是做一个扩展/收缩矩形。基本上,通过1做一个边界框(它是原始多边形的bbox的直线+ x单位)相交,您认为将捕获至少一个相交。对于相交的数据,执行子查询,以测试那些匹配项中最接近的匹配项。对于失败的数据,展开边界框并重复。

显然这是一个递归编程问题,在Python中使用Shapely可能比在postgis中直接完成100%更好。

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.