首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >java经纬度操作

java经纬度操作

作者头像
低调小熊猫
发布2020-06-06 23:46:00
1.6K0
发布2020-06-06 23:46:00
举报
文章被收录于专栏:低调小熊猫低调小熊猫

通过第三方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);
    }
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-03-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 低调小熊猫 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档