计算平均经纬度坐标


19

如何计算几个纬度和经度点之间的平均值?

我应该只计算lat和lng的算术平均值吗?


3
我认为平均的适当性取决于您的用例。如果您只是在为城市地图群集城市餐厅位置,请确保平均在大多数情况下都有效。但是,您可能会在某些地方遇到错误。.对于原型或预算较低的应用程序,可能还可以。但是,如果您正在做更严肃的事情或覆盖广阔的区域,则可能需要考虑到投影的细微差别。
Glenn

1
这些分数是如何收集的?而不是询问如何平均坐标,而是询问平均是否是补偿测量误差的适当方法。这本电子书 有很多错误定义。
Kirk Kuykendall

请注意,在某些极端情况下,“平均点”的定义不明确:例如,赤道沿线的任何地方都可能是N和S极的“平均”。
Dan S.

Answers:


15

简单来说,您不希望平均经度和纬度坐标。这在较低的纬度下可能效果很好,但是在较高的纬度下,它将开始产生较差的结果,并在两极附近完全崩溃。

我用于此类事物的方法是将经度/纬度坐标转换为3d笛卡尔坐标(x,y,z)。平均这些(以给出笛卡尔向量),然后再次转换回去。请注意,您可能不需要对向量进行归一化,因此实际平均过程可能只是一个简单的总和。


编辑,这是我的代码:

以下将笛卡尔坐标转换为纬度/经度(以度RAD2DEG为单位):删除弧度的常数。

Latitude = MPUtility.RAD2DEG * Math.Atan2(z, Math.Sqrt(x * x + y * y));
Longitude = MPUtility.RAD2DEG * Math.Atan2(-y, x);

在这里,我们根据纬度/经度(以弧度为单位)计算笛卡尔坐标:

private void CalcCartesianCoord()
{
    _x = Math.Sin(LatitudeRadians) * Math.Cos(LongitudeRadians);
    _y = Math.Sin(LatitudeRadians) * Math.Sin(LongitudeRadians);
    _z = Math.Cos(LatitudeRadians); 
}

两者都是从真实代码中剪切和粘贴的,因此是度数和弧度的混合。这里有一些执行某些转换LatitudeRadians的属性(例如,是一个返回弧度值的属性)。

请注意,可以进行优化:例如,重复正弦计算。如果您经常调用它们,trig计算也可能是可缓存的。


1
好点。我不敢相信我忘了提..在极点和日期线附近平均数以前已经使我难过了。
Glenn

3
(+1)问题不仅仅限于极点和+ -180度子午线:当要平均的点的纬度变化很大时,纬度/经度坐标的直线平均等于使用板式Carree投影,引入随纬度增加的可变度量失真。没有数值问题,但平均值只是在错误的位置。因此,@ Glenn答案中建议的经/纬度计算很少接受,除了相对较小的非极性区域。
ub

@winwaed谢谢,您能建议一些(Java)代码片段或好的教程来做到这一点吗?
aneuryzm 2011年

1
数学位于“笛卡尔坐标”下的en.wikipedia.org/wiki/Spherical_coordinates。(我的实现是C#并进行了部分优化-另外,我要在牙医那里输入
密码

1
我认为对于精确的工程用例,您是非常正确的。但是,除非要求极高的精度,否则在城市乃至区域区域对WGS84纬度,经度坐标进行平均都可以很好地工作,并且得出的结果对于大多数使用平均的用途来说都是可以接受的。
Glenn

3

集群选项:我认为涵盖此类操作的概念性时髦词是“集群”。到目前为止,平均是最简单的实施方法,并且可以很好地用于大多数目的。我唯一会使用其他方法的情况是,如果您担心异常值[Edit]->或极点或国际日期变更线。[编辑]->也可以取平均值,尽管它会给您看起来接近群集中心的位置,但由于度数并不总是相同而导致投影不准确,因此会有些偏离相隔公里/英里。您平均的面积越大,失真越大。

这是一些群集选项的比较

平均值(简单,快速,不准确): 只需将纬度值相加并除以计数,然后对lng值进行相同的处理。如果您使用的是Int32,请务必注意是否有溢出,某些系统(特别是c#)将悄无声息地回到低位。您可以通过对总和累加器使用浮点精度来避免这些错误。这种方法的一个问题是离群值可能会使您的位置偏斜。[编辑]->另一个问题是,极点和国际日期界线附近的数学平均值不佳,并且会严重歪斜位置。

最近的邻居(更难,更慢,没有异常的偏向) 与其求平均,不如使用实际的纬度位置,到所有邻居的平均距离最小。这有点像采用“中位数”。不利的一面是,这在计算上是昂贵的,因为您将每个点与每个其他点进行比较并计算它们之间的距离。例如,对10,000个点进行聚类将需要进行1亿个距离计算..并不是那么慢,但是它肯定不能很好地扩展。

网格单元(需要一些额外的设置,速度更快,没有异常偏斜)这类似于最近的邻居,但是速度更快。您可以选择任意精度,例如0.01纬度(在人口纬度大约为1公里),然后将各个点归为0.01 x .01度的水桶。然后,您可以选择其中包含最多点的存储桶,然后取这些点的平均值,或者仅对那些点进行最近的邻居分析。我在大型数据集(数千亿条记录)中经常使用此方法,并发现它在精度和速度之间达到了很好的平衡。

凸壳质心(硬,慢,整洁的结果): 您还可以在点周围画一条带以定义一个覆盖所有点的形状(请参阅Wikipedia),然后计算该形状的中心点。典型的质心函数不是中心加权的,因此您需要使用形状内的采样点进行某种逆最近邻分析,直到找到距离边缘最远的一个。由于凸包本身而不是既不快速也不精确的实际中心查找算法,因此该方法确实更有趣。


@winwaed对于在极点附近平均坐标很重要,我还要添加国际日期线。例如,如果一侧有一个点,另一侧有一个点,则会得到一些差的平均值(还有边界框)。很少出现这种情况,但是调试时确实很痛苦
Glenn

当您平均时,@ whuber很好地说明了中心漂移。虽然平均会给您一些看起来接近群集中心的信息,但是由于纬度并不总是以公里/英里为单位的相同距离而导致投影不准确,因此会有些偏离。您平均的面积越大,失真越大。
Glenn

0

不确定要达到的目标,但是纬度为原始点集的平均纬度和经度为原始点集的平均经度的点将是原始点集的平均点。[更新]:在上面,avg是算术平均值。


在您的答案中,avg =算术平均值?
aneuryzm 2011年

1
是,对的。这就是我对缺乏明确性表示抱歉。我更新了答案。但是我不确定我是否会在这里带来一些非常有用的信息……
GuillaumeC
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.