确定给定折线与一组现有折线的近似重叠

时间:2014-02-15 17:55:39

标签: algorithm google-maps postgis computational-geometry polyline

我有一组折线(编号为千分之几,每条折线有大约200-300个顶点)。这些代表地图上的路线(如果有帮助,则全部来自Google Maps API)。顶点是纬度/经度坐标。

我现在给出了一个查询折线,我必须找到查询折线与任何现有折线的“重叠”。因此,结果本身将是折线,按最大到最小重叠的顺序排序。我只需要前100个结果左右。另一个问题是重叠不一定是精确的,但可以是近似的(即,被视为重叠的线段的部分不需要位于另一个上,而只需要彼此“接近”)。

为了给出具体的表示,在下图的左侧部分,蓝色折线(折线A)是数据库中的折线,红色折线(折线B)是查询折线。该算法应确定以粗黑标记的折线,如右图所示。

Polyline overlap problem description

我目前倾向于使用空间数据库(正在考虑的选项是PostgreSQL + PostGIS),但我不确定延迟是否可以接受 - 查询需要立即返回结果。我的计算几何结果确实很弱,但我想知道:是否有任何现有的算法或方法可能对解决这一特定问题有用?

非常感谢提前!

3 个答案:

答案 0 :(得分:3)

快速近似查询,你不需要找到所有匹配的气味,如http://en.wikipedia.org/wiki/Locality-sensitive_hashing - 我怀疑你会得到大量的点击。前一段时间我对http://www.cs.ubc.ca/~lowe/papers/09muja.pdf很感兴趣 - 我不知道它是否在实践中有效,但重新发现该论文的搜索在http://www.cs.ubc.ca/research/flann/找到了一个库。直接LSH上的维基百科页面也指向底部的至少一个实现。 LSH的优点是可以使用关系数据库或dbm文件整齐地转换为数据库查找。

答案 1 :(得分:2)

鉴于问题规模很大,我建议您从网格化方法开始。我的意思是在地图顶部覆盖一个正方形网格,并且对于每个图块(让我们称之为像素)保留一条穿过它的折线列表。在某种程度上,这相当于使用Bresenham算法或变体执行地图的光栅扫描转换。

同样,您可以绘制查询折线并收集与前者共享一个或多个像素的所有折线。您可以保留公共像素的计数以获得重叠长度的第一个估计值。建议绘制“粗”线以吸收由于离散化导致的不准确性。

在第一次筛选过程之后,要考虑的折线数量会非常小,因此任何蛮力方法都可用于重叠评估。

一个关键问题是网格分辨率。太粗糙会导致候选人拒绝效率低下。太精细会以不可接受的方式增加预处理时间/空间。

假设您的网格大小为W x H像素,则需要W x H链接列表指针和N x L指针(对于平均长度为L的N条折线,以像素为单位 - 不在顶点计数中)。第一项增长为分辨率的平方,而第二项只是线性增长。预处理时间与此数据结构的大小呈线性关系(W x H用于初始化列表,N x L用于Bresenham线图)。

查询的成本大致为L'x K,其中L'是查询折线的长度,K是找到的重叠折线的数量(如果K>> 1,则使用有效的字典结构进行簿记K候选人)。这与分辨率成正比。

PS:如果选择的分辨率是这样的,你可以假设每个像素不超过一条折线(这是一个近似值),那么算法简化为:绘制整个地图,每条折线采用不同的颜色;然后绘制查询折线并记下你交叉的颜色。这正是你勾勒出来的!

答案 2 :(得分:1)

首先只考虑线条的边界框 - 因此(x1,y1)->(x2,y2)中的一条线变为矩形(x1,y1,x2,y2)。查找一个边界框和其他边界框之间的重叠可以使用二维interval treesegment tree在O(log n)时间内完成。然后,您可以迭代这些潜在的匹配项以检查线条是否真正相交。给定具有较少重叠边界框的数据集的所有线的总时间复杂度大致为O(n log n)。

有一个stackoverflow帖子,其中详细描述了如何test if two lines intersect