ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

python – 在地图中查找附近的平行街道对的高效算法

2019-05-28 08:44:45  阅读:183  来源: 互联网

标签:python algorithm openstreetmap


我正在研究一个处理来自Openstreetmap的地图数据的Python程序,我需要能够识别彼此接近和平行的街道(路)对.现在,我使用的基本算法是非常低效的:

>将所有街道(街道对象)放入一个大型列表中
>使用嵌套for循环查找列表中每条可能的两条街道;对于每对,在两条街道周围绘制一个矩形,并计算每条街道的朝向角度.
>如果矩形重叠,则重叠区域足够大,并且角度相似,该对中的两条街道被认为是平行的并且彼此靠近.

这适用于小地图,但是对于大地图,最大的问题显然是会有大量的对迭代,因为一个城市可能有数千条街道.我希望能够在大面积(如城市)上运行程序,而不必将区域分成更小的部分.

我想到的一个想法是按纬度或经度对街道列表进行排序,并且仅比较列表中彼此相距50个位置的街道对.它可能会更有效但它似乎仍然不是很优雅;有没有更好的方法?

每个Street都由Node对象组成,我可以轻松地检索Node对象和每个Node的纬度/经度位置.我也可以轻松找回街道所朝向的角度.

解决方法:

我认为首先要做的是按角度对所有街道进行排序,从而使所有平行的街道彼此靠近.

然后,假设您可以准确识别角度,并且需要具有完全相同角度的街道对. (这不是一个真实的情况,因为浮点精度和由于所需的街道可能在数据中不完全平行,但让我们暂时忘记这一点.)

然后,所有排序的街道可以分成相同方向的组.在每个这样的组内存在如下定义的自然顺序.考虑垂直于具有相同方向的所有街道的另一条线.对于任何这样的街道,考虑与该垂直线的交叉点,并通过该交叉点对所有这些街道进行排序(我假设所有街道都是无限长的).

这种排序可以在没有任何交叉点的情况下轻松完成,您只需计算每条街道与原点(或任何其他固定点)到该街道线的距离,并按此距离对街道进行排序. (如果您有一条由标准直线方程Ax By C = 0定义的街道,那么这个距离原点的距离是C / sqrt(A * A B * B).)

现在,您按照此排序顺序将所有需要的并行关闭街道彼此非常接近.如果所有的街道都是无限长的,那么这些最接近的对将总是一个接一个地走;街道数量有限,两者之间可能还有其他街道,但我认为在任何真实数据中都会有很少的街道.因此,你可以采取一些距离差异的阈值,并检查其中的所有对.

现在让我们记住,角度没有精确定义.我可以建议以下方法.维护街道的二叉搜索树(类似于C的std :: map),搜索关键字是从原点到街道线的距离.按顺序沿着街道行进,因为它们按角度排序.在树中,我们将保持所有街道的角度相差不到一些阈值.因此,在树的每个街道的每个时间,树中的邻居将具有相差小于阈值的两个角度,并且距离原点的距离相差小于某个阈值.因此,对于每条街道,请执行以下操作:

>将此街道添加到树中
>对于树中的所有街道,但其角度与当前街道的角度差异太大,请从树中移除这些街道
>现在处理添加的街道:查看树中具有搜索关键字(距离原点的距离)在所需阈值内的所有街道,并检查该对(添加街道,另一条街道).

第一个点是O(log N),第二个点是O(log N)每个删除的街道如果你只是让另一个指针沿着排序的角度数组运行指向要删除的街道,第三个点是O(log N)每个邻居街道考虑.

一个非常粗略的伪代码:

sort lines by angle
r = 0 // the street to be deleted from the tree
for l=0..n-1
    tree.add(street[l])
    while street[r].angle<streel[l].angle-angle_threshold
        tree.remove(street[r])
    other_street=tree.prev(street[l])
    while other_street.dist>street[l].dist-dist_threshold
        process(street[l], other_street)
        other_street = tree.prev(other_street)
    other_street=tree.next(street[l])
    while other_street.dist<street[l].dist+dist_threshold
        process(street[l], other_street)
        other_street = tree.next(other_street)

这里tree.prev找到树中的前一条街道,即最大距离小于给定街道距离的街道,tree.next类似地找到下一条街道.两个操作都可以在O(log N)中完成.

这不会“循环”数组,即不考虑一对位于排序数组末端而另一端位于最开始的街道,但这很容易修复.

标签:python,algorithm,openstreetmap
来源: https://codeday.me/bug/20190528/1169941.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有