2020-06-11關(guān)于WGS84 高德坐標 百度坐標的相互轉(zhuǎn)換

在地圖學中,一般將坐標分為投影坐標和地理坐標。地理坐標和投影坐標的聯(lián)系和區(qū)別對于一般的地圖使用者而言可能并不需要掌握的非常清楚。通俗一點來說,地理坐標是一個球體的坐標,而投影坐標是一個平面的坐標。常用的GPS、百度地圖、高德地圖等都是采用的地理坐標。
確定了地理坐標之后,常見的地圖應用分別采用的都是什么坐標系呢?一般來說,國外的一些地圖,都是采用WGS84坐標系,比如谷歌地圖、OMS地圖、Bing地圖(非中國區(qū)域)等。而國內(nèi)的地圖,處于保密需求,大多采用火星坐標系,在WGS84的基礎(chǔ)上作了一些偏移,如高德地圖、騰訊地圖等。而百度又在火星坐標系的基礎(chǔ)上又作了一定偏移,生成了自己的百度坐標系。

WGS84:谷歌地圖 OMS
火星坐標系:高德地圖 騰訊地圖
百度坐標系:百度地圖

這些加密算法,一般是無法準確還原的,但是在小范圍內(nèi)的數(shù)據(jù),可以通過一定的變換相互轉(zhuǎn)化。具體的C#代碼如下

 public struct Cor
    {
        public double lng;
        public double lat;
    }
    public class Transformer
    {
        const double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        const double pi = 3.1415926535897932384626; // π
        const double a = 6378245.0;// 長半軸
        const double ee = 0.00669342162296594323; // 扁率

        //火星轉(zhuǎn)百度
        public static Cor gcj02tobd09(Cor HxCor)
        {
            double z = Math.Sqrt(HxCor.lng * HxCor.lng + HxCor.lat * HxCor.lat) + 0.00002 * Math.Sin(HxCor.lat * x_pi);
            double theta = Math.Atan2(HxCor.lat, HxCor.lng) + 0.000003 * Math.Cos(HxCor.lng * x_pi);
            Cor BaiduCor;
            BaiduCor.lng = z * Math.Cos(theta) + 0.0065;
            BaiduCor.lat = z * Math.Sin(theta) + 0.006;
            return BaiduCor;
        }

        //百度轉(zhuǎn)火星
        public static Cor bd09togcj02(Cor Bd)
        {
            double x = Bd.lng - 0.0065;
            double y = Bd.lat - 0.006;
            double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) - .000003 * Math.Cos(x * x_pi);
            Cor hx;
            hx.lng = z * Math.Cos(theta);
            hx.lat = z * Math.Sin(theta);
            return hx;
        }

        //WGS84轉(zhuǎn)火星
        public static Cor wgs84togcj02(Cor wgs84)
        {
            if (OutOfChina(wgs84))
            {
                return wgs84;
            }
            double dlat = transformlat(wgs84.lng - 105.0, wgs84.lat - 35.0);
            double dlng = transformlng(wgs84.lng - 105.0, wgs84.lat - 35.0);
            double radlat = wgs84.lat / 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);
            dlng = (dlng * 180.0) / (a / sqrtmagic * Math.Cos(radlat) * pi);
            Cor hx;
            hx.lat = wgs84.lat + dlat;
            hx.lng = wgs84.lng + dlng;
            return hx;
        }


        //火星轉(zhuǎn)84
        public static Cor gcj02towgs84(Cor hx)
        {
            if (OutOfChina(hx))
            {
                return hx;
            }
            double dlat = transformlat(hx.lng - 105.0, hx.lat - 35.0);
            double dlng = transformlng(hx.lng - 105.0, hx.lat - 35.0);
            double radlat = hx.lat / 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);
            dlng = (dlng * 180.0) / (a / sqrtmagic * Math.Cos(radlat) * pi);
            Cor wgs84;
            double mglat = hx.lat + dlat;
            double mglng = hx.lng + dlng;
            wgs84.lat = hx.lat * 2 -mglat;
            wgs84.lng = hx.lng *2-mglng;
            return wgs84;
        }
        
        //百度轉(zhuǎn)84
        public static Cor bd09towgs84(Cor bd)
        {
            Cor hx = bd09togcj02(bd);
            Cor wgs84 = gcj02towgs84(hx);
            return wgs84;
        }

        //84轉(zhuǎn)百度
        public static Cor wgs84tobd09(Cor wgs84)
        {
            Cor hx = wgs84togcj02(wgs84);
            Cor bd = gcj02tobd09(hx);
            return bd;
        }
        /*輔助函數(shù)*/
        //判斷是否在國內(nèi)
        private static Boolean OutOfChina(Cor wgs84)
        {
            if (wgs84.lng < 72.004 || wgs84.lng > 137.8347)
            {
                return true;
            }
            if (wgs84.lat < 0.8293 || wgs84.lat > 55.8271)
            {
                return true;
            }
            return false;
        }

        /*輔助函數(shù)*/
        //轉(zhuǎn)換lat
        private static double transformlat(double lng, double lat)
        {
            double ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat +
        0.1 * lng * lat + 0.2 * Math.Sqrt(Math.Abs(lng));
    ret += (20.0 * Math.Sin(6.0 * lng * pi) + 20.0 *
            Math.Sin(2.0 * lng * pi)) * 2.0 / 3.0;
    ret += (20.0 * Math.Sin(lat * pi) + 40.0 *
            Math.Sin(lat / 3.0 * pi)) * 2.0 / 3.0;
    ret += (160.0 * Math.Sin(lat / 12.0 * pi) + 320 *
            Math.Sin(lat * pi / 30.0)) * 2.0 / 3.0;
            return ret;
        }

        /*輔助函數(shù)*/
        //轉(zhuǎn)換lng
        private static double transformlng(double lng, double lat)
        {
            double ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng +
        0.1 * lng * lat + 0.1 * Math.Sqrt(Math.Abs(lng));
            ret += (20.0 * Math.Sin(6.0 * lng * pi) + 20.0 *
                    Math.Sin(2.0 * lng * pi)) * 2.0 / 3.0;
            ret += (20.0 * Math.Sin(lng * pi) + 40.0 *
                    Math.Sin(lng / 3.0 * pi)) * 2.0 / 3.0;
            ret += (150.0 * Math.Sin(lng / 12.0 * pi) + 300.0 *
                    Math.Sin(lng / 30.0 * pi)) * 2.0 / 3.0;
            return ret;
        }

        // 按類計算
        public static   Cor transform(Cor corOld,string transType)
        {
            switch (transType)
            {
                case "百度轉(zhuǎn)火星":   
                        return Transformer.bd09togcj02(corOld);
                case "百度轉(zhuǎn)84":
                        return Transformer.bd09towgs84(corOld);
                case "火星轉(zhuǎn)84":    
                        return Transformer.gcj02towgs84(corOld);
                case "84轉(zhuǎn)火星":
                        return Transformer.wgs84togcj02(corOld);
                case "火星轉(zhuǎn)百度":
                        return Transformer.gcj02tobd09(corOld);
                case "84轉(zhuǎn)百度":
                        return Transformer.wgs84tobd09(corOld);
                default:
                    return corOld;
            }
            
        }
    }

完整可編譯的源碼在https://github.com/njupt-shao/coordinate-transformation
示例程序下載鏈接:https://pan.baidu.com/s/1bAkJK_-ra96eG_70DRnudw
提取碼:cbr5

單個轉(zhuǎn)換

文件轉(zhuǎn)換

CSV文件格式,一行一個坐標,半角逗號隔開經(jīng)緯度

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容