【问题标题】:Get the distance between two geo points获取两个地理点之间的距离
【发布时间】:2011-02-14 01:06:03
【问题描述】:

我想制作一个应用程序来检查用户最近的位置。我可以轻松获取用户的位置,并且我已经有了一个经纬度的地点列表。

根据当前用户位置了解列表中最近位置的最佳方法是什么。

我在谷歌 API 中找不到任何东西。

【问题讨论】:

    标签: android geolocation maps


    【解决方案1】:
    Location loc1 = new Location("");
    loc1.setLatitude(lat1);
    loc1.setLongitude(lon1);
    
    Location loc2 = new Location("");
    loc2.setLatitude(lat2);
    loc2.setLongitude(lon2);
    
    float distanceInMeters = loc1.distanceTo(loc2);
    

    参考:http://developer.android.com/reference/android/location/Location.html#distanceTo(android.location.Location)

    【讨论】:

    • 可能比使用 Location.DistanceBetween() 慢,因为它使用的是 Location 对象,但非常适合我的目的。
    • 我必须为位置 import android.location.Location; 导入哪个类或哪个类
    • @PranavMS 是的 android.location.Location;
    • 我认为 distanceTo 返回第一个点和最后一个点之间的距离,但在直肠线上,所以如果你从点 a 到 b 采取任何其他方向,因为路径不同,它永远不会被精确,那就是当 distanceBetween 加入时,您可以保存创建的点之间的每个距离,然后使用最终参数 results[] 获得正确的距离。
    【解决方案2】:

    http://developer.android.com/reference/android/location/Location.html

    查看 distanceTo 或 distanceBetween。您可以根据纬度和经度创建 Location 对象:

    Location location = new Location("");
    location.setLatitude(lat);
    location.setLongitude(lon);
    

    【讨论】:

    • distanceBetween 是一个静态方法,需要 2 组 lat long 点,所以你甚至不需要实例化一个 Location 对象 =)
    • 我确定他的意思是 distanceTo 方法。
    • 这很棒而且非常有用,但是构造函数中的字符串提供程序是什么?
    【解决方案3】:

    一个近似解(基于 ​​equirectangular 投影),更快(它只需要 1 个三角函数和 1 个平方根)。

    如果您的点相距不太远,则此近似值是相关的。与真实的半正弦距离相比,它总是会高估。例如,如果两点之间的纬度或经度增量不超过 4 个十进制度,它将不超过 0.05382 % 到实际距离。

    标准公式(Haversine)是精确的公式(也就是说,它适用于地球上的任何经度/纬度),但根据需要慢得多 7 个三角函数和 2 个平方根。如果您的两个点相距不太远,并且绝对精度不是最重要的,您可以使用这个近似版本(Equirectangular),因为它只使用一个三角函数和一个平方根,所以速度更快。

    // Approximate Equirectangular -- works if (lat1,lon1) ~ (lat2,lon2)
    int R = 6371; // km
    double x = (lon2 - lon1) * Math.cos((lat1 + lat2) / 2);
    double y = (lat2 - lat1);
    double distance = Math.sqrt(x * x + y * y) * R;
    

    您可以通过以下任一方式进一步优化

    1. 删除平方根,如果您只是将距离与另一个比较(在这种情况下比较两个平方距离);
    2. 将余弦分解,如果您计算从一个主点到许多其他点的距离(在这种情况下,您会进行以主点为中心的 equirectangular 投影,因此您可以为所有比较计算一次余弦) .

    欲了解更多信息,请参阅:http://www.movable-type.co.uk/scripts/latlong.html

    Haversine 公式有多种语言的一个很好的参考实现:http://www.codecodex.com/wiki/Calculate_Distance_Between_Two_Points_on_a_Globe

    【讨论】:

    • 伟大的人thanx。但是,如果我需要在外围的一个位置周围获取一组位置,我是否应该使用 while 循环来检查每个位置与搜索到的位置并仅保留外围中的位置?
    • 你可以,但这是O(n) 中的蛮力方法。对于O(1) 解决方案,请在计算精确解决方案之前使用二维空间索引来修剪潜在匹配项。我们将离开这个问题的范围:)
    • 这是对可能的优化的一个非常好的总结。谢谢!正是我想要的
    • 我只是想知道这个公式是否适用于远距离
    • 查看答案,但简而言之:,它不适用于远距离。两点之间的距离越大,与精确的 Haversine 公式相比误差越大。
    【解决方案4】:

    您可以使用几种方法,但要确定哪种方法最好,我们首先需要知道您是否知道用户的高度以及其他点的高度?

    根据您所追求的准确度,您可以研究 Haversine 或 Vincenty 公式...

    这些页面详细介绍了公式,并且,对于不太喜欢数学的人,还提供了如何在脚本中实现它们的说明!

    Haversine 公式:http://www.movable-type.co.uk/scripts/latlong.html

    文森提公式:http://www.movable-type.co.uk/scripts/latlong-vincenty.html

    如果您对公式中的任何含义有任何疑问,请发表评论,我会尽力回答:)

    【讨论】:

      【解决方案5】:

      有两种方法可以获取 LatLng 之间的距离。

      public static void distanceBetween (double startLatitude, double startLongitude, double endLatitude, double endLongitude, float[] results)
      

      See this

      第二个

      public float distanceTo (Location dest) 由 praveen 回答。

      【讨论】:

        【解决方案6】:
        private float getDistance(double lat1, double lon1, double lat2, double lon2) {
                float[] distance = new float[2];
                Location.distanceBetween(lat1, lon1, lat2, lon2, distance);
                return distance[0];
            }
        

        【讨论】:

          【解决方案7】:

          只需使用以下方法,将其经纬度传递并以米为单位获得距离:

          private static double distance_in_meter(final double lat1, final double lon1, final double lat2, final double lon2) {
              double R = 6371000f; // Radius of the earth in m
              double dLat = (lat1 - lat2) * Math.PI / 180f;
              double dLon = (lon1 - lon2) * Math.PI / 180f;
              double a = Math.sin(dLat/2) * Math.sin(dLat/2) +
                      Math.cos(latlong1.latitude * Math.PI / 180f) * Math.cos(latlong2.latitude * Math.PI / 180f) *
                              Math.sin(dLon/2) * Math.sin(dLon/2);
              double c = 2f * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
              double d = R * c;
              return d;
          }
          

          【讨论】:

          • latlong1 和 latlong2 未定义
          • latlong1 & latlong2 是什么?
          【解决方案8】:

          a = sin²(Δφ/2) + cos φ1 ⋅ cos φ2 ⋅ sin²(Δλ/2)

          c = 2 ⋅ atan2( √a, √(1−a) )

          距离 = R ⋅ c

          其中 φ 是纬度,λ 是经度,R 是地球半径(平均半径 = 6,371km);

          请注意,角度需要以弧度为单位才能传递给三角函数!

          fun distanceInMeter(firstLocation: Location, secondLocation: Location): Double {
              val earthRadius = 6371000.0
              val deltaLatitudeDegree = (firstLocation.latitude - secondLocation.latitude) * Math.PI / 180f
              val deltaLongitudeDegree = (firstLocation.longitude - secondLocation.longitude) * Math.PI / 180f
              val a = sin(deltaLatitudeDegree / 2).pow(2) +
                      cos(firstLocation.latitude * Math.PI / 180f) * cos(secondLocation.latitude * Math.PI / 180f) *
                      sin(deltaLongitudeDegree / 2).pow(2)
              val c = 2f * atan2(sqrt(a), sqrt(1 - a))
              return earthRadius * c
          }
          
          
          data class Location(val latitude: Double, val longitude: Double)
          

          【讨论】:

            【解决方案9】:

            您可以使用 google Map API 获取距离和时间 Google Map API

            只需将下载的 JSON 传递给此方法,您将获得两个 latlong 之间的实时距离和时间

            void parseJSONForDurationAndKMS(String json) throws JSONException {
            
                Log.d(TAG, "called parseJSONForDurationAndKMS");
                JSONObject jsonObject = new JSONObject(json);
                String distance;
                String duration;
                distance = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("distance").getString("text");
                duration = jsonObject.getJSONArray("routes").getJSONObject(0).getJSONArray("legs").getJSONObject(0).getJSONObject("duration").getString("text");
            
                Log.d(TAG, "distance : " + distance);
                Log.d(TAG, "duration : " + duration);
            
                distanceBWLats.setText("Distance : " + distance + "\n" + "Duration : " + duration);
            
            
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-03-20
              • 2020-10-06
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多