从一个点获得最短距离

时间:2013-08-24 15:58:05

标签: android sql sqlite gps location

我在sqlite中有这个表

Locations
ID
Lat ( latitude)
Lon ( longitude) 
Type
Name
City

我有100条记录 我需要的是(使用我自己的坐标)得到表格中最近的点。

我所做的是获得当前点与表中每个点之间的最短距离,并返回最短点,但我正在寻找更好的解决方案

由于

8 个答案:

答案 0 :(得分:6)

一种可能的解决方案是为您感兴趣的整个地图使用网格,并将点预分配给特定的行/列。然后:

  1. 计算新点的网格位置 - 为此向数据库添加一列。
  2. 计算当前网格中所有坐标的距离 - 如果存在
  3. 您仍然需要计算下一个网格中的所有距离(您不太可能完全居中于当前的方格,您总是需要检查距离最佳匹配的网格距离。)
  4. 应该减少你需要做的计算次数。

    如果您希望始终在X距离内找到位置,您可以查询x / y坐标,这些坐标将在您的坐标范围内+/- x KM(正方形),计算它们是否属于xKM圈内你的观点,然后选择最短的。

    更新 - 网格选项

    我假设你已经在两点计算之间做距离,并且不会描述它。

    如果您有方便的地图集,您可以通过查看索引中的位置来查看示例。它将为您提供一个页面和网格位置,如M5。如果你去那个页面,它会有用数字和字母标记的行和列,如果你看到第M行和第5列相交的方块,你会在那里找到那个城市。要为您的系统执行此操作,您需要:

    1. 确定你的网格应该有多大(你的点数有多密集 - 拥有一个大网格并且你的所有点落在一个方格中都没有好处。)
    2. 对于每个点,计算它所在的网格。如果您的多边形很复杂,那么多边形代码中有大量的点要复制。如果(就我的例子而言)你只是使用正方形,你只需要确定每个点之间的行/列。
    3. 请参阅地图了解用户位置和最近点示例:
    4. enter image description here

      因此,如果用户是绿色标记,他将在C4中。您将搜索C4中的所有其他点并确定最接近的是#2。然后你还必须检查一个网格,以确保没有比你找到的更近的项目,所以这包括正方形:B3,B4,B5,C3,C5,D3,D4,D5 。当你这样做时,你将从C3中选择#3并完成。

      如果用户在方形D2中没有其他分数,那么你会在C2中找到你的第一场比赛。检查C1,C2,C3,D1,D3,E1,E2,E3时。一旦找到,你将再次需要检查另一个半径,这将是:B0-4,C0,C4,D0,D4,E0,E4,F0-4。您可以看到网格选择对于尽可能提高效率非常重要。

      另请注意,假设您的网格与我的手绘示例不同。

      选项2:

      如果您希望X km内的结果,并且您希望数据库能够快速计算出来,那么您可以这样做:

      LatMin = currentLatCoord-radiusValInDegrees
      LatMax = currentLatCoord+radiusValInDegrees
      LonMin = currentLonCoord-radiusValInDegrees
      LonMax = currentLonCoord+radiusValInDegrees
      
      SELECT * 
      From Locations 
      WHERE Lat BETWEEN LatMin AND LatMax
        AND Lon BETWEEN LonMin AND LonMax
      

      现在,这将为您提供正方形的所有结果。重要的是,然后检查它们实际上是在圆圈中 - 您需要在角落中放下任何角落,因为实际上可能存在比圆圈边缘更近的坐标。因此,对于每个点,检查它是否首先在圆圈内(Equation for testing if a point is inside a circle),然后计算距离并保持最近的距离。如果没有得到结果,请加宽圆圈。

      同样,选择良好的半径取决于您的数据。

答案 1 :(得分:4)

您是否在本网站上查看了如何计算distance between two points on Earth

但请记住,它根据地球表面给出的距离不是基于到达该位置的实际路径。因此,如果您想根据实际路径计算距离以达到该位置,那么您可以使用Google MAP API获取该距离。

Google Maps API根据实际路径给出两点之间的距离。

希望这些信息对您有所帮助。

享受编码......:)

答案 2 :(得分:2)

两点之间的距离:((x1 - x2) ^ 2 + (y1 - y2) ^ 2) ^ 0.5。但是,这些点之间的距离是直线。最有可能的是,有一些变量,如本地和高速公路,更不用说单行道和水道,你需要找到最近的桥梁。因此,我建议使用谷歌和Bing地图api。对于有限数量的搜索是免费的。

答案 3 :(得分:2)

Query to get records based on Radius in SQLite?处有一个相当聪明的解决方案 基于在插入行时预先计算每个位置的一些三角函数值,然后只允许使用算术函数计算查询中的距离。

我在自己的代码中非常成功地使用了它

答案 4 :(得分:1)

让我确保这是正确的:您有点a和点a[]表。目前,您执行以下操作:

  
      
  • 循环b[]   
        
    • distance获取b[i]a
    •   
    • 如果distance小于minimumDistance   
          
      • 设置minimumDistance = distance
      •   
      • 设置closestPoint = i
      •   
    •   
  •   
  • return closestPoint
  •   

如果是这样,你会在O(n)时间内找到它,但实际上并没有真正得到改善。您必须检查所有点以查看哪个点最近。

然而,正如Matthew所指出的那样,你可以通过为网格分配点来修剪n。这可以大大减少比较所需的点数。费用是预处理的一点时间,逻辑稍微复杂一些。如果你有一长串的积分(或distance()函数需要很长时间),你肯定会想做这样的事情。

答案 5 :(得分:1)

取决于你在靠近两极时对你的正确程度的关注

如果最近的毕达哥拉斯距离足够好你可以按照sql的顺序使用它

例如。 SELECT * FROM locations ORDERBY (Lat-myLat)*(Lat-myLat) + (Lon-myLon)*(Lon-myLon) LIMIT 1

从技术上讲,它不是最正确的,但保存从数据库中获取所有位置并循环遍历它们,让sqlite为您执行此操作

答案 6 :(得分:1)

你可以使用我的php类hilbert curve @ phpclasses.org。它使用怪物曲线和四核来找到最短距离。要搜索四核,您可以使用任何深度。

答案 7 :(得分:1)

虽然这不是最佳选择 让你试图找出 N 英里/公里的最短距离,对于固定的位置/您的位置表数据没有定期更改。
添加另一列 Distance_Index(DI)自我多引用键ArrayType。一旦运行程序并根据与DI的距离按升序更新DI。  现在从下一次开始,你就可以了。只需查询数据库并使用它 Sample table data

现在,在你的问题中,没有位置在N之内,DI不会太长。只是一个意见。