如何使用laravel/php基于经度/纬度接近度对对象进行分组

TJ *_*ill 3 php geolocation laravel-5

我有一组用户.用户数可能是50或者可能是2000.每个用户都应该有一个我从Google Geo api检索到的长/ lat.

我需要查询所有内容,并按接近度和特定计数对它们进行分组.假设计数为12,我在该组中有120个用户.我想根据他们与其他人的距离(长/纬)来对人进行分组.因此,我最近接近10组人.

我目前有谷歌地理编码api设置,并希望使用它.

TIA.

- 更新我已经谷歌搜索了一段时间,似乎我正在寻找一个空间查询,通过接近返回组.

rf1*_*234 5

...似乎我正在寻找一个通过邻近度返回组的空间查询....

你可以使用hdbscan.您的组实际上是hdbscan措辞中的集群.您需要使用min_cluster_size和min_samples来使您的组正确.

https://hdbscan.readthedocs.io/en/latest/parameter_selection.html

https://hdbscan.readthedocs.io/en/latest/

似乎hdbscan在Python下运行.

下面是关于如何从PHP调用Python两个环节: 在PHP中调用的Python, 运行从PHP Python脚本

以下是有关选择哪种聚类算法的更多信息:http: //nbviewer.jupyter.org/github/scikit-learn-contrib/hdbscan/blob/master/notebooks/Comparing%20Clustering%20Algorithms.ipynb

http://scikit-learn.org/stable/modules/clustering.html#clustering


Jav*_*let 5

请记住,这个问题随着您添加的每个用户的增长呈指数级增长,因为距离计算的数量与用户数量的平方相关(实际上是N*(N-1)距离...因此2000个用户群将意味着将近400万次距离计算每遍都行,在确定所需资源时请记住这一点

您是要根据直线(实际上是一个大圆)距离还是根据步行/行车距离对它们进行分组?

如果是前者,那么如果您能够容忍很小的误差范围并且希望假设地球是一个球体,那么可以用简单的数学方法估算出较大的圆距离。从GCMAP.com:

地球的假设形状称为大地水准面,近似为椭圆形或扁球形。一个更简单的模型是使用球体,该球体非常接近并且使数学更容易。假设半径为6371.2公里的球体,将经度和纬度转换为弧度(乘以pi / 180),然后使用以下公式:

theta = lon2 - lon1
dist = acos(sin(lat1) × sin(lat2) + cos(lat1) × cos(lat2) × cos(theta))
if (dist < 0) dist = dist + pi
dist = dist × 6371.2
Run Code Online (Sandbox Code Playgroud)

结果距离以公里为单位。

现在,如果您需要精确的计算并愿意花费很多复杂数学所需的CPU周期,则可以使用Vincenty公式,该公式使用了地球的WGS-84参考椭球模型,该模型用于导航,地图绘制等。更多信息在这里

至于算法本身,您需要使用每次计算的结果来构建一个“至”矩阵。每行和每列将代表每个节点。您可以考虑两种简化方法:

  1. 距离不取决于行进方向,因此$dist[n][m] == $dist[m][n](无需计算整个矩阵,只需计算一半即可)
  2. 节点到其自身的距离始终为0,因此无需计算,但由于您打算按接近度进行分组,为避免用户与其自身分组,您可能希望始终强制$dist[m][m]使用任意定义且异常大的节点常量($dist[m][m] = 22000 (miles)例如,只要您的所有用户都在地球上就可以使用)

完成所有计算后,使用数组排序方法找到每个节点附近的X个最接近的节点,然后在该节点上找到(您可能会或可能不想防止将用户分组到多个组中,但这仅是业务逻辑)

目前无法提供实际的代码太多,而没有先看到您的一些进度,但这基本上是您需要通过算法完成的工作。