最全JAVA地球上两点间的距离算法!包含球体、椭球体、百度算法

  • Post author:
  • Post category:java


在网上浏览了很多根据经纬度去计算两点间距离的帖子和书籍。今天有时间整理一下!希望能帮助浏览本贴的程序员们!


第一种:百度算法(java版)网上其他博客也有

Python版



public static double max(double a, double b) {




if (a > b)



return a;



return b;



}



public static double min(double a, double c) {




if (a > c)



return c;



return a;



}



public static double lw(double a, double b, double c) {




// b != n && (a = Math.max(a, b));



// c != n && (a = Math.min(a, c));



a = max(a, b);



a = min(a, c);



return a;



}



public static double ew(double a, double b, double c) {




while (a > c) {




a = a – (c – b);



}



while (a < b) {




a = a + (c – b);



}



return a;



}



public static double oi(double a) {




return Math.PI * a / 180;



}



public static double Td(double a, double b, double c, double d) {




return 6370996.81 * Math.acos(Math.sin(c) * Math.sin(d) + Math.cos(c) * Math.cos(d) * Math.cos(b – a));



}



public static double Wv(Point a, Point b) {




double ew = ew(a.getY(), -180, 180);



double lw = lw(a.getX(), -74, 74);



double ew2 = ew(b.getY(), -180, 180);



double lw2 = lw(b.getX(), -74, 74);



return Td(oi(ew), oi(ew2), oi(lw), oi(lw2));



}



public static double getDistance(Point a, Point b) {




double c = Wv(a, b);



return c / 1000;



}




第二种:椭球体算法(最为精确)



public static String BLANK = “”;



public static String ZERO = “0”;



private static double EARTH_RADIUS = 6378.137;



/**



* VincentyConstants Constants for Vincenty functions.



*/



public static double vincentyConstantA = 6378137;



public static double vincentyConstantB = 6356752.314245;



public static double vincentyConstantF = 1 / 298.257223563;



// 根据两个点坐标计算它们之间的距离(按照圆球体计算,粗略计算)



public static double getDistanceBySphere(double y1, double x1, double y2, double x2) {




double rady1 = rad(y1);



double rady2 = rad(y2);



double a = rady1 – rady2;



double b = rad(x1) – rad(x2);



double s = 2 * Math.asin(Math



.sqrt(Math.pow(Math.sin(a / 2), 2) + Math.cos(rady1) * Math.cos(rady2) * Math.pow(Math.sin(b / 2), 2)));



s = s * EARTH_RADIUS;



s = (double) (Math.round(s * 10000) / 10000);



return s;



}



// 转换弧度



private static double rad(double d) {




return d * Math.PI / 180.0;



}



/**



* Given two objects representing points with geographic coordinates, this



* calculates the distance between those points on the surface of an



* ellipsoid. 按照椭球体计算,精确计算



*



* Returns: The distance (in km) between the two input points as measured on



* an ellipsoid. Note that the input point objects must be in geographic



* coordinates (decimal degrees) and the return distance is in kilometers.



*/



public static double distVincenty(double y1, double x1, double y2, double x2) {




double a = vincentyConstantA;



double b = vincentyConstantB;



double f = vincentyConstantF;



double L = degtoRad(x2 – x1);



double U1 = Math.atan((1 – f) * Math.tan(degtoRad(y1)));



double U2 = Math.atan((1 – f) * Math.tan(degtoRad(y2)));



double sinU1 = Math.sin(U1);



double cosU1 = Math.cos(U1);



double sinU2 = Math.sin(U2);



double cosU2 = Math.cos(U2);



double lambda = L;



double lambdaP = 2 * Math.PI;



double iterLimit = 20;



double sinLambda = 0.0d;



double cosLambda = 0.0d;



double sinSigma = 0.0d;



double cosSigma = 0.0d;



double sigma = 0.0d;



double alpha = 0.0d;



double cosSqAlpha = 0.0d;



double cos2SigmaM = 0.0d;



double C = 0.0d;



while (Math.abs(lambda – lambdaP) > 1e-12 && –iterLimit > 0) {




sinLambda = Math.sin(lambda);



cosLambda = Math.cos(lambda);



sinSigma = Math.sqrt((cosU2 * sinLambda) * (cosU2 * sinLambda)



+ (cosU1 * sinU2 – sinU1 * cosU2 * cosLambda) * (cosU1 * sinU2 – sinU1 * cosU2 * cosLambda));



if (sinSigma == 0) {




return 0; // co-incident points



}



cosSigma = sinU1 * sinU2 + cosU1 * cosU2 * cosLambda;



sigma = Math.atan2(sinSigma, cosSigma);



alpha = Math.asin(cosU1 * cosU2 * sinLambda / sinSigma);



cosSqAlpha = Math.cos(alpha) * Math.cos(alpha);



cos2SigmaM = cosSigma – 2 * sinU1 * sinU2 / cosSqAlpha;



C = f / 16 * cosSqAlpha * (4 + f * (4 – 3 * cosSqAlpha));



lambdaP = lambda;



lambda = L + (1 – C) * f * Math.sin(alpha)



* (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)));



}



if (iterLimit == 0) {




return 0.0; // formula failed to converge



}



double uSq = cosSqAlpha * (a * a – b * b) / (b * b);



double A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 – 175 * uSq)));



double B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 – 47 * uSq)));



double deltaSigma = B * sinSigma * (cos2SigmaM + B / 4 * (cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM)



– B / 6 * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)));



double s = b * A * (sigma – deltaSigma);



// double d = Number(s.toFixed(3))/1000; // round to 1mm precision



double d = s / 1000; // round to 1mm precision



return d;



}



/**



* Convert degrees to radian



*



* @param val



*            Value to convert



*/



public static double degtoRad(double val) {




return val * Math.PI / 180;



}




第三种:纯球体近似计算






  1. private




    static




    double


    EARTH_RADIUS =


    6378.137


    ;



  2. private




    static




    double


    rad(


    double


    d)


  3. {


  4. return


    d * Math.PI /


    180.0


    ;


  5. }



  6. public




    static




    double


    GetDistance(


    double


    lat1,


    double


    lng1,


    double


    lat2,


    double


    lng2)


  7. {


  8. double


    radLat1 = rad(lat1);



  9. double


    radLat2 = rad(lat2);



  10. double


    a = radLat1 – radLat2;



  11. double


    b = rad(lng1) – rad(lng2);



  12. double


    s =


    2


    * Math.asin(Math.sqrt(Math.pow(Math.sin(a/


    2


    ),


    2


    ) +


  13. Math.cos(radLat1)*Math.cos(radLat2)*Math.pow(Math.sin(b/

    2


    ),


    2


    )));


  14. s = s * EARTH_RADIUS;

  15. s = Math.round(s *

    10000


    ) /


    10000


    ;



  16. return


    s;

大家使用时请注意单位:km;



版权声明:本文为weixin_35726519原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。