经纬度坐标比较
Posted
技术标签:
【中文标题】经纬度坐标比较【英文标题】:Comparison of Lat, Long Coordinates 【发布时间】:2010-09-07 08:15:45 【问题描述】:我有一个超过 15000 个经纬度坐标的列表。给定任意 X,Y 坐标,找到列表中最近坐标的最快方法是什么?
【问题讨论】:
【参考方案1】:我为一个网站做过一次。 IE。在您的邮政编码 50 英里范围内找到经销商。我使用great circle calculation 找到了北 50 英里、东 50 英里、南 50 英里和西 50 英里的坐标。这给了我一个最小和最大纬度以及最小和最大长度。然后我做了一个数据库查询:
select *
from dealers
where latitude >= minlat
and latitude <= maxlat
and longitude >= minlong
and longitude <= maxlong
由于其中一些结果仍然在 50 多英里之外,所以我在那个小坐标列表上再次使用了great circle formula。然后我打印出列表以及与目标的距离。
当然,如果您想搜索国际日期变更线或两极附近的点,那么这是行不通的。但它非常适合在北美境内进行搜索!
【讨论】:
【参考方案2】:您将需要使用称为Voronoi diagram 的几何构造。这会将平面划分为多个区域,每个区域一个区域,其中包含最接近每个给定点的所有点。
用于创建 Voronoi 图和安排数据结构查找的精确算法的代码太大,无法放入这个小编辑框。 :)
@Linor:这基本上就是您在创建 Voronoi 图后要做的事情。但是,您可以选择与 Voronoi 图线非常匹配的分割线,而不是制作矩形网格(这样您将获得更少的穿过分割线的区域)。如果您沿着每个子图的最佳分割线递归地将 Voronoi 图分成两半,则可以对要查找的每个点进行树搜索。这需要一些前期工作,但可以节省以后的时间。每个查找将按 log N 的顺序进行,其中 N 是点数。 16 次比较比 15,000 次要好很多!
【讨论】:
【参考方案3】:您所描述的一般概念是nearest-neighbour search,并且有大量技术可以准确或近似地解决这些类型的查询。基本思想是使用空间分区技术将复杂度从每个查询的 O(n) 降低到(大约)每个查询的 O(log n)。
KD-Trees 和 KD-Trees 的变体似乎工作得很好,但四叉树也可以工作。这些搜索的质量取决于您的 15,000 个数据点集是否是静态的(您没有向参考集添加大量数据点)。 Mount 和 Arya 在 Approximate Nearest Neighbour 库上的工作既易于使用又易于理解,即使没有良好的数学基础。它还为您在查询的类型和容差方面提供了一些灵活性。
【讨论】:
我已经用 KD-Trees 解决了这个确切的问题。只要您乐于将树保存在 RAM 中,它就可以很好地工作。【参考方案4】:这取决于你想要做多少次,以及可用的资源 - 如果你只做一次测试,那么 O(log N) 技术很好。如果您在服务器上执行一千次,则构建位图查找表会更快,直接给出结果或作为第一阶段。 2GB 的位图可以将整个世界经纬度映射到 0.011 度像素(赤道 1.2 公里)处的 32 位值,并且应该适合内存。如果你只做一个国家,或者可以排除两极,你可以有一个更小的地图或更高的分辨率。对于 15,000 点,您可能有一个小得多的地图 - 我首先调整它的大小,作为进行经纬度到邮政编码搜索的第一步,这需要更高的分辨率。根据要求,您可以使用映射值直接指向结果,或指向候选者的短列表(这将允许较小的映射,但需要更多的后续处理 - 您不再处于 O(1) 查找区域)。
【讨论】:
【参考方案5】:您没有具体说明最快的含义。如果您想在不编写任何代码的情况下快速获得答案,我会试试gpsbabel radius filter。
【讨论】:
【参考方案6】:根据您的说明,我将使用几何数据结构,例如 KD-tree 或 R-tree。 mysql 有一个 SPATIAL 数据类型可以做到这一点。其他语言/框架/数据库有库来支持这一点。基本上,这样的数据结构将点嵌入到矩形树中,并使用半径搜索树。这应该足够快,而且我相信比构建 Voronoi 图更简单。我想有一个阈值,您更喜欢 Voronoi 图的附加性能,因此您将准备好为增加的复杂性付出代价。
【讨论】:
【参考方案7】:这可以通过多种方式解决。我将首先通过生成一个Delaunay 网络来解决这个问题,该网络将最近的点相互连接起来。这可以通过开源 GIS 应用程序GRASS 中的 v.delaunay 命令来完成。您可以使用 GRASS 中的众多 network analysis modules 之一来完成 GRASS 中的问题。或者,您可以使用免费空间 RDBMS PostGIS 进行距离查询。 PostGIS 空间查询比 MySQL 中的要强大得多,因为它们不受 BBOX 操作的限制。例如:
SELECT network_id, ST_Length(geometry) from spatial_table where ST_Length(geometry) < 10;
由于您使用的是经度和纬度,因此您可能希望使用Spheroid-Distance functions。借助空间索引,PostGIS 非常适合大型数据集。
【讨论】:
【参考方案8】:即使您创建了一个 voronoi 图,这仍然意味着您需要将您的 x、y 坐标与所有 15000 个创建的区域进行比较。为了使这更容易,我想到的第一件事是在可能的值上创建某种网格,以便您可以轻松地将 x/y 坐标放置到网格中的一个框中,如果相同的话完成区域列表后,您应该快速缩小可能的候选对象进行比较(因为网格会更矩形,一个区域可能位于多个网格位置)。
【讨论】:
【参考方案9】:Premature optimization is the root of all evil.
15K 坐标并不多。为什么不遍历 15K 坐标,看看这是否真的是一个性能问题?您可以节省大量工作,而且可能永远不会太慢以至于无法注意到。
【讨论】:
您不知道他的计算(cpu)到底在哪里进行,以及为什么。他可以在 MIPS 之类的嵌入式平台上进行操作,这可能会花费他大量的 CPU 时间。【参考方案10】:这些坐标分布在多大的范围内?他们在哪个纬度?您需要多少精度?如果它们非常接近,您可能会忽略地球是圆的这一事实,而只是将其视为笛卡尔平面,而不是搞乱球面几何和大圆距离。当然,随着您远离赤道,经度与纬度相比变得更小,因此某种比例因子可能是合适的。
从一个相当简单的距离公式和蛮力搜索开始,看看这需要多长时间,以及结果是否足够准确,然后才开始看中。
【讨论】:
【参考方案11】:感谢大家的回答。
@Tom,@Chris Upchurch:坐标彼此相当接近,并且它们位于相对较小的区域内,大约 800 平方公里。我想我可以假设表面是平坦的。我需要一遍又一遍地处理请求,响应速度应该足够快,以获得更多的网络体验。
【讨论】:
【参考方案12】:网格非常简单,而且速度非常快。它基本上只是一个二维列表数组。每个数组条目表示落在网格单元内的点。很容易设置网格:
对于每个点 p 获取包含 p 的单元格 将点添加到该单元格的列表而且查找起来非常容易:
给定一个查询点 p 获取包含 p 的单元格 针对查询点 p 检查该单元格(及其 8 个邻居)中的点阿莱霍
【讨论】:
【参考方案13】:为了逆势而上,您是指距离很近还是(驾驶)时间很近?在市区,我很乐意在高速公路上行驶 5 英里(5 分钟),而不是在另一个方向行驶 4 英里(20 分钟走走停停)。
因此,如果它是您需要的“最接近”的指标,我会查看带有旅行时间指标的 GIS 数据库。
【讨论】:
以上是关于经纬度坐标比较的主要内容,如果未能解决你的问题,请参考以下文章
在中国地图上确定南京和拉萨得经纬度,在世界地图上确定美国休斯敦得经纬度,比较三者谁的经纬度相近?讲