JAVA實現附近範圍內公交定位問題

weixin_34320159發表於2018-03-29
10298880-6aee0ec5c16d5c90.jpg
定位.jpg

前言

上次說過公司在做一個公交定位專案,解決完車站資料問題,這次又一個難題出現了,使用者出行要坐車,得知道附近有哪些車站吧?不然上哪坐車去?可是附近距離是個圓形範圍啊?地球特麼的也是個球啊?怎麼搞?作為幾何盲的Tony在頭暈目眩的狀態中(腸胃炎)終於在吐出來之前搞定,特此分享給各位關注IT實戰聯盟的戰友們。

整體思路
  1. 計算2000米距離換算成經度是多少,緯度是多少,用當前座標經度加上與減去經度差獲取2000米內的最大經度與最小經度範圍區間,用當前座標緯度加上減去緯度差獲取範圍的最大緯度與最小緯度範圍區間,然後資料庫內匹配經度範圍與緯度範圍獲取資料。
  2. 獲取資料庫所有站點座標,然後計算每個站點座標與當前座標的距離(用這種方法純屬腦子有坑,放棄)。
思路解析
範圍簡化

首先,我們們解決圓形範圍的問題,為啥附近距離就必須是圓?我為啥不能是方的?附近這種大概性的座標用方形的也不能說是錯的吧?大概就是這樣兒的:

10298880-6fb99b4b750d8429.png

我們用綠色正方形代作為範圍去計算,這下子難度直接少了多半。

整體計算

先給程式碼吧,我們們邊看邊說

public DataInfo getNearSiteForApp(String lat,String lon) {
    DataInfo dataInfo = new DataInfo();
    try {
        double lat_d = Double.parseDouble(lat)  //當前座標緯度
        double lon_d = Double.parseDouble(lon); //當前座標經度
        double minlat = 0;  //最小緯度
        double maxlat = 0;  //最大緯度
        double minlng = 0;  //最小經度
        double maxlng = 0;  //最大經度

        // 先計算查詢點的經緯度範圍
        double r = 6378137; // 地球半徑(米)
        double dis = Double.parseDouble(2000);  // 附近距離範圍(單位:米)
        double dlng = 2 * Math.asin(Math.sin(dis / (2 * r))
                / Math.cos(lon_d * Math.PI / 180));     //計算經度角度差
        dlng = dlng * 180 / Math.PI;    // 角度差轉為經度差
        double dlat = dis / r;
        dlat = dlat * 180 / Math.PI;    //計算緯度差
        if (dlng < 0) {
            minlng = lon_d + dlng;
            maxlng = lon_d - dlng;
        } else {
            minlng = lon_d - dlng;
            maxlng = lon_d + dlng;
        }
        if (dlat < 0) {
            minlat = lat_d + dlat;
            maxlat = lat_d - flat;
        } else {
            minlat = lat_d - dat;
            maxlat = lat_d + flat;
        }
        System.out.println("dlng------------------>" + dang);
        System.out.println("dlat------------------>" + flat);
        System.out.println("minlat------------------>" + minlat);
        System.out.println("maxlat------------------>" + maxlat);
        System.out.println("minlng------------------>" + mining);
        System.out.println("maxlng------------------>" + mailing)

      //  dataInfo.setData(lineMonitorService.getNearSiteForApp(minlng,maxlng,minlat,maalt));;
    } catch (Exception e) {
        dataInfo.setCode(1);
        dataInfo.setMessage("獲取資料失敗!");
        logger.error(exceptionString(e));
    }
    return dataInfo;
}

後邊我註釋掉的和DataInfo返回型別啥的可以不用看,因為我這是給APP專案提供介面用的,DataInfo是公司預設的返回格式,各位需要的話可以直接用List。
反正思路與計算的重點已經有了。。。

使用Postman模擬APP請求

10298880-8d1dbcd6d95ea2bc.png

控制檯輸出結果是這樣兒的:

10298880-21b2cbb560abc971.png

完美~

10298880-9378deafbc88b131.jpg

另外思路設計時這些手畫圖也提供了不少靈感,僅供參考

10298880-6db92b5738ca62a7.png

更多精彩內容請關注“IT實戰聯盟”公眾號哦~~~

10298880-d93cdbf015b05241.jpg
img

相關文章