天天看點

Java根據兩點經緯度計算距離

這些經緯線是怎樣定出來的呢?地球是在不停地繞地軸旋轉(地軸是一根通過地球南北兩極和地球中心的

假想線),在地球中腰畫一個與地軸垂直的大圓圈,使圈上的每一點都和南北兩極的距離相等,這個圓圈

就叫作“赤道”。在赤道的南北兩邊,畫出許多和赤道平行的圓圈,就是“緯圈”;構成這些圓圈的線段,

叫做緯線。我們把赤道定為緯度零度,向南向北各為90度,在赤道以南的叫南緯,在赤道以北的叫北緯。

北極就是北緯90度,南極就是南緯90度。緯度的高低也标志着氣候的冷熱,如赤道和低緯度地地區無冬,

兩極和高緯度地區無夏,中緯度地區四季分明。

其次,從北極點到南極點,可以畫出許多南北方向的與地球赤道垂直的大圓圈,這叫作“經圈”;構成這

些圓圈的線段,就叫經線。公元1884平面坐标圖年,國際上規定以通過英國倫敦近郊的格林尼治天文台的

經線作為計算經度的起點,即經度零度零分零秒,也稱“本初子午線”。在它東面的為東經,共180度;

在它西面的為西經,共180度。因為地球是圓的,是以東經180度和西經180度的經線是同一條經線。各國

公定180度經線為“國際日期變更線”。為了避免同一地區使用兩個不同的日期,國際日期變線在遇陸地時

略有偏離。

每一經度和緯度還可以再細分為60分,每一分再分為60秒以及秒的小數。利用經緯線,我們就可以确定

地球上每一個地方的具體位置,并且把它在地圖或地球儀上表示出來。例如問北京的經緯度是多少?我們

很容易從地圖上查出來是東經116度24分,北緯39度54分。在大海中航行的船隻,隻要把所在地的經度測

出來,就可以确定船在海洋中的位置和前進方向。 緯度共有90度。赤道為0度,向兩極排列,圈子越小,

度數越大。

橫線是緯度,豎線是經度。

當然可以計算,四元二次方程。

經度和緯度都是一種角度。經度是個兩面角,是兩個經線平面的夾角。因所有經線都是一樣長,為了度量

經度選取一個起點面,經1884年國際會議協商,決定以通過英國倫敦近郊、泰晤士河南岸的格林尼治皇家

天文台(舊址)的一台主要子午儀十字絲的那條經線為起始經線,稱為本初子午線。本初子午線平面是起

點面,終點面是本地經線平面。某一點的經度,就是該點所在的經線平面與本初子午線平面間的夾角。在

赤道上度量,自本初子午線平面作為起點面,分别往東往西度量,往東量值稱為東經度,往西量值稱為西

經度。由此可見,一地的經度是該地對于本初子午線的方向和角距離。本初子午線是0°經度,東經度的最

大值為180°,西經度的最大值為180°,東、西經180°經線是同一根經線,是以不分東經或西經,而統稱

180°經線。

緯度是個線面角。起點面是赤道平面,線是本地的地面法線。所謂法線,即垂直于參考扁球體表面的線。

某地的緯度就是該地的法線與赤道平面之間的夾角。緯度在本地經線上度量,由赤道向南、北度量,向北

量值稱為北緯度,向南量值稱為南緯度。由此可見,一地的緯度是該地對于赤道的方向和角距離。赤道是

0°緯線,北緯度的最大值為90°,即北極點;南緯度的最大值為90°,即南極點。

經緯度互換

度換算成度分秒

度(DDD):E 108.90593度 N 34.21630度

如 何将度(DDD):: 108.90593度換算成度分秒(DMS)東經E 108度54分22.2秒?轉換方法是将108.90593整數位不變取108(度),用0.9059360=54.3558,取整數位 54(分),0.355860=21.348再取整數位21(秒),故轉化為108度54分21秒.

同樣将度分秒(DMS):東經E 108度54分22.2秒 換算成度(DDD)的方法如下:108度54分22.2秒=108+(54/60)+(22.2/3600)=108.90616度

因為計算時小數位保留的原因,導緻正反計算存在一定誤差,但誤差影響不是很大。1秒的誤差就是幾米的樣子。GPS車友可以用上述方法換算成自己需要的機關坐标。

關于經緯度十進制表示法

對于兩個點,在緯度相等的情況下:

經度每隔0.00001度,距離相差約1米;每隔0.0001度,距離相差約10米;每隔0.001度,距離相差約100米;每隔0.01度,距離相差約1000米;每隔0.1度,距離相差約10000米。

對于兩個點,在經度相等的情況下:

緯度每隔0.00001度,距離相差約1.1米;每隔0.0001度,距離相差約11米;每隔0.001度,距離相差約111米;每隔0.01度,距離相差約1113米;每隔0.1度,距離相差約11132米。

根據地球上任意兩點的經緯度計算兩點間的距離

Java根據兩點經緯度計算距離

方 法1:由于地球是橢球體,這個太難算了,如果假設地球是球體,可以使用以下公式:設地球上某點的經度為A,緯度為B, 則這點的空間坐标是 x=cos(B)cos(A) y=cos(B)sin(A) z=sin(B) 設地球上兩點的空間坐标分别為(x1,y1,z1),(x2,y2,z2) 則它們的夾角為 C=acos(x1x2+y1y2+z1z2),C是角度 則兩地距離為 C/180pi*R,其中R為地球平均半徑6371 誤差不超過1%

地 球是一個近乎标準的橢球體,它的赤道半徑為6378.140千米,極半徑為 6356.755千米,平均半徑6371.004千米。如果我們假設地球是一個完美的球體,那麼它的半徑就是地球的平均半徑,記為R。如果以0度經線為基 準,那麼根據地球表面任意兩點的經緯度就可以計算出這兩點間的地表距離(這裡忽略地球表面地形對計算帶來的誤差,僅僅是理論上的估算值)。設第一點A的經 緯度為(LonA, LatA),第二點B的經緯度為(LonB, LatB),按照0度經線的基準,東經取經度的正值(Longitude),西經取經度負值(-Longitude),北緯取90-緯度值(90- Latitude),南緯取90+緯度值(90+Latitude),則經過上述處理過後的兩點被計為(MLonA, MLatA)和(MLonB, MLatB)。那麼根據三角推導,可以得到計算兩點距離的如下公式:

C = sin(MLatA)sin(MLatB)cos(MLonA-MLonB) + cos(MLatA)*cos(MLatB)

Distance = RArccos(C)Pi/180

這裡,R和Distance機關是相同,如果是采用6371.004千米作為半徑,那麼Distance就是千米為機關,如果要使用其他機關,比如mile,還需要做機關換算,1千米=0.621371192mile

如果僅對經度作正負的處理,而不對緯度作90-Latitude(假設都是北半球,南半球隻有澳洲具有應用意義)的處理,那麼公式将是:

C = sin(LatA)sin(LatB) + cos(LatA)cos(LatB)*cos(MLonA-MLonB)

以上通過簡單的三角變換就可以推出。

如果三角函數的輸入和輸出都采用弧度值,那麼公式還可以寫作:

C = sin(LatAPi/180)sin(LatBPi/180) + cos(LatAPi/180)cos(LatBPi/180)cos((MLonA-MLonB)Pi/180)

也就是:

C = sin(LatA/57.2958)sin(LatB/57.2958) + cos(LatA/57.2958)cos(LatB/57.2958)*cos((MLonA-MLonB)/57.2958)

Distance = RArccos(C) = 6371.004Arccos(C)

kilometer = 0.6213711926371.004Arccos(C)

mile = 3958.758349716768*Arccos(C) mile

/**

  • Copyright (C), 2015-2018, 亞信(中國)科技有限公司
  • FileName: a
  • Author: zhoumoxuan
  • Date: 10/8/18 10:35 AM
  • Description: e
  • History:
  • 作者姓名 修改時間 版本号 描述

    */

package com.asiainfo.utils;

  • 〈一句話功能簡述〉
  • 〈e〉

    *

  • @author zhoumoxuan
  • @create 10/8/18
  • @since 1.0.0

public class a {

private static final  double EARTH_RADIUS = 6378137;//赤道半徑(機關m)  

/**
 * 轉化為弧度(rad) 
 * */
private static double rad(double d)
{
    return d * Math.PI / 180.0;
}

/**
 * 基于餘弦定理求兩經緯度距離 
 * @param lon1 第一點的精度 
 * @param lat1 第一點的緯度 
 * @param lon2 第二點的精度 
 * @param lat3 第二點的緯度 
 * @return 傳回的距離,機關km 
 * */
public static double LantitudeLongitudeDist(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 = EARTH_RADIUS * Math.cos(radLon1) * Math.sin(radLat1);
    double y1 = EARTH_RADIUS * Math.sin(radLon1) * Math.sin(radLat1);
    double z1 = EARTH_RADIUS * Math.cos(radLat1);

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

    double d = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)+ (z1 - z2) * (z1 - z2));
    //餘弦定理求夾角  
    double theta = Math.acos((EARTH_RADIUS * EARTH_RADIUS + EARTH_RADIUS * EARTH_RADIUS - d * d) / (2 * EARTH_RADIUS * EARTH_RADIUS));
    double dist = theta * EARTH_RADIUS;
    return dist;
}           

}

坐​标​與​距​離​換​算​,​經​測​試​,​相​差​一​米

import java.io.BufferedReader;

import java.io.IOException;

import java.io.InputStreamReader;

import java.math.BigDecimal;

import java.net.URL;

import java.net.URLEncoder;

import java.util.HashMap;

import java.util.Map;

import org.apache.commons.lang.StringUtils;

public class LatitudeUtil {

public static final String KEY_1 = "ChwEVlrmoje34iED20piImPc";

/**
 * 根據位址查坐标
 *
 * @param address 位址,格式:深圳市羅湖區火車站
 * @return
 */

// @param key   申請ak(即擷取密鑰),若無百度賬号則首先需要注冊百度賬号。     
public static Map<String, String> getGeocoderLatitude(String address) {
    BufferedReader in = null;
    if (CommonUtil.NotEmpty(key)) { //         
        return null;
    }
    try {
        address = URLEncoder.encode(address, "UTF-8");
        URL tirc = new URL("http://api.map.baidu.com/geocoder?address=" + address + "&output=json&key=" + KEY_1);
        in = new BufferedReader(new InputStreamReader(tirc.openStream(), "UTF-8"));
        String res;
        StringBuilder sb = new StringBuilder("");
        while ((res = in.readLine()) != null) {
            sb.append(res.trim());
        }
        String str = sb.toString();
        Map<String, String> map = new HashMap<String, String>();
        if (StringUtils.isNotEmpty(str)) {
            int lngStart = str.indexOf("lng\":");
            int lngEnd = str.indexOf(",\"lat");

            int latEnd = str.indexOf("},\"precise");
            if (lngStart > 0 && lngEnd > 0 && latEnd > 0)

            {
                String lng = str.substring(lngStart + 5, lngEnd);
                String lat = str.substring(lngEnd + 7, latEnd);
                map.put("lng", lng);
                map.put("lat", lat);
                return map;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        try {
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    return null;
}

/**
 * 計算地球上任意兩點(經緯度)距離
 * *
 * * @param lon1
 * *            第一點經度
 * * @param lat1
 * *            第一點緯度
 * * @param lon2
 * *            第二點經度
 * * @param lat2
 * *            第二點緯度
 * * @return 傳回距離 機關:千米
 */
public static double getDistatce(
        double lon1, double lat1, double lon2, double lat2) {
    double R = 6371;
    double distance = 0.0;
    double dLat = (lat2 - lat1) * Math.PI / 180;
    double dLon = (lon2 - lon1) * Math.PI / 180;
    double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(lat1 * Math.PI / 180) * Math.cos(lat2 * Math.PI / 180) * Math.sin(dLon / 2) * Math.sin(dLon / 2);
    distance = (2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a))) * R;
    return distance;
}

/**
 * 計算地球上任意兩點(經緯度)距離      *       * @param long1       *            第一點經度      * @param lat1       *            第一點緯度      * @param long2       *            第二點經度      * @param lat2       *            第二點緯度      * @return 傳回距離 機關:米
 */
public static double Distance(double long1, double lat1, double long2, double lat2) {
    double a, b, R;
    R = 6378137; // 地球半徑         
    lat1 = lat1 * Math.PI / 180.0;
    lat2 = lat2 * Math.PI / 180.0;
    a = lat1 - lat2;
    b = (long1 - long2) * Math.PI / 180.0;
    double d;
    double sa2, sb2;
    sa2 = Math.sin(a / 2.0);
    sb2 = Math.sin(b / 2.0);
    d = 2 * R * Math.asin(Math.sqrt(sa2 * sa2 + Math.cos(lat1) * Math.cos(lat2) * sb2 * sb2));
    return d;
}

/**
 * 查找一定範圍内的經緯度值   * 傳入值: 經度 緯度   查找半徑(m)   * 傳回值:最小經度、緯度,最大經度、緯度   113.957541,22.549392 朗峰大廈
 */
public static Map<String, Double> getAround(Double lon, Double lat, Double raidus) {
    Double PI = 3.14159265;    // 圓周率 
    Double EARTH_RADIUS = 6378137d;
    // 地球半徑    
    Double RAD = Math.PI / 180.0;
    // 弧度      
    Double longitude = lon;
    //經度   
    Double latitude = lat;
    //緯度      
    Double degree = (24901 * 1609) / 360.0;
    Double raidusMile = raidus;
    //距離     
    Double dpmLat = 1 / degree;
    Double radiusLat = dpmLat * raidusMile;
    Double minLat = latitude - radiusLat;
    //最小緯度   
    Double maxLat = latitude + radiusLat;
    //最大緯度     
    Double mpdLng = degree * Math.cos(latitude * (PI / 180));
    Double dpmLng = 1 / mpdLng;
    Double radiusLng = dpmLng * raidusMile;
    Double minLng = longitude - radiusLng;
    //最小經度   
    Double maxLng = longitude + radiusLng;   ]
    //最大經度   
    Map<String, Double> m = new HashMap<String, Double>();
    m.put("minLng", minLng);
    //最小經度   
    m.put("minLat", minLat);
    //最小緯度   
    m.put("maxLng", maxLng);
    //最大經度   
    m.put("maxLat", maxLat);
    //最大緯度   
    System.err.println("最小經度:" + minLng);
    System.err.println("最小緯度:" + minLat);
    System.err.println("最大經度:" + maxLng);
    System.err.println("最大緯度:" + maxLat);
    return m;
}

public static void main(String args[]) {
    Map<String, String> json = LatitudeUtil.getGeocoderLatitude("深圳羅湖火車站");
    Map<String, String> json = LatitudeUtil.getGeocoderLatitude("tl");
    System.out.println("lng : " + json.get("lng"));
    System.out.println("lat : " + json.get("lat"));
    double d1 = getDistatce(113.993941, 22.596919, 114.156395, 22.581934);
    double d2 = Distance(113.993941, 22.596919, 114.156395, 22.581934);
    System.out.println("d1 -> " + d1 + ", d2 -> " + d2);
    double f = 111.234;
    BigDecimal bg = new BigDecimal(f);
    double f1 = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
    System.out.println(f1);
}           

}

  • 經緯距離換算

public class MapDistance {

private static final double PI = 3.14159265;
private static final double EARTH_RADIUS = 6378137;
private static final double RAD = Math.PI / 180.0;
private static Double a;

private static MapDistance mapDistance=null;

public MapDistance(){

}

public static MapDistance getInstance(){
    if(mapDistance==null){
        mapDistance=new MapDistance();
    }

    return mapDistance;
}

// @see of-a-Latitude-and-Longitude--65095/
// The circumference of the earth is 24,901 miles.
// 24,901/360 = 69.17 miles / degree
/**
 * 根據提供的經度和緯度、以及半徑,取得此半徑内的最大最小經緯度
 *  @param raidus 機關米 * 
 *  @return minLat,minLng,maxLat,maxLng 
 *  
 */
public static Double[] getAround(Double lat, Double lon, int raidus) {
    Double latitude = lat;//緯度
    Double longitude = lon;//經度
    Double degree = (24901 * 1609) / 360.0;//度
    double raidusMile = raidus;//半徑
    Double dpmLat = 1 / degree;
    Double radiusLat = dpmLat * raidusMile;
    Double minLat = latitude - radiusLat;
    Double maxLat = latitude + radiusLat;
    Double mpdLng = degree * Math.cos(latitude * (PI / 180));
    Double dpmLng = 1 / mpdLng;
    Double radiusLng = dpmLng * raidusMile;
    Double minLng = longitude - radiusLng;
    Double maxLng = longitude + radiusLng;
    System.out.println(minLat+"   "+maxLat+"   "+minLng+"  "+maxLng);
    // System.out.println(&quot;[&quot;+minLat+&quot;,&quot;+minLng+&quot;,&quot;+maxLat+&quot;,&quot;+maxLng+&quot;]&quot;);
    return new Double[] { minLat,maxLat,minLng,maxLng };
}

/**
 * 根據兩點間經緯度坐标(double值),計算兩點間距離,機關為米 * 
 * @param lng1 *
 * @param lat1 
 * @param lng2  
 * @param lat2 
 * @return
 */
public static Double getDistance(Double lng1, Double lat1, Double lng2, Double lat2) {
    double radLat1 = lat1 * RAD;
    double radLat2 = lat2 * RAD;
    double a = radLat1 - radLat2;
    Double b = (lng1 - lng2) * RAD;
    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;
    s = Math.round(s * 10000) / 10000.0;
    return s;
}

public static void main(String[] args) {           

// Double lat1 = 34.264648;

// Double lon1 = 108.952736;

// int radius = 1000; // [34.25566276027792,108.94186385411045,34.27363323972208,108.96360814588955]

// getAround(lat1, lon1, radius); // 911717.0

//// // 34.264648,108.952736,39.904549,116.407288

//// Double dis = getDistance(108.952736, 34.264648, 116.407288, 39.904549);

//// System.out.println(dis);

System.out.println((0!=0.0));
}