美文网首页
.NET 地图坐标互相转换(WGS-84,GCJ-02,BD-0

.NET 地图坐标互相转换(WGS-84,GCJ-02,BD-0

作者: jfwangncs | 来源:发表于2019-05-29 17:14 被阅读0次

    在我们使用地图的时候都会接触到坐标。有时候发现同一个点位再不同地图中坐标是不一样的,这就是因为各个地图系统用了不同标准的坐标系统。因为有些国家规定坐标必须进行投影偏转。
    我们现在常用的坐标系有
    WGS-84:一种国际上采用的地心坐标系。坐标原点为地球质心,国外一般都用这种例如Google Earth和中国外的Google Map。
    GCJ-02:GCJ-02是由中国国家测绘局(G表示Guojia国家,C表示Cehui测绘,J表示Ju局)制订的地理信息系统的坐标系统。它是一种对经纬度数据的加密算法,即加入随机的偏差。使用的有中国Google Map、高德、腾讯。
    BD-09:百度地图使用,在GCJ-02基础上二次加密而成。
    转换代码

     public class TempGps
        {
    
            public double Tlng;
            public double Tlat;
        }
    
        public class GPS
        {
            public string oLng;//经度 度分秒坐标
            public string oLat;//纬度 度分秒坐标
    
            public double lng;//经度 WGS-84
            public double lat;//纬度 WGS-84
    
            public double gLng;//经度 GCJ-02 中国坐标偏移标准 Google Map、高德、腾讯使用
            public double gLat;//纬度 GCJ-02 中国坐标偏移标准 Google Map、高德、腾讯使用
    
            public double bLng;//经度 BD-09 百度坐标偏移标准,Baidu Map使用
            public double bLat;//纬度 BD-09 百度坐标偏移标准,Baidu Map使用
    
    
            public double PI = Math.PI;
            double xPI = Math.PI * 3000.0 / 180.0;
    
            public TempGps delta(TempGps t)
            {
                var a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
                var ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
                var dLat = this.transformLat(t.Tlng - 105.0, t.Tlat - 35.0);
                var dLng = this.transformLng(t.Tlng - 105.0, t.Tlat - 35.0);
                var radLat = t.Tlat / 180.0 * PI;
                var magic = Math.Sin(radLat);
                magic = 1 - ee * magic * magic;
                var sqrtMagic = Math.Sqrt(magic);
                return new TempGps() { Tlat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * PI),  Tlng= (dLng * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * PI) };
            }
            //WGS-84 to GCJ-02
            public void gcj_encrypt()
            {
                if (this.outOfChina(lng, lat))
                {
                    gLng = lng;
                    gLat = lat;
                }
                var t = this.delta(new TempGps() { Tlng = lng, Tlat = lat });
                gLng = t.Tlng+lng;
                gLat = t.Tlat+lat;
            }
    
            //GCJ-02 to WGS-84
            public void gcj_decrypt()
            {
    
    
                if (this.outOfChina(gLng, gLat))
                {
                    lng = gLng;
                    lat = gLat;
    
                }
                var t = this.delta(new TempGps() { Tlng = gLng, Tlat = gLat });
                lng = gLng-t.Tlng;
                lat = gLat-t.Tlat;
            }
    
            //GCJ-02 to BD-09
            public void bd_encrypt()
            {
                double x = gLng;
                double y = gLat;
                double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * xPI);
                double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * xPI);
                bLng = z * Math.Cos(theta) + 0.0065;
                bLat = z * Math.Sin(theta) + 0.006;
            }
            //BD-09 to GCJ-02
            public void bd_decrypt()
            {
                double x = bLng - 0.0065;
                double y = bLat - 0.006;
                double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * xPI);
                double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * xPI);
                gLng = z * Math.Cos(theta);
                gLat = z * Math.Sin(theta);
            }
    
            //WGS-84 to 度分秒坐标  
            public void wgs_decrypt()
            {
                oLng = TranDegreeToDMs(lng);
                oLat = TranDegreeToDMs(lat);
            }
    
    
            //度分秒坐标 to WGS-84
            public void wgs_encrypt()
            {
                lng = TranDMsToDegree(oLng);
                lat = TranDMsToDegree(oLat);
            }
    
    
            public double TranDMsToDegree(string _dms)
            {
                string[] dms = _dms.Split('.');
                if (dms.Length > 2)
                    return double.Parse(dms[0]) + double.Parse(dms[1]) / 60 + double.Parse(dms[2] + "." + dms[3] ?? "0") / 3600;
                else
                    return 0d;
    
            }
    
    
            private static string TranDegreeToDMs(double d)
            {
                int Degree = Convert.ToInt16(Math.Truncate(d));//度
                d = d - Degree;
                int M = Convert.ToInt16(Math.Truncate((d) * 60));//分
                int S = Convert.ToInt16(Math.Round((d * 60 - M) * 60));
                if (S == 60)
                {
                    M = M + 1;
                    S = 0;
                }
                if (M == 60)
                {
                    M = 0;
                    Degree = Degree + 1;
                }
                string rstr = Degree.ToString() + ".";
                if (M < 10)
                    rstr = rstr + "0" + M.ToString();
                else
                    rstr = rstr + M.ToString();
                if (S < 10)
                    rstr = rstr + "0" + S.ToString();
                else
                    rstr = rstr + S.ToString();
                return rstr;
            }
    
            private bool outOfChina(double _lng, double _lat)
            {
                if (lng < 72.004 || lng > 137.8347)
                    return true;
                if (lat < 0.8293 || lat > 55.8271)
                    return true;
                return false;
            }
    
            private 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 double transformLng(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;
            }
        }
    

    使用方法

    GPS t = new GPS();
    t.oLng = dt.Rows[i][1].ToString();
    t.oLat = dt.Rows[i][2].ToString();
    t.wgs_encrypt();
    t.gcj_encrypt();
    t.bd_encrypt();
    cells[i+1, 3].PutValue(t.bLng);
    cells[i+1, 4].PutValue(t.bLat);
    

    github:https://github.com/jfwangncs/GPSConvert

    相关文章

      网友评论

          本文标题:.NET 地图坐标互相转换(WGS-84,GCJ-02,BD-0

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