据我所知,OSM 中没有标准的 API 可以做到这一点(这确实是一个非常不常见的用例)。
我假设您将 enclose 定义为 代表当前位置的点在多边形的内部区域内。此外,我假设优化流程可能包括改变算法的整个概念。
首先,您需要定义矩形来获取数据。为此,您需要考虑查询太大的矩形会产生太多数据。据我所知,没有特定的 API 只能查询循环方式,即使有,查询太大的矩形也可能会被服务器拒绝,因为服务器负载会很大。
服务器端预计算/预过滤
因此我建议第一个优化:不要查询不适合您目的的 API,而是使用保存在 Android 设备上的离线数据库。 OsmAnd 和其他人离线保存一个国家的整个数据库,但在您的特定用例中,您只需要保存一个预先过滤的循环数据库。
据我所知,OSM 中只有一小部分方式是循环的。因此,我建议编写一个定期下载 OSM 转储的脚本,例如从Geofabrik,删除非循环方式(例如,您可以检查方式中的最后一个节点 ID 是否等于第一个节点 ID,但您需要检查它是否捕获了您定义为循环的任何方式)。您运行它的频率取决于您的用例。
这个优化解决了:
- 下载大量数据的问题
- 大请求API超载问题
- 无法请求大块数据的问题
如果这不适合您的用例,我建议在您的服务器上为此构建一个简单的 API。
将数据重新分块到适当的网格中
但是,您仍然需要过滤大量数据。为了部分解决这个问题,我建议第二个优化:重新分块你的数据。例如,如果您当前的位置在弗吉尼亚州,则无需过滤面积不超出德克萨斯州的环形路。因为按州等进行过滤会高度依赖国家和困难(CPU密集型),我建议选择一个网格,例如0.05 纬度/经度(我会选择等角投影,因为如果您已经有纬度/经度坐标,它很容易计算)。
然后,预处理该数据的脚本将为您要使用的区域中的任何矩形创建一个数据块(可能是一个文件,但我们对您的用例了解不足,无法讨论特定的数据结构) .当且仅当它在块区域内至少有一个节点时,才会在该块中包含循环方式。
然后您将只请求/过滤您当前所在位置的特定块。为您的应用程序选择适当的块大小(最好相当小,但这取决于许多因素!)。
这个优化解决了:
- 假设大多数圆形通道的边界矩形都非常小,您只需要过滤整个通道的一小部分
- IO 已最小化,尤其是如果您
迟滞启发式
如果上述优化不能充分减少您的计算时间,我建议第三个优化取决于您想要找到 多少 循环方式(如果您真的需要找到 全部,它根本没有帮助):使用滞后。保存您在上次计算期间所处的循环方式(假设新的当前位置靠近最后一个位置)并首先检查它们。如果您的位置没有太大变化,那么您很有可能在最初的几次光线投射中撞到您所在的位置。
利用不同循环方式之间的关系
另外,第四种优化是可能的:将有一些循环方式完全封闭在另一种循环方式中。您可以对您的程序进行编码,以便它知道该关系并首先检查内部循环方式。如果此检查成功,您现在自动认为当前位置也包含在外循环方式中。我认为计算信息(服务器端)可能会非常耗费 CPU,实现它也可能是一项艰巨的任务,因此我建议仅在无法避免的情况下使用此优化。
调整这些优化的参数应该足以显着减少计算所需的 CPU 时间。如果您对这些建议还有其他问题,请随时发表评论/询问。