通过彼此接近来分组坐标

时间:2015-07-30 11:32:00

标签: php mysql group-by coordinates

我正在构建REST API,因此答案不能包含Google地图或javascript内容。 在我们的应用程序中,我们有一个包含以下内容的表格:

  ID |   latitude   | longitude   | other_sutff
   1 | 50.4371243   |  5.9681102  |    ...
   2 | 50.3305477   |  6.9420498  |    ...
   3 | -33.4510148  | 149.5519662 |    ...

我们有一个地图视图,显示全球所有帖子。 希望我们会有很多帖子,在地图中显示成千上万的标记会很荒谬。所以我们希望通过接近度对它们进行分组,这样我们就可以在大陆上找到2-3个标记。

要说清楚,我们需要这个: enter image description here 来自https://github.com/googlemaps/js-marker-clusterer的图片

我做了一些研究,发现k-means似乎是解决方案的一部分。 由于我在数学方面真的很糟糕,我尝试了几个像这样的PHP库:https://github.com/bdelespierre/php-kmeans这似乎做得不错。 但是,有一个缺点:每次加载地图时我都必须解析所有表。性能方面,它很糟糕。

所以我想知道是否有人已经解决了这个问题,或者是否有更好的解决方案。

1 个答案:

答案 0 :(得分:4)

我一直在搜索,我找到了替代KMeans的方法: GEOHASH

维基百科将比我更好地解释它是什么:Wiki geohash

但总而言之,世界地图被划分为32个单元格,每个单元格都有一个字母数字字符。 每个细胞也分为32个细胞,依此类推12个细胞。 因此,如果我在第一个哈希字母上执行GROUP BY,我将获得最低缩放级别的聚类,如果我想要更高的精度,我只需要按照哈希的前N个字母进行分组。

所以,我所做的只是在我的表中添加了一个字段并生成与我的坐标对应的哈希:

ID |   latitude   | longitude   | geohash      | other_sutff
 1 | 50.4371243   |  5.9681102  | csyqm73ymkh2 |     ...
 2 | 50.3305477   |  6.9420498  | p24k1mmh98eu |     ...
 3 | -33.4510148  | 149.5519662 | 8x2s9674nd57 |     ...

现在,如果我想获得我的集群,我只需要做一个简单的查询:

SELECT count(*) as nb_markers FROM mtable GROUP BY SUBSTRING(geohash,1,2); 

在子字符串中,2是精度级别,必须介于1到12之间

PS:Lib I used to generate my hash