通过第三方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);
}
}