java经纬度操作

遇上了,记录一下…

大概就是,通过第三方sdk定位目标经纬度,然后计算两个位置的距离等,合并经纬度为一个单一数字等(方便存数据库)和一些转换操作,代码如下:

/** 地图工具类 */
public class WorldMapUtil {
	/** 经纬度转换常量 */
	private static final double EARTH_RADIUS = 6378137.0;
	/** 保留经纬度小数点后的位数 */
	private static int point_length = Context.point_length;
	
	/**
	 * 计算AB两点距离(米)
	 * @param lat_a	A点纬度
	 * @param lng_a	A点经度
	 * @param lat_b	B点纬度
	 * @param lng_b	B点经度
	 * @return	AB两点距离多少米
	 */
	public static Double getDistance(double lat_a, double lng_a, double lat_b, double lng_b) {
		double radLat1 = (lat_a * Math.PI / 180.0);
		double radLat2 = (lat_b * Math.PI / 180.0);
		double a = radLat1 - radLat2;
		double b = (lng_a - lng_b) * Math.PI / 180.0;
		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 lat_a	A点纬度
	 * @param lng_a	A点经度
	 * @param lat_b	B点纬度
	 * @param lng_b	B点经度
	 * @return	返回角度
	 */
	public static double gps2d(double lat_a, double lng_a, double lat_b, double lng_b) {
		double d = 0;
		lat_a=lat_a*Math.PI/180;
		lng_a=lng_a*Math.PI/180;
		lat_b=lat_b*Math.PI/180;
		lng_b=lng_b*Math.PI/180;
		
		d=Math.sin(lat_a)*Math.sin(lat_b)+Math.cos(lat_a)*Math.cos(lat_b)*Math.cos(lng_b-lng_a);
		d=Math.sqrt(1-d*d);
		d=Math.cos(lat_b)*Math.sin(lng_b-lng_a)/d;
		d=Math.asin(d)*180/Math.PI;
		
//		d = (d*10000);
		return d;
	}
	
	/**
	 * 合并经纬度为一个单一数字
	 * @param lat	维度
	 * @param lng	经度
	 * @return	合并后的单一数据
	 */
	public static Long mergerPoint(Double lat, Double lng) {
		if(isErrorLoction(lng, lat)) {
			throw new CommonException(Error.system_location_error);
		}
		String latStr = lat.toString();
		String lngStr = lng.toString();
		int lat_d = latStr.indexOf(".");
		int lng_d = lngStr.indexOf(".");
		latStr = latStr.replace(".", "");
		lngStr = lngStr.replace(".", "");
		// 处理掉过长经纬度
		latStr = (latStr.length()-lat_d)>point_length ? latStr.substring(0, lat_d+point_length) : latStr;
		lngStr = (lngStr.length()-lng_d)>point_length ? lngStr.substring(0, lng_d+point_length) : lngStr;
		// 处理过短的经纬度
		while(latStr.length()-lat_d < point_length) {
			latStr += "0";
		}
		while(lngStr.length()-lng_d < point_length) {
			lngStr += "0";
		}
		
		// 转换成数字数据并获取数据的二进制下的长度(准备做二进制对插)
		Long tempLat = Long.parseLong(latStr);
		Long tempLng = Long.parseLong(lngStr);
		int lengthLat = Long.toBinaryString(tempLat).length();
		int lengthLng= Long.toBinaryString(tempLng).length();
		
		// 获取经纬度中最长为位数
		int maxLength = lengthLat>lengthLng?lengthLat:lengthLng;
		
		// 进行二进制对插处理
		Long newPoint = 0L;
		for(int i=0; i<maxLength; i++) {
			newPoint += ((tempLat>>i)%2)*(new Double(Math.pow(2, i*2)).longValue());
			newPoint += ((tempLng>>i)%2)*(new Double(Math.pow(2, i*2+1)).longValue());
		}
		return newPoint;
	}
	
	/**
	 * 将合并后的数值重新转换为经纬度
	 * @param num	合并后的数值
	 * @return	借用 Point.Double 来表示经纬度(x:纬度lat,y:经度lng)
	 */
	public static Point.Double getPointForMerger(Long num) {
		int binaryLength = Long.toBinaryString(num).length();
		Long latNg = 0L;
		Long lngNg = 0L;
		for(int i=0; i<binaryLength; i++) {
			if(i%2 == 0) {
				latNg += ((num>>i)%2) * (new Double(Math.pow(2, i/2)).longValue());
			} else {
				lngNg += ((num>>i)%2) * (new Double(Math.pow(2, i/2)).longValue());
			}
		}
		
		Double pow = Math.pow(10, point_length);
		Double lat = latNg / pow;
		Double lng = lngNg / pow;
		return new Point2D.Double(lat, lng);
	}
	
	/**
	 * 校验经纬度是否是异常值
	 * (处理经纬度有获取不到的情况)
	 * @param lng	经度
	 * @param lat	纬度
	 * @return	是否正常(true:非正常)
	 */
	public static boolean isErrorLoction(Double lng, Double lat) {
		if(lng==null || lat==null) {
			return true;
		}
		if(lng.equals(Double.MAX_VALUE) || lat.equals(Double.MAX_VALUE)) {
			return true;
		}
		if(lng.equals(0.0d) || lat.equals(0.0d)) {
			return true;
		}
		// 特殊值(未获取到经纬度时的值)
		if(lng.equals(4.9E-324) || lat.equals(4.9E-324)) {
			return true;
		}
		return false;
	}
	
	
	/**
	 * 计算合并后数值间的距离
	 * @param num1	数值1
	 * @param num2	数值2
	 * @return	距离(米)
	 */
	public static double getDistance(Long num1, Long num2) {
		Point.Double pd1 = getPointForMerger(num1);
		Point.Double pd2 = getPointForMerger(num2);
		return getDistance(pd1.x, pd1.y, pd2.x, pd2.y);
	}
	
	/**
	 * 计算合并后数值间的角方位
	 * @param num1	数值1
	 * @param num2	数值2
	 * @return	角度
	 */
	public static double gps2d(Long num1, Long num2) {
		Point.Double pd1 = getPointForMerger(num1);
		Point.Double pd2 = getPointForMerger(num2);
		return gps2d(pd1.x, pd1.y, pd2.x, pd2.y);
	}
}
  • 本文作者:
    低调小熊猫
  • 本文链接:

    http://ilovey.live/archives/wordmapuitl

  • 版权声明:
    博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0
    许可协议。转载请注明出处!

原文 

http://ilovey.live/archives/wordmapuitl

本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。

PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » java经纬度操作

赞 (0)
分享到:更多 ()

评论 0

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址