在给定距离处查找彼此远离的表格中的坐标

Posted

技术标签:

【中文标题】在给定距离处查找彼此远离的表格中的坐标【英文标题】:Find coordinates in a table away from each other at given distance 【发布时间】:2018-05-29 09:13:20 【问题描述】:

mysql 表中有类似的数据。 (大约 500k)条记录

    id  latitude    longitude   
------  ----------  ------------
106837  24.7218925  68.2604037  
106838  24.7218947  68.260412   
106839  24.7219007  68.2604083  
106840  24.721902   68.260403   
106841  24.7219149  68.260416   
106842  24.7219169  68.2604118  
106843  24.7219172  68.2604141  
106844  24.7219269  68.2604097  
106845  24.7219299  68.2604039  
106846  24.7219346  68.2603994  
106847  24.7219409  68.2604027  
106848  24.7219434  68.2604129  
106849  24.721956   68.2603941  
106850  24.7219879  68.2603614  
106851  24.7268579  68.2586257  
106852  24.7283047  68.2575022  
106853  24.7283047  68.2575032  
106854  24.7283141  68.2575256  
106855  24.728375   68.2575342  
106856  24.7283862  68.2575007  
106857  24.7284202  68.2575555  
106858  24.7284468  68.257605   
106859  24.7284485  68.2576076  
106860  24.7284639  68.2576095  
106861  24.7284675  68.2576157  

我想过滤所有相距 100 米的坐标。

我有 500k 个坐标,其中一些坐标大约取自相同的位置并相互重叠,但我只想区分所有至少相距 100 米的坐标

架构:

CREATE TABLE `coordinates` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `region` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `area` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `territory` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `town` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `latitude` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `longitude` varchar(191) COLLATE utf8mb4_unicode_ci NOT NULL,
  `completed` tinyint(1) NOT NULL DEFAULT '0',
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=533273 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

用图片和更多细节更新我的问题。

图片更清晰:

如您所见,我在地图 A、B、C、D、E、F 上有 6 个坐标,我的表格中有这些坐标,如下所示。

现在,只检索 A、B、C 和 D 坐标的查询是什么?我不想得到 E 和 F,因为 E 已经离 D 最近,而 F 离 C 很近,或者我们可以说 E、F 都在其他坐标的 100 米半径范围内。希望你能理解我的问题。

【问题讨论】:

你可以通过使用where 子句得到这个,其中差值大于等于100 你在解决这个问题的哪一部分? 如果这些代表地球上的坐标,那么我认为所有点之间的距离都远远超过 100m。 请看现在我已经更新了我的数据,我的桌子上有真实的坐标。 【参考方案1】:

算法1.聚类分析

据我了解,您想找到点的“集群”。这是一个非常困难的数学挑战。它超出了简单 SQL 操作的范围。

算法 2. 详尽

所以我将简化任务。您从 500K 点的列表开始。您将从列表中删除点,直到没有两个点“彼此非常接近”。

Foreach point, A, remaining in the list
    Foreach other point, B, in the list
        If A and B are within 100 meters, delete B from the list.

让我们分析一下这个简单的算法。

假设最终结果将是 100K 点。我们需要询问您需要执行多少次“is A near B”测试。

第一点 A 必须与 500K-1 Bs 进行比较。 最后一点 A 必须与大约 100K Bs 进行比较。 所以比较的总数在 100K^2 和 500K^2 之间。这些值是 10 billion 和 250 billion 。呸。这可能需要数周才能运行。

算法 3:“桶”

    制作一个 200 米乘 200 米的网格。 (简单 SQL;50 万次操作) 计算每个点在哪个桶中。将其放在与该点相关的列中。 对于每个桶,进行距离检查以消除“非常接近”的点。 (可能只有几百万次测试。)

现在您即将获得一个已清理的点列表。但是两个接近点可能在网格中的相邻存储桶中。这可以通过重做网格向东移动 100 米,然后向南,然后向西移动来解决。即上述3个步骤共执行4次。

距离

同时,你真的想用VARCHAR(191) 做算术吗?如果你想使用ST_Distance_Sphere(),你可以这样做。或者您可以切换到DOUBLE 并使用简单的毕达哥拉斯算法。 (我不知道哪个会更快。但我知道任何一个都足够精确,可以决定对抗微小的 100 米。

请使用 InnoDB。

【讨论】:

【参考方案2】:

您可以通过使用 ST_Distance_Sphere(g1, g2 [, radius]) mysql 函数的where 子句在差异大于等于 100 的情况下获得此信息

select *
from tbl
where ST_Distance_Sphere(POINT(Latitude,Longitude), POINT(Latitude,Longitude)) >=100

【讨论】:

我认为你没有明白我的意思。我有 500k 坐标,其中一些坐标大约取自相同的位置并相互重叠,但我只想区分所有至少相距 100 米的坐标。 你能确定一下,上面的查询对你有用吗?我有 5.7.19 的 mysql。我还分享了有问题的表架构。 另一个问题 --- SELECT ST_Distance_Sphere(POINT(latitude, longitude), POINT(latitude, longitude)) AS 'distance' --- 它正在工作,但每行返回 0。跨度> 问题是如何将表格中的每个坐标与特定距离进行比较。

以上是关于在给定距离处查找彼此远离的表格中的坐标的主要内容,如果未能解决你的问题,请参考以下文章

计算Excel表格中两个地方之间的地理坐标距离

查找坐标之间的平均距离

查找用户是不是在给定坐标的给定距离内

在距源一定距离处找到坐标

如何批量删除excel表格中数字前后的方括号

在Shapely中查找路径起点的坐标距离