【问题标题】:Python kdtree find "n" nearest neighboring groups (of coordinates)Python kdtree 找到“n”个最近的相邻组(坐标)
【发布时间】:2019-02-01 14:02:40
【问题描述】:

目标:给定一个坐标 X,为坐标 X 找到“n”个最近的线多边形,而不仅仅是“n”个最近的点。示例:https://i.imgur.com/qyxV2MF.png


我有一组空间线多边形,可以有超过 2 个坐标。它们的坐标存储在 (scipy)KDtree 中以启用 NN 搜索。

首先,我会查询“i”个最近的坐标,然后查找对应的线-多边形->“i”坐标不一定会产生“i”线。

为了实现“n”最近的行,我需要增加“i”。我的问题是“i”可能是不可预测的,因为每个线多边形之间的坐标数都不同。例如,一个线多边形可以用 2 个坐标表示,但另一个可以用 10 个坐标表示。大多数时候,我只需要距离 X 点最近的 2 个相邻线多边形。

在示例图像中,我需要 A 行和 B 行作为结果。即使 "i" = 3,也只会找到线 A,因为 A1、A2、A3 是 X 的最近邻居。


问题:有没有办法将一个形状的坐标组合在一起,然后进行NN搜索以获得“n”个独特的形状? (除了暴力破解“i”以确保“n”个独特的形状)


当前的解决方法伪代码:

found = []
while True:
    if first_loop:
        result = look up N nearest coords
    else:
        result = look up Nth nearest coord

    look up shapes using result and append to found
    perform de-duplication of found

    if len(found) >= required:
         return found
    else:
         N = N+1 # to check the Nth neighbor next iteration

【问题讨论】:

  • 将您的组转换为“平均/中点”有意义吗?因此,您可以将问题转化为点 NN,匹配 k 个最近点,然后将这些匹配扩展为原始组。
  • 嗨 randomir,我也想过使用单个坐标来表示每个形状。但是,我的地理空间形状的大小也有所不同,因此对最近邻居使用质心可能不会给出期望的结果(每个查询我最多只需要 4 个)。想象一个星形道路网络,我在中心,有 5 条道路(形状)分支出来。从技术上讲,我和5条路之间的距离是一样的。但如果我们使用质心作为参考,道路长度就会很重要。

标签: python algorithm data-structures nearest-neighbor kdtree


【解决方案1】:

我看到了两种有效的方法:

  1. 索引完整的“线多边形”:为此,您可以通过最小边界矩形来限制每个线多边形。然后使用适当的索引结构(如R-Tree)索引所有矩形。您将在最低级别使用线多边形而不是点,因此您必须针对这种情况调整距离。
  2. 使用Distance Browsing:这里的想法是将其线多边形的ID附加到每个点,并在索引结构(例如,KD-Tree)中索引这些点。然后,您使用距离浏览连续检索到您的查询的下一个最近点。您继续此操作,直到找到 n 个不同线多边形的点。

【讨论】:

  • 嗨@SaiBot,谢谢你的回答:| 1.我知道rtree可以用来存储形状的空间索引(边界矩形),可以快速找到可能的交叉点。您打算增加这个边界矩形的大小,以便它们以后可以与点 X 相交?我可以考虑用边界点 X 代替。 | 2. 感谢参考。虽然我理解你的解释,但它看起来很复杂。我正在寻找一个允许此附件的库。否则,需要手动实施,类似于下面 Sandipan Dey 的回答。
  • 1.您不仅可以找到与 R-Tree 的交叉点,还可以找到最近的邻居。您不必增加矩形的大小! 2.论文看起来很复杂,但想法很简单:您必须构建一个最小堆,其中点和矩形(例如,KD-Tree节点)以与查询X的最小距离存储。然后插入根节点你的索引。每当您从堆中删除条目时,您都会重新插入子项。当您检索一个点时,您将获得下一个最近的邻居。
  • 有趣!我有点时间紧迫,不得不接受当前的工作,但肯定会尝试你的建议。谢谢! :)
【解决方案2】:

如果我正确理解了您的问题,那就是拥有正确的数据结构的问题。

让我们有以下数据结构, 1. 从线多边形到点的字典 2.另一个从点到线多边形的字典(或等效的来自 bidict 的单个双向映射而不是几个字典) 3.一个布尔数组visited,大小等于点数

现在下面的算法应该可以解决你的问题(可以用上面的数据结构高效地实现):

  1. 对于所有点,将访问数组初始化为 False。

  2. 首先从 kd-tree 中找到离查询点最近的点,将匹配点和匹配点所属的相应多边形中的所有点标记为已访问,并将该特定多边形 (id) 返回为最近的多边形(如果有多个这样的多边形,则全部返回)。

  3. 重复步骤 2,直到返回 n 个这样的(不同的)多边形。考虑从 kd-tree 返回的新点与查询点匹配,如果它尚未访问(如果 kd-tree 返回的匹配点已被访问,则丢弃它并查询下一个最近匹配的点)。访问一个点后,将该点和相应多边形中的所有点标记为已访问并返回该多边形。

【讨论】:

  • 嗨@Sandipan,是的,你是对的,这更多的是算法和数据结构问题。在我当前的实现中,我确实有 #1 和 #2。我试图避免 #3 布尔数组,因为那是蛮力。我将在我的问题中详细介绍我的工作(与您的工作非常相似)。谢谢! :)
猜你喜欢
  • 2016-04-24
  • 1970-01-01
  • 1970-01-01
  • 2018-06-16
  • 2018-02-06
  • 2020-06-23
  • 2015-02-24
  • 2018-06-27
  • 1970-01-01
相关资源
最近更新 更多