(转)根据经纬度计算方位距离

(原文地址:http://www.cnblogs.com/leejuan/p/5552460.html)

1.根据两点经纬度计算其间距离,发现有3种公式,结果区别不是很大。

2.根据一点的经纬度与到另外一点的距离、方位角,计算另一点的经纬度,误差不是很大。

  1. /** 
  2.  *  
  3.  * 计算经纬度、距离、方位角 
  4.  *  
  5.  * */  
  6. public class CalculationLogLatDistance {  
  7.     /** 
  8.      * 地球赤道半径(km) 
  9.      * */  
  10.     public final static double EARTH_RADIUS = 6378.137;  
  11.     /** 
  12.      * 地球每度的弧长(km) 
  13.      * */  
  14.     public final static double EARTH_ARC = 111.199;  
  15.   
  16.     /** 
  17.      * 转化为弧度(rad) 
  18.      * */  
  19.     public static double rad(double d) {  
  20.         return d * Math.PI / 180.0;  
  21.     }  
  22.   
  23.     /** 
  24.      * 求两经纬度距离 
  25.      *  
  26.      * @param lon1 
  27.      *            第一点的经度 
  28.      * @param lat1 
  29.      *            第一点的纬度 
  30.      * @param lon2 
  31.      *            第二点的经度 
  32.      * @param lat2 
  33.      *            第二点的纬度 
  34.      * @return 两点距离,单位km 
  35.      * */  
  36.     public static double GetDistanceOne(double lon1, double lat1, double lon2,  
  37.             double lat2) {  
  38.         double r1 = rad(lat1);  
  39.         double r2 = rad(lon1);  
  40.         double a = rad(lat2);  
  41.         double b = rad(lon2);  
  42.         double s = Math.acos(Math.cos(r1) * Math.cos(a) * Math.cos(r2 - b)  
  43.                 + Math.sin(r1) * Math.sin(a))  
  44.                 * EARTH_RADIUS;  
  45.         return s;  
  46.     }  
  47.   
  48.     /** 
  49.      * 求两经纬度距离(google maps源码中) 
  50.      *  
  51.      * @param lon1 
  52.      *            第一点的经度 
  53.      * @param lat1 
  54.      *            第一点的纬度 
  55.      * @param lon2 
  56.      *            第二点的经度 
  57.      * @param lat2 
  58.      *            第二点的纬度 
  59.      * @return 两点距离,单位km 
  60.      * */  
  61.     public static double GetDistanceTwo(double lon1, double lat1, double lon2,  
  62.             double lat2) {  
  63.         double radLat1 = rad(lat1);  
  64.         double radLat2 = rad(lat2);  
  65.         double a = radLat1 - radLat2;  
  66.         double b = rad(lon1) - rad(lon2);  
  67.         double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)  
  68.                 + Math.cos(radLat1) * Math.cos(radLat2)  
  69.                 * Math.pow(Math.sin(b / 2), 2)));  
  70.         s = s * EARTH_RADIUS;  
  71.         return s;  
  72.     }  
  73.   
  74.     /** 
  75.      * 求两经纬度距离 
  76.      *  
  77.      * @param lon1 
  78.      *            第一点的经度 
  79.      * @param lat1 
  80.      *            第一点的纬度 
  81.      * @param lon2 
  82.      *            第二点的经度 
  83.      * @param lat2 
  84.      *            第二点的纬度 
  85.      * @return 两点距离,单位km 
  86.      * */  
  87.     public static double GetDistanceThree(double lon1, double lat1,  
  88.             double lon2, double lat2) {  
  89.         double radLat1 = rad(lat1);  
  90.         double radLat2 = rad(lat2);  
  91.         double radLon1 = rad(lon1);  
  92.         double radLon2 = rad(lon2);  
  93.         if (radLat1 < 0)  
  94.             radLat1 = Math.PI / 2 + Math.abs(radLat1);// south  
  95.         if (radLat1 > 0)  
  96.             radLat1 = Math.PI / 2 - Math.abs(radLat1);// north  
  97.         if (radLon1 < 0)  
  98.             radLon1 = Math.PI * 2 - Math.abs(radLon1);// west  
  99.         if (radLat2 < 0)  
  100.             radLat2 = Math.PI / 2 + Math.abs(radLat2);// south  
  101.         if (radLat2 > 0)  
  102.             radLat2 = Math.PI / 2 - Math.abs(radLat2);// north  
  103.         if (radLon2 < 0)  
  104.             radLon2 = Math.PI * 2 - Math.abs(radLon2);// west  
  105.         double x1 = Math.cos(radLon1) * Math.sin(radLat1);  
  106.         double y1 = Math.sin(radLon1) * Math.sin(radLat1);  
  107.         double z1 = Math.cos(radLat1);  
  108.   
  109.         double x2 = Math.cos(radLon2) * Math.sin(radLat2);  
  110.         double y2 = Math.sin(radLon2) * Math.sin(radLat2);  
  111.         double z2 = Math.cos(radLat2);  
  112.   
  113.         double d = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)  
  114.                 + Math.pow((z1 - z2), 2);  
  115.         // // 余弦定理求夹角  
  116.         // double theta = Math.acos((2 - d) / 2);  
  117.   
  118.         d = Math.pow(EARTH_RADIUS, 2) * d;  
  119.         // //余弦定理求夹角  
  120.         double theta = Math.acos((2 * Math.pow(EARTH_RADIUS, 2) - d)  
  121.                 / (2 * Math.pow(EARTH_RADIUS, 2)));  
  122.   
  123.         double dist = theta * EARTH_RADIUS;  
  124.         return dist;  
  125.     }  
  126.   
  127.     /** 
  128.      * 求两经纬度方向角 
  129.      *  
  130.      * @param lon1 
  131.      *            第一点的经度 
  132.      * @param lat1 
  133.      *            第一点的纬度 
  134.      * @param lon2 
  135.      *            第二点的经度 
  136.      * @param lat2 
  137.      *            第二点的纬度 
  138.      * @return 方位角,角度(单位:°) 
  139.      * */  
  140.     public static double GetAzimuth(double lon1, double lat1, double lon2,  
  141.             double lat2) {  
  142.         lat1 = rad(lat1);  
  143.         lat2 = rad(lat2);  
  144.         lon1 = rad(lon1);  
  145.         lon2 = rad(lon2);  
  146.         double azimuth = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1)  
  147.                 * Math.cos(lat2) * Math.cos(lon2 - lon1);  
  148.         azimuth = Math.sqrt(1 - azimuth * azimuth);  
  149.         azimuth = Math.cos(lat2) * Math.sin(lon2 - lon1) / azimuth;  
  150.         azimuth = Math.asin(azimuth) * 180 / Math.PI;  
  151.         if (Double.isNaN(azimuth)) {  
  152.             if (lon1 < lon2) {  
  153.                 azimuth = 90.0;  
  154.             } else {  
  155.                 azimuth = 270.0;  
  156.             }  
  157.         }  
  158.         return azimuth;  
  159.     }  
  160.   
  161.     /** 
  162.      * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度(计算结果有误) 
  163.      *  
  164.      * @param lon1 
  165.      *            A的经度 
  166.      * @param lat1 
  167.      *            A的纬度 
  168.      * @param distance 
  169.      *            AB距离(单位:米) 
  170.      * @param azimuth 
  171.      *            AB方位角 
  172.      * @return B的经纬度 
  173.      * */  
  174.     public static String GetOtherPoint(double lon1, double lat1,  
  175.             double distance, double azimuth) {  
  176.         azimuth = rad(azimuth);  
  177.         double ab = distance / EARTH_ARC;// AB间弧线长  
  178.         ab = rad(ab);  
  179.         double Lat = Math.asin(Math.sin(lat1) * Math.cos(ab) + Math.cos(lat1)  
  180.                 * Math.sin(ab) * Math.cos(azimuth));  
  181.         double Lon = lon1  
  182.                 + Math.asin(Math.sin(azimuth) * Math.sin(ab) / Math.cos(Lat));  
  183.         System.out.println(Lon + ”,” + Lat);  
  184.   
  185.         double a = Math.acos(Math.cos(90 - lon1) * Math.cos(ab)  
  186.                 + Math.sin(90 - lon1) * Math.sin(ab) * Math.cos(azimuth));  
  187.         double C = Math.asin(Math.sin(ab) * Math.sin(azimuth) / Math.sin(a));  
  188.         System.out.println(”c=” + C);  
  189.         double lon2 = lon1 + C;  
  190.         double lat2 = 90 - a;  
  191.         return lon2 + “,” + lat2;  
  192.     }  
  193.   
  194.     /** 
  195.      * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度 
  196.      *  
  197.      * @param lon1 
  198.      *            A的经度 
  199.      * @param lat1 
  200.      *            A的纬度 
  201.      * @param distance 
  202.      *            AB距离(单位:米) 
  203.      * @param azimuth 
  204.      *            AB方位角 
  205.      * @return B的经纬度 
  206.      * */  
  207.     public static String ConvertDistanceToLogLat(double lng1, double lat1,  
  208.             double distance, double azimuth) {  
  209.         azimuth = rad(azimuth);  
  210.         // 将距离转换成经度的计算公式  
  211.         double lon = lng1 + (distance * Math.sin(azimuth))  
  212.                 / (EARTH_ARC * Math.cos(rad(lat1)));  
  213.         // 将距离转换成纬度的计算公式  
  214.         double lat = lat1 + (distance * Math.cos(azimuth)) / EARTH_ARC;  
  215.         return lon + “,” + lat;  
  216.     }  
  217.   
  218.     public static void main(String[] args) {  
  219.         double lon1 = 121.469156;  
  220.         double lat1 = 31.232307;  
  221.         double lon2 = 121.469156;  
  222.         double lat2 = 31.233205;  
  223.         double distance = GetDistanceTwo(lon1, lat1, lon2, lat2);  
  224.         double azimuth = GetAzimuth(lon1, lat1, lon2, lat2);  
  225.         System.out.println(”经纬度为(“ + lon1 + “,” + lat1 + “)的点与经纬度为(“ + lon2  
  226.                 + ”,” + lat2 + “)相距:” + distance + “千米,” + “方位角:” + azimuth  
  227.                 + ”°”);  
  228.         System.out.println(”距经纬度为(“ + lon1 + “,” + lat1 + “)的点” + distance  
  229.                 + ”千米,方位角为” + azimuth + “°的另一点经纬度为(“  
  230.                 + ConvertDistanceToLogLat(lon1, lat1, distance, azimuth) + ”)”);  
  231.     }  
  232. }  
/**
 * 
 * 计算经纬度、距离、方位角
 * 
 * */
public class CalculationLogLatDistance {
    /**
     * 地球赤道半径(km)
     * */
    public final static double EARTH_RADIUS = 6378.137;
    /**
     * 地球每度的弧长(km)
     * */
    public final static double EARTH_ARC = 111.199;

    /**
     * 转化为弧度(rad)
     * */
    public static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 求两经纬度距离
     * 
     * @param lon1
     *            第一点的经度
     * @param lat1
     *            第一点的纬度
     * @param lon2
     *            第二点的经度
     * @param lat2
     *            第二点的纬度
     * @return 两点距离,单位km
     * */
    public static double GetDistanceOne(double lon1, double lat1, double lon2,
            double lat2) {
        double r1 = rad(lat1);
        double r2 = rad(lon1);
        double a = rad(lat2);
        double b = rad(lon2);
        double s = Math.acos(Math.cos(r1) * Math.cos(a) * Math.cos(r2 - b)
                + Math.sin(r1) * Math.sin(a))
                * EARTH_RADIUS;
        return s;
    }

    /**
     * 求两经纬度距离(google maps源码中)
     * 
     * @param lon1
     *            第一点的经度
     * @param lat1
     *            第一点的纬度
     * @param lon2
     *            第二点的经度
     * @param lat2
     *            第二点的纬度
     * @return 两点距离,单位km
     * */
    public static double GetDistanceTwo(double lon1, double lat1, double lon2,
            double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double a = radLat1 - radLat2;
        double b = rad(lon1) - rad(lon2);
        double s = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2)
                + Math.cos(radLat1) * Math.cos(radLat2)
                * Math.pow(Math.sin(b / 2), 2)));
        s = s * EARTH_RADIUS;
        return s;
    }

    /**
     * 求两经纬度距离
     * 
     * @param lon1
     *            第一点的经度
     * @param lat1
     *            第一点的纬度
     * @param lon2
     *            第二点的经度
     * @param lat2
     *            第二点的纬度
     * @return 两点距离,单位km
     * */
    public static double GetDistanceThree(double lon1, double lat1,
            double lon2, double lat2) {
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        double radLon1 = rad(lon1);
        double radLon2 = rad(lon2);
        if (radLat1 < 0)
            radLat1 = Math.PI / 2 + Math.abs(radLat1);// south
        if (radLat1 > 0)
            radLat1 = Math.PI / 2 - Math.abs(radLat1);// north
        if (radLon1 < 0)
            radLon1 = Math.PI * 2 - Math.abs(radLon1);// west
        if (radLat2 < 0)
            radLat2 = Math.PI / 2 + Math.abs(radLat2);// south
        if (radLat2 > 0)
            radLat2 = Math.PI / 2 - Math.abs(radLat2);// north
        if (radLon2 < 0)
            radLon2 = Math.PI * 2 - Math.abs(radLon2);// west
        double x1 = Math.cos(radLon1) * Math.sin(radLat1);
        double y1 = Math.sin(radLon1) * Math.sin(radLat1);
        double z1 = Math.cos(radLat1);

        double x2 = Math.cos(radLon2) * Math.sin(radLat2);
        double y2 = Math.sin(radLon2) * Math.sin(radLat2);
        double z2 = Math.cos(radLat2);

        double d = Math.pow((x1 - x2), 2) + Math.pow((y1 - y2), 2)
                + Math.pow((z1 - z2), 2);
        // // 余弦定理求夹角
        // double theta = Math.acos((2 - d) / 2);

        d = Math.pow(EARTH_RADIUS, 2) * d;
        // //余弦定理求夹角
        double theta = Math.acos((2 * Math.pow(EARTH_RADIUS, 2) - d)
                / (2 * Math.pow(EARTH_RADIUS, 2)));

        double dist = theta * EARTH_RADIUS;
        return dist;
    }

    /**
     * 求两经纬度方向角
     * 
     * @param lon1
     *            第一点的经度
     * @param lat1
     *            第一点的纬度
     * @param lon2
     *            第二点的经度
     * @param lat2
     *            第二点的纬度
     * @return 方位角,角度(单位:°)
     * */
    public static double GetAzimuth(double lon1, double lat1, double lon2,
            double lat2) {
        lat1 = rad(lat1);
        lat2 = rad(lat2);
        lon1 = rad(lon1);
        lon2 = rad(lon2);
        double azimuth = Math.sin(lat1) * Math.sin(lat2) + Math.cos(lat1)
                * Math.cos(lat2) * Math.cos(lon2 - lon1);
        azimuth = Math.sqrt(1 - azimuth * azimuth);
        azimuth = Math.cos(lat2) * Math.sin(lon2 - lon1) / azimuth;
        azimuth = Math.asin(azimuth) * 180 / Math.PI;
        if (Double.isNaN(azimuth)) {
            if (lon1 < lon2) {
                azimuth = 90.0;
            } else {
                azimuth = 270.0;
            }
        }
        return azimuth;
    }

    /**
     * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度(计算结果有误)
     * 
     * @param lon1
     *            A的经度
     * @param lat1
     *            A的纬度
     * @param distance
     *            AB距离(单位:米)
     * @param azimuth
     *            AB方位角
     * @return B的经纬度
     * */
    public static String GetOtherPoint(double lon1, double lat1,
            double distance, double azimuth) {
        azimuth = rad(azimuth);
        double ab = distance / EARTH_ARC;// AB间弧线长
        ab = rad(ab);
        double Lat = Math.asin(Math.sin(lat1) * Math.cos(ab) + Math.cos(lat1)
                * Math.sin(ab) * Math.cos(azimuth));
        double Lon = lon1
                + Math.asin(Math.sin(azimuth) * Math.sin(ab) / Math.cos(Lat));
        System.out.println(Lon + "," + Lat);

        double a = Math.acos(Math.cos(90 - lon1) * Math.cos(ab)
                + Math.sin(90 - lon1) * Math.sin(ab) * Math.cos(azimuth));
        double C = Math.asin(Math.sin(ab) * Math.sin(azimuth) / Math.sin(a));
        System.out.println("c=" + C);
        double lon2 = lon1 + C;
        double lat2 = 90 - a;
        return lon2 + "," + lat2;
    }

    /**
     * 已知一点经纬度A,和与另一点B的距离和方位角,求B的经纬度
     * 
     * @param lon1
     *            A的经度
     * @param lat1
     *            A的纬度
     * @param distance
     *            AB距离(单位:米)
     * @param azimuth
     *            AB方位角
     * @return B的经纬度
     * */
    public static String ConvertDistanceToLogLat(double lng1, double lat1,
            double distance, double azimuth) {
        azimuth = rad(azimuth);
        // 将距离转换成经度的计算公式
        double lon = lng1 + (distance * Math.sin(azimuth))
                / (EARTH_ARC * Math.cos(rad(lat1)));
        // 将距离转换成纬度的计算公式
        double lat = lat1 + (distance * Math.cos(azimuth)) / EARTH_ARC;
        return lon + "," + lat;
    }

    public static void main(String[] args) {
        double lon1 = 121.469156;
        double lat1 = 31.232307;
        double lon2 = 121.469156;
        double lat2 = 31.233205;
        double distance = GetDistanceTwo(lon1, lat1, lon2, lat2);
        double azimuth = GetAzimuth(lon1, lat1, lon2, lat2);
        System.out.println("经纬度为(" + lon1 + "," + lat1 + ")的点与经纬度为(" + lon2
                + "," + lat2 + ")相距:" + distance + "千米," + "方位角:" + azimuth
                + "°");
        System.out.println("距经纬度为(" + lon1 + "," + lat1 + ")的点" + distance
                + "千米,方位角为" + azimuth + "°的另一点经纬度为("
                + ConvertDistanceToLogLat(lon1, lat1, distance, azimuth) + ")");
    }
}


根据两点的经纬度计算方位距离是一个常见的问题,可以使用C++中的数学库来解决。以下是计算两点之间距离方位角的示例代码: ```c++ #include <iostream> #include <cmath> using namespace std; const double PI = 3.14159265358979323846; const double EARTH_RADIUS = 6378.137; // 地球半径,单位为千米 double rad(double d) { return d * PI / 180.0; } double getDistance(double lng1, double lat1, double lng2, double lat2) { double radLat1 = rad(lat1); double radLat2 = rad(lat2); double a = radLat1 - radLat2; double b = rad(lng1) - rad(lng2); double s = 2 * asin(sqrt(pow(sin(a / 2), 2) + cos(radLat1) * cos(radLat2) * pow(sin(b / 2), 2))); s *= EARTH_RADIUS; return s; } double getAzimuth(double lng1, double lat1, double lng2, double lat2) { double radLat1 = rad(lat1); double radLat2 = rad(lat2); double radLng1 = rad(lng1); double radLng2 = rad(lng2); double y = sin(radLng2 - radLng1) * cos(radLat2); double x = cos(radLat1) * sin(radLat2) - sin(radLat1) * cos(radLat2) * cos(radLng2 - radLng1); double brng = atan2(y, x); brng = brng * 180 / PI; if (brng < 0) { brng += 360; } return brng; } int main() { double lng1 = 116.388171; double lat1 = 39.935961; double lng2 = 116.397458; double lat2 = 39.908722; double distance = getDistance(lng1, lat1, lng2, lat2); double azimuth = getAzimuth(lng1, lat1, lng2, lat2); cout << "两点之间的距离为:" << distance << "千米" << endl; cout << "两点之间的方位角为:" << azimuth << "度" << endl; return 0; } ``` 其中,getDistance函数用于计算两点之间的距离,getAzimuth函数用于计算两点之间的方位角。需要注意的是,这里使用的是WGS84坐标系,如果需要使用其他坐标系,需要进行换。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值