如何将近点与GPS位置分组?


10

我是一名IT人员,所以我对预测不了解太多,所以希望您能为我提供帮助。

我已经为Android制作了一个应用程序,该应用程序收集GPS位置,因此我在给定时间具有经度和纬度。我要救那些元素结合在一起接近对方,在相同的物理性大小的地形区域的群体; 问题是我不事先知道这些要点,它们可以来自世界的任何位置

我的第一个想法(稍微解释一下这个问题)是使用经度和纬度的小数点进行分组。例如,一组将是纬度在35.123和35.124之间,经度在60.101和60.102之间的位置。因此,如果我得到像lat = 35.1235647和lon = 60.1012254598之类的职位,那么这一点将转到该组。

对于笛卡尔2D表示,此解决方案是可以的,因为我的宽度和高度为0.001单位;但是,由于不同纬度下1度经度的大小不同,因此我无法使用此方法。

任何的想法?


为什么不能按原样存储位置,然后再进行处理?同样在赤道处,经度为1度约为111 km,因此0.001度将略大于1 Km。你真的想要你的垃圾箱这么大吗?
Devdatta Tengshe 2013年

0.001度只是我的想法的一个例子。当然,我将不得不使其适应要求。我无法进行后期处理,因为它计划成为实时应用程序,并且我无法对用户说“等到明天,因为我必须将要点分组”无论如何都要感谢您的想法;)
Kuu

Answers:


6

一种快速而肮脏的方法是使用递归球面细分。从地球表面的三角剖分开始,递归地将每个三角形从顶点延伸到最长边的中间。(理想情况下,您会将三角形分成两个相等直径的部分或相等面积的部分,但是由于这些部分涉及一些复杂的计算,因此我只是将边精确地分成了一半:这会导致各个三角形的大小最终有所不同,但是对于这个应用来说似乎并不重要。)

当然,您将在数据结构中维护此细分,以便快速识别任意点所在的三角形。二叉树(基于递归调用)很好地工作:每次拆分三角形时,树都会在该三角形的节点处拆分。保留有关分割平面的数据,以便您可以快速确定任意点位于平面的哪一侧:这将确定是在树上向左还是向右移动。

(我是否说过要分割“平面”?是的-如果将地球表面建模为球体并使用地心(x,y,z)坐标,则我们的大部分计算都将在三个维度上进行,其中三角形的边是球体与通过其原点的平面的交点。这使得计算变得快速而简单。)


我将通过显示一个球体的一个八分圆点的过程进行说明。其他七个八分圆以相同的方式处理。这样的八分圆是90-90-90的三角形。在我的图形中,我将绘制跨越相同角的欧几里得三角形:它们看起来不会很好,直到变小为止,但是可以轻松,快速地绘制它们。这是与八分圆对应的欧几里得三角形:这是过程的开始。

图1

由于所有边的长度相等,因此随机选择一个边作为“最长边”并细分:

图2

对每个新三角形重复此操作:

图3

n步之后,我们将有2 ^ n个三角形。这是经过10个步骤后的情况,显示了八分圆中的1024个三角形(总球面上的8192个三角形):

图4

作为进一步的说明,我在该八分圆内生成了一个随机点,然后遍历了细分树,直到三角形的最长边小于0.05弧度。显示(笛卡尔)三角形,探测点为红色。

图5

顺便说一句,要将点的位置缩小到一个纬度(大约),您会注意到这大约是1/60弧度,因此覆盖了(1/60)^ 2 / /(Pi / 2)= 1/6000弧度。总表面。由于每个细分大约将三角形大小减半,因此八分圆的大约13到14个细分将达到目的。这并不需要太多的计算,正如我们将在下面看到的那样,这使它完全不必存储树,而是动态地进行细分是很有效的。在开始时,您会注意到该点位于哪个八分圆中-由其三个坐标的符号确定,可以将其记录为三位数的二进制数-并且在每个步骤中,您都需要记住该点是否位于在三角形的左(0)或右(1)中。这给出了另一个14位二进制数。 您可以使用这些代码对任意点进行分组。

(通常,当两个代码接近于实际的二进制数时,对应的点也接近;但是,这些点仍然可以接近并且具有明显不同的代码。例如,将相距一米的两个点分隔为赤道,例如:它们的代码必须相同,甚至在二进位点之前,因为它们位于不同的八分位。任何固定的空间划分都是不可避免的。)


我使用Mathematica 8来实现这一点:您可以将其按原样或作为伪代码在您喜欢的编程环境中实现。

确定平面0-ab点p位于哪一侧:

side[p_, {a_, b_}] := If[Det[{p, a, b}] >=  0, left, right];

根据点p细化三角形abc。

refine[p_, {a_, b_, c_}] := Block[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  If[side[p, {x, m}] === right, {y, m, x}, {x, m, z}] 
  ]

最后一个图是通过显示八分圆并在其上方将以下列表呈现为一组多边形来绘制的:

p = Normalize@RandomReal[NormalDistribution[0, 1], 3]        (* Random point *)
{a, b, c} = IdentityMatrix[3] . DiagonalMatrix[Sign[p]] // N (* First octant *)
NestWhileList[refine[p, #] &, {a, b, c}, Norm[#[[1]] - #[[2]]] >= 0.05 &, 1, 16]

NestWhileListrefine在条件适用(三角形较大)时或直到达到最大操作计数(16)时,重复应用操作()。

为了显示八分圆的完整三角剖分,我从第一个八分圆开始,并对精化进行了十次迭代。首先对以下内容进行一些修改refine

split[{a_, b_, c_}] := Module[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  {{y, m, x}, {x, m, z}}
  ]

不同之处在于,它split返回输入三角形的两个一半,而不是给定点所在的三角形。完整的三角剖分是通过以下方式获得的:

triangles = NestList[Flatten[split /@ #, 1] &, {IdentityMatrix[3] // N}, 10];

为了进行检查,我计算了每个三角形的大小并查看了范围。(此“大小”与每个三角形和球体中心对接的金字塔形图形成比例;对于像这样的小三角形,此大小基本上与其球形区域成比例。)

Through[{Min, Max}[Map[Round[Det[#], 0.00001] &, triangles[[10]] // N, {1}]]]

{0.00523,0.00739}

因此,大小与平均值的上下差异约为25%:这对于实现近似统一的分组方式似乎是合理的。

在扫描此代码时,您不会注意到三角函数:唯一需要的地方就是在球坐标和笛卡尔坐标之间来回转换。该代码也不会将地球表面投射到任何地图上,从而避免了随之而来的变形。否则,它仅使用平均值(Mean),勾股定理(Norm)和3×3行列式(Det)来完成所有工作。(还有一些简单的列表操作命令,例如RotateLeftFlatten,以及对每个三角形最长边的搜索。)


1

这是一项艰巨的任务,因为从3D WGS84地理坐标系到平面2D投影时,投影会引入变形。在全球范围内,您一定会在系统中的某个地方出现失真。

我认为您最好的选择是投影到通用横轴墨卡托投影。据我所知,这是最接近失真最小的全局投影。

如果您可以放宽必须在完全相同大小的区域中定义组的要求以及实时处理的要求,那么可以使用诸如DBSCAN的聚类算法以及一组派生类来帮助进行分组。


1
UTM不是“全局投影”:演示是几乎任何一对有效坐标(例如(500000,5000000))对应于UTM系统中至少120个不同的,广泛分隔的点。而且,不幸的是,聚类算法无法满足OP 仅基于其位置(而不是基于它们与其他点的接近度)进行实时分组的需求。
ub

@whuber回复:“全球投影”-对。这就是为什么我说“最接近全球投影”。如果您知道更好的投影系统更合适,请在评论中保留它,然后我将编辑我的答案。另外,OP在最初的帖子中没有实时要求。我将编辑答案以考虑到这一点。
肖恩·巴博

肖恩(1)我对全局投影问题的解决方案是不使用它。存在无奇全球投影。(2)是的,实时澄清出现在评论中。不过,“我的第一个想法”后面的文字确实做得很好,强调该问题是对地球表面进行分区而不是对一组位置进行聚类。这就是我(不是很有效)试图在我对您的早期评论中传达的观点。
ub
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.