1. 程式人生 > >Android 常用的地球經緯度轉換公里(km)計算工具類

Android 常用的地球經緯度轉換公里(km)計算工具類

地球赤道上環繞地球一週走一圈共40075.04公里,而@一圈分成360°,而每1°(度)有60,每一度一秒在赤道上的長度計算如下:   40075.04km/360°=111.31955km   

111.31955km/60=1.8553258km=1855.3m

任意兩點距離計算公式見程式碼:

package org.wavefar.lib.utils;

import android.content.Context;

import com.baidu.location.BDAbstractLocationListener;
import com.baidu.location.LocationClient;
import com.baidu.location.LocationClientOption;
import com.baidu.mapapi.model.LatLng;
import com.baidu.mapapi.navi.BaiduMapAppNotSupportNaviException;
import com.baidu.mapapi.navi.BaiduMapNavigation;
import com.baidu.mapapi.navi.NaviParaOption;
import com.baidu.mapapi.utils.poi.BaiduMapPoiSearch;
import com.baidu.mapapi.utils.route.BaiduMapRoutePlan;
import com.baidu.mapsdkplatform.comapi.location.CoordinateType;

import org.wavefar.lib.utils.LogUtil;
import org.wavefar.lib.utils.StringUtil;

/**
 * 定位相關工具類
 * @author summer
 */
public class LocationUtil {

	private LocationClient  mLocationClient;
	private BDAbstractLocationListener mlistener;
	private Context context;
    // 地球半徑
	private final static double EARTH_RADIUS = 6378.137;
	public LocationUtil(Context context) {
		 this.context = context;
		 mLocationClient = new LocationClient(context.getApplicationContext());
	     LocationClientOption option = initLocationOption();
	     mLocationClient.setLocOption(option);
	     LogUtil.d(LocationUtil.class.getSimpleName(), "當前定位庫版本" + mLocationClient.getVersion());
	}

	private LocationClientOption initLocationOption() {
		LocationClientOption option = new LocationClientOption();
        // 設定定位模式
		option.setLocationMode(LocationClientOption.LocationMode.Hight_Accuracy);
        // 返回的定位結果是百度經緯度,預設值gcj02
		option.setCoorType(CoordinateType.BD09LL);
        // 設定發起定位請求的間隔時間為5000ms
		option.setScanSpan(5000);
        // 返回的定位結果包含地址資訊
		option.setIsNeedAddress(true);
        //可選,預設false,設定是否需要POI結果,可以在BDLocation.getPoiList裡得到
		option.setIsNeedLocationPoiList(true);
        // 返回的定位結果包含手機機頭的方向
		option.setNeedDeviceDirect(true);
        //可選,預設false,設定是否需要位置語義化結果,可以在BDLocation.getLocationDescribe裡得到,結果類似於“在北京天安門附近”
        option.setIsNeedLocationDescribe(true);
        option.setOpenGps(true);
		return option;
	}
	
	/**
	 * 註冊定位回撥
	 * @param listener
	 */
	public void registerLocationListener(BDAbstractLocationListener listener) {
		mlistener = listener;
		if (mlistener != null) {
            mLocationClient.registerLocationListener(mlistener);
        }
	}
	
    /**
     * 啟動定位
     */
    public void start() {
        if (mLocationClient.isStarted()) {
            return;
        }
        mLocationClient.start();
    }

    /**
     * 重新定位
     */
    public void reStart() {
        if (mLocationClient.isStarted()) {
            return;
        }
        mLocationClient.restart();
    }

    /**
     * 停止定位
     */
    public void stop() {
        if (mLocationClient.isStarted()) {
            mLocationClient.stop();
        }
    }
	
    /**
     * 銷燬定位
     */
    public void destroy() {
        if (mLocationClient != null) {
            mLocationClient.unRegisterLocationListener(mlistener);
            mLocationClient.stop();
            mLocationClient = null;
        }
    }
    
    /**
     * 啟動百度地圖導航(Native),如果本地沒有安裝百度地圖,呼叫WEBAPP
     * @param pt1 起點
     * @param pt2 終點
     */
    public void startNavi(LatLng pt1, LatLng pt2) {
        // 構建 導航引數
        NaviParaOption para = new NaviParaOption()
                .startPoint(pt1).endPoint(pt2);
        try {
            BaiduMapNavigation.openBaiduMapNavi(para, context);
        } catch (BaiduMapAppNotSupportNaviException e) {
            BaiduMapNavigation.openWebBaiduMapNavi(para, context);
            e.printStackTrace();
        }
    }

    /**
     * 啟動百度地圖導航(Web)
     */
    public void startWebNavi(LatLng pt1,LatLng pt2) {
        NaviParaOption para = new NaviParaOption()
                .startPoint(pt1).endPoint(pt2);
        BaiduMapNavigation.openWebBaiduMapNavi(para, context);
    }
    
    /**
     * 用完導航後需要呼叫該函式銷燬
     */
    public void stopNavi() {
	   try {
           BaiduMapNavigation.finish(context);
           BaiduMapRoutePlan.finish(context);
           BaiduMapPoiSearch.finish(context);
       } catch (Exception e) {
           e.printStackTrace();
       }
    }
    
    private static double rad(double d) {
        return d * Math.PI / 180.0;
    }

    /**
     * 計算距離 返回單位km
     * @param lat1
     * @param lng1
     * @param lat2
     * @param lng2
     * @return
     */
    public static double getDistance(double lat1, double lng1, double lat2,
                                     double lng2) {
        LogUtil.d("LocationUtil", "lat1:" + lat1 + "lng1:" + lng1 + "lat2:" + lat2 + "lng2:" + lng2);
        double radLat1 = rad(lat1);
        double radLat2 = rad(lat2);
        // 如果有一方等於零,直接返回0
        if (radLat1 == 0 || radLat2 == 0) {
            return 0;
        }
        double a = radLat1 - radLat2;
        double b = rad(lng1) - rad(lng2);
        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;
        return s;
    }

    /**
     * 距離格式化
     *
     * @param distance 以千米為單位
     * @return
     */
    public static String distanceKMFormat(double distance) {
        return distance > 1 ? (distance + "KM") : (distance * 1000 + "M");
    }


    /**
     * 距離只保留兩位小數
     * @param distance 以米為單位
     * @return
     */
    public static String distanceFormat(double distance) {
        String str;
        double value = distance;
        if (distance >= 1000) {
            value = value / 1000;
            str = "KM";
        } else {
            str = "M";
        }
        return String.format("%s%s",StringUtil.formatDecimal(value,null),str);
    }
    
}

 以上程式碼定位依賴於百度定位API,所以貼上以上程式碼之前,需要引入百度定位API,引入百度定位API不在這裡介紹,自行去百度定位官方檢視;