美文网首页
Android GPS解析

Android GPS解析

作者: leach_chen | 来源:发表于2022-10-18 09:54 被阅读0次

    原地址:https://leach-chen.github.io/blog/android-gps/
    个人网站:https://www.leachchen.com/

    在做轨迹相关功能时经常需要GPS解析,从GPS文件中我们可以提取出经纬度信息,速度,方向,时间等信息。

    GPS格式可阅读这篇博客
    把GPS文件中的经纬度信息提取出来,我们就可以在地图上绘制轨迹信息了。这里有个GPS格式文件的解析库,可解析出经纬度,速度,方向,时间等信息,具体用法可以在看文章底部提供的源码。

    [图片上传失败...(image-4a9546-1666058032304)]

    世界坐标转系火星坐标系

    往往设备记录下来的坐标是原始坐标系,这是国际公认的世界标准坐标体系,我们地图上要绘制的时候一般要先转换为火星坐标系,通过下面代码中transform(double wgLat, double wgLon),传入经纬度,便可得到转换后的经纬度信息了。

    public class EvilTransform {
        final static double pi = 3.14159265358979324;
    
        //
        //
        // a = 6378245.0, 1/f = 298.3
        // b = a * (1 - f)
        // ee = (a^2 - b^2) / a^2;
        final static double a = 6378245.0;
        final static double ee = 0.00669342162296594323;
    
    
        final static double DEF_PI = 3.14159265359; // PI
        final static double DEF_2PI = 6.28318530712; // 2*PI
        final static double DEF_PI180 = 0.01745329252; // PI/180.0
        final static double DEF_R = 6370693.5; // radius of earth
    
    
        //
        // World Geodetic System ==> Mars Geodetic System
        public static double[] transform(double wgLat, double wgLon) {
            double mgLat = 0;
            double mgLon = 0;
            if (outOfChina(wgLat, wgLon)) {
                mgLat = wgLat;
                mgLon = wgLon;
    
            } else {
                double dLat = transformLat(wgLon - 105.0, wgLat - 35.0);
                double dLon = transformLon(wgLon - 105.0, wgLat - 35.0);
                double radLat = wgLat / 180.0 * pi;
                double magic = Math.sin(radLat);
                magic = 1 - ee * magic * magic;
                double sqrtMagic = Math.sqrt(magic);
                dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * pi);
                dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * pi);
                mgLat = wgLat + dLat;
                mgLon = wgLon + dLon;
            }
            double[] point = {mgLat, mgLon};
            return point;
        }
    
        private static boolean outOfChina(double lat, double lon) {
            if (lon < 72.004 || lon > 137.8347)
                return true;
            if (lat < 0.8293 || lat > 55.8271)
                return true;
            return false;
        }
    
        private static double transformLat(double x, double y) {
            double ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(y * pi) + 40.0 * Math.sin(y / 3.0 * pi)) * 2.0 / 3.0;
            ret += (160.0 * Math.sin(y / 12.0 * pi) + 320 * Math.sin(y * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }
    
        private static double transformLon(double x, double y) {
            double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
            ret += (20.0 * Math.sin(6.0 * x * pi) + 20.0 * Math.sin(2.0 * x * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.sin(x * pi) + 40.0 * Math.sin(x / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.sin(x / 12.0 * pi) + 300.0 * Math.sin(x / 30.0 * pi)) * 2.0 / 3.0;
            return ret;
        }
    
        public static double GetShortDistance(double lon1, double lat1, double lon2,double lat2) {
            double ew1, ns1, ew2, ns2;
            double dx, dy, dew;
            double distance;
            // 角度转换为弧度
            ew1 = lon1 * DEF_PI180;
            ns1 = lat1 * DEF_PI180;
            ew2 = lon2 * DEF_PI180;
            ns2 = lat2 * DEF_PI180;
            // 经度差
            dew = ew1 - ew2;
            // 若跨东经和西经180 度,进行调整
            if (dew > DEF_PI)
                dew = DEF_2PI - dew;
            else if (dew < -DEF_PI)
                dew = DEF_2PI + dew;
            dx = DEF_R * Math.cos(ns1) * dew; // 东西方向长度(在纬度圈上的投影长度)
            dy = DEF_R * (ns1 - ns2); // 南北方向长度(在经度圈上的投影长度)
            // 勾股定理求斜边长
            distance = Math.sqrt(dx * dx + dy * dy);
            return distance;
        }
    }
    

    获取轨迹距离

    获取一段轨迹的距离,我们可以依次计算相邻两个轨迹点之间的距离,再累加起来,便可以得到这段轨迹的距离了,通过上面代码中GetShortDistance(double lon1, double lat1, double lon2,double lat2)函数,前两个参数是前一个点的经纬度,后两个参数是后一个点的经纬度。

    源码参考samples里面的TestGps
    源码下载

    相关文章

      网友评论

          本文标题:Android GPS解析

          本文链接:https://www.haomeiwen.com/subject/wyldartx.html