使用纬度经度计算两点之间的距离?

m4d*_*ign 81 java math latitude-longitude

这是我的尝试,它只是我的代码片段:

final double RADIUS = 6371.01;
double temp = Math.cos(Math.toRadians(latA))
            * Math.cos(Math.toRadians(latB))
            * Math.cos(Math.toRadians((latB) - (latA)))
            + Math.sin(Math.toRadians(latA))
            * Math.sin(Math.toRadians(latB));
    return temp * RADIUS * Math.PI / 180;
Run Code Online (Sandbox Code Playgroud)

我使用这个公式来获得经度和经度:

x = Deg + (Min + Sec / 60) / 60)
Run Code Online (Sandbox Code Playgroud)

Dav*_*rge 191

以上Dommer给出的Java代码给出了稍微不正确的结果,但如果您正在处理GPS轨道,则会出现小错误.以下是Java中Haversine方法的实现,它还考虑了两点之间的高度差异.

/**
 * Calculate distance between two points in latitude and longitude taking
 * into account height difference. If you are not interested in height
 * difference pass 0.0. Uses Haversine method as its base.
 * 
 * lat1, lon1 Start point lat2, lon2 End point el1 Start altitude in meters
 * el2 End altitude in meters
 * @returns Distance in Meters
 */
public static double distance(double lat1, double lat2, double lon1,
        double lon2, double el1, double el2) {

    final int R = 6371; // Radius of the earth

    double latDistance = Math.toRadians(lat2 - lat1);
    double lonDistance = Math.toRadians(lon2 - lon1);
    double a = Math.sin(latDistance / 2) * Math.sin(latDistance / 2)
            + Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2))
            * Math.sin(lonDistance / 2) * Math.sin(lonDistance / 2);
    double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
    double distance = R * c * 1000; // convert to meters

    double height = el1 - el2;

    distance = Math.pow(distance, 2) + Math.pow(height, 2);

    return Math.sqrt(distance);
}
Run Code Online (Sandbox Code Playgroud)

  • 为什么不Math.toRadians()而不是deg2rad()?这将是真正的自我包容. (7认同)
  • @ÁronNemmondommegavezetéknevem我已经更新了方法以使用你非常好的建议. (4认同)
  • @DavidG:输出的单位是多少? (2认同)
  • @Bala - 我的不好,这是在我的计算机上的代码评论中,但在这里丢失.距离(米). (2认同)
  • 这里有一些评论:http://stackoverflow.com/questions/28510115/java-math-toradiansangle-vs-hard-calculated?lq=1 (2认同)
  • 我犯了和 Mladen 一样的错误,通过了 (lat1, lon1, lat2, lon2) 而不是 (lat1, lat2, lon1, lon2)。确保不要交换值。 (2认同)

dom*_*mer 74

这是一个Java函数,用于计算两个纬度/长点之间的距离.

编辑

我找到了另一个代码的引用.

并在下面发布,以防它再次消失.

    private double distance(double lat1, double lon1, double lat2, double lon2, char unit) {
      double theta = lon1 - lon2;
      double dist = Math.sin(deg2rad(lat1)) * Math.sin(deg2rad(lat2)) + Math.cos(deg2rad(lat1)) * Math.cos(deg2rad(lat2)) * Math.cos(deg2rad(theta));
      dist = Math.acos(dist);
      dist = rad2deg(dist);
      dist = dist * 60 * 1.1515;
      if (unit == 'K') {
        dist = dist * 1.609344;
      } else if (unit == 'N') {
        dist = dist * 0.8684;
        }
      return (dist);
    }

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  This function converts decimal degrees to radians             :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double deg2rad(double deg) {
      return (deg * Math.PI / 180.0);
    }

    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    /*::  This function converts radians to decimal degrees             :*/
    /*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/
    private double rad2deg(double rad) {
      return (rad * 180.0 / Math.PI);
    }

    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'M') + " Miles\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'K') + " Kilometers\n");
    System.out.println(distance(32.9697, -96.80322, 29.46786, -98.53506, 'N') + " Nautical Miles\n");
Run Code Online (Sandbox Code Playgroud)

  • 工作只是修复单位的报价..它的字符所以单引号不加倍.. (3认同)
  • @Samy 上面的函数给你直线距离。 (3认同)
  • Google 地图显示 12.915700、77.632046、11.665154、78.145657 的 200 公里,其中上述代码显示 149.82 公里。有些东西仍然不正确。 (2认同)

gra*_*der 16

偶然发现这篇 SOF 文章的未来读者。

显然,这个问题是在 2010 年提出的,现在是 2019 年。但它在互联网搜索中很早就出现了。原始问题不打折第三方库的使用(当我写这个答案时)。

public double calculateDistanceInMeters(double lat1, double long1, double lat2,
                                     double long2) {


    double dist = org.apache.lucene.util.SloppyMath.haversinMeters(lat1, long1, lat2, long2);
    return dist;
}
Run Code Online (Sandbox Code Playgroud)

<dependency>
  <groupId>org.apache.lucene</groupId>
  <artifactId>lucene-spatial</artifactId>
  <version>8.2.0</version>
</dependency>
Run Code Online (Sandbox Code Playgroud)

https://mvnrepository.com/artifact/org.apache.lucene/lucene-spatial/8.2.0

请在开始之前阅读有关“SloppyMath”的文档!

https://lucene.apache.org/core/8_2_0/core/org/apache/lucene/util/SloppyMath.html

  • 我认为,如果您可以在代码中将其替换为 28 行,则向某些内容添加依赖项是一种不好的做法,除非您使用该依赖项中的更多内容 (3认同)

小智 12

注意:此解决方案仅适用于短距离.

我尝试使用dommer发布的公式用于应用程序,并发现它在长距离上表现良好,但在我的数据中,我使用的距离非常短,而且dommer的帖子做得很差.我需要速度,更复杂的地理计算效果很好,但速度太慢.所以,在你需要速度的情况下,你所做的所有计算都很短(可能<100m左右).我发现这个小近似值很好.它假设世界是平心的,所以不要长距离使用它,它通过近似给定纬度的单个纬度和经度的距离并以米为单位返回毕达哥拉斯距离.

public class FlatEarthDist {
    //returns distance in meters
    public static double distance(double lat1, double lng1, 
                                      double lat2, double lng2){
     double a = (lat1-lat2)*FlatEarthDist.distPerLat(lat1);
     double b = (lng1-lng2)*FlatEarthDist.distPerLng(lat1);
     return Math.sqrt(a*a+b*b);
    }

    private static double distPerLng(double lat){
      return 0.0003121092*Math.pow(lat, 4)
             +0.0101182384*Math.pow(lat, 3)
                 -17.2385140059*lat*lat
             +5.5485277537*lat+111301.967182595;
    }

    private static double distPerLat(double lat){
            return -0.000000487305676*Math.pow(lat, 4)
                -0.0033668574*Math.pow(lat, 3)
                +0.4601181791*lat*lat
                -1.4558127346*lat+110579.25662316;
    }
}
Run Code Online (Sandbox Code Playgroud)


Sta*_*lov 9

提供了很多很好的答案,但是我发现了一些性能缺陷,所以让我提供一个考虑到性能的版本。每个常数都是预先计算的,并引入 x,y 变量以避免两次计算相同的值。希望能帮助到你

    private static final double r2d = 180.0D / 3.141592653589793D;
    private static final double d2r = 3.141592653589793D / 180.0D;
    private static final double d2km = 111189.57696D * r2d;
    public static double meters(double lt1, double ln1, double lt2, double ln2) {
        double x = lt1 * d2r;
        double y = lt2 * d2r;
        return Math.acos( Math.sin(x) * Math.sin(y) + Math.cos(x) * Math.cos(y) * Math.cos(d2r * (ln1 - ln2))) * d2km;
    }
Run Code Online (Sandbox Code Playgroud)


Chr*_*lor 5

这是一个页面,其中包含用于各种球面计算的 javascript 示例。页面上的第一个应该给你你需要的东西。

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

这是Javascript代码

var R = 6371; // km
var dLat = (lat2-lat1).toRad();
var dLon = (lon2-lon1).toRad(); 
var a = Math.sin(dLat/2) * Math.sin(dLat/2) + 
        Math.cos(lat1.toRad()) * Math.cos(lat2.toRad()) *
        Math.sin(dLon/2) * Math.sin(dLon/2); 
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a)); 
var d = R * c;
Run Code Online (Sandbox Code Playgroud)

'd' 将保持距离。