地图坐标转换器

  1 public static class MapConvertercs
  2             {
  3                 //WGS-84原始坐标系
  4                 //GCJ-02:高德、Google
  5                 //BD-09:百度
  6 
  7 
  8                 /// <summary>
  9                 /// 圆周率
 10                 /// </summary>
 11                 private const double PI = 3.1415926535897932384626;
 12                 private const double X_PI = PI * 3000.0 / 180.0;
 13 
 14                 /// <summary>
 15                 /// 地理位置是否位于中国以外
 16                 /// </summary>
 17                 /// <param name="wgLat">WGS-84坐标纬度</param>
 18                 /// <param name="wgLon">WGS-84坐标经度</param>
 19                 /// <returns>
 20                 ///     true:国外
 21                 ///     false:国内
 22                 /// </returns>
 23                 public static bool OutOfChina(double wgLat, double wgLon)
 24                 {
 25                     if (wgLon < 72.004 || wgLon > 137.8347) return true;
 26                     if (wgLat < 0.8293 || wgLat > 55.8271) return true;
 27 
 28                     return false;
 29                 }
 30 
 31                 /// <summary>
 32                 /// WGS-84坐标系转火星坐标系 (GCJ-02)
 33                 /// </summary>
 34                 /// <param name="wgLat">WGS-84坐标纬度</param>
 35                 /// <param name="wgLon">WGS-84坐标经度</param>
 36                 /// <param name="mgLat">输出:GCJ-02坐标纬度</param>
 37                 /// <param name="mgLon">输出:GCJ-02坐标经度</param>
 38                 public static void WGS84ToGCJ02(double wgLat, double wgLon, out double mgLat, out double mgLon)
 39                 {
 40                     if (OutOfChina(wgLat, wgLon))
 41                     {
 42                         mgLat = wgLat;
 43                         mgLon = wgLon;
 44                     }
 45                     else
 46                     {
 47                         double dLat;
 48                         double dLon;
 49                         Delta(wgLat, wgLon, out dLat, out dLon);
 50                         mgLat = wgLat + dLat;
 51                         mgLon = wgLon + dLon;
 52                     }
 53                 }
 54 
 55                 /// <summary>
 56                 /// 火星坐标系 (GCJ-02)转WGS-84坐标系
 57                 /// </summary>
 58                 /// <param name="mgLat">GCJ-02坐标纬度</param>
 59                 /// <param name="mgLon">GCJ-02坐标经度</param>
 60                 /// <param name="wgLat">输出:WGS-84坐标纬度</param>
 61                 /// <param name="wgLon">输出:WGS-84坐标经度</param>
 62                 public static void GCJ02ToWGS84(double mgLat, double mgLon, out double wgLat, out double wgLon)
 63                 {
 64                     if (OutOfChina(mgLat, mgLon))
 65                     {
 66                         wgLat = mgLat;
 67                         wgLon = mgLon;
 68                     }
 69                     else
 70                     {
 71                         double dLat;
 72                         double dLon;
 73                         Delta(mgLat, mgLon, out dLat, out dLon);
 74                         wgLat = mgLat - dLat;
 75                         wgLon = mgLon - dLon;
 76                     }
 77                 }
 78 
 79                 /// <summary>
 80                 /// 火星坐标系 (GCJ-02)转WGS-84坐标系
 81                 /// </summary>
 82                 /// <param name="mgLat">GCJ-02坐标纬度</param>
 83                 /// <param name="mgLon">GCJ-02坐标经度</param>
 84                 /// <param name="wgLat">输出:WGS-84坐标纬度</param>
 85                 /// <param name="wgLon">输出:WGS-84坐标经度</param>
 86                 public static void GCJ02ToWGS84Exact(double mgLat, double mgLon, out double wgLat, out double wgLon)
 87                 {
 88                     const double InitDelta = 0.01;
 89                     const double Threshold = 0.000001;
 90 
 91                     double dLat = InitDelta;
 92                     double dLon = InitDelta;
 93                     double mLat = mgLat - dLat;
 94                     double mLon = mgLon - dLon;
 95                     double pLat = mgLat + dLat;
 96                     double pLon = mgLon + dLon;
 97 
 98                     double nLat;
 99                     double nLon;
100 
101                     int i = 0;
102                     do
103                     {
104                         wgLat = (mLat + pLat) / 2;
105                         wgLon = (mLon + pLon) / 2;
106 
107                         WGS84ToGCJ02(wgLat, wgLon, out nLat, out nLon);
108 
109                         dLat = nLat - mgLat;
110                         dLon = nLon - mgLon;
111                         if ((Math.Abs(dLat) < Threshold) && (Math.Abs(dLon) < Threshold)) break;
112 
113                         if (dLat > 0) pLat = wgLat; else mLat = wgLat;
114                         if (dLon > 0) pLon = wgLon; else mLon = wgLon;
115                     } while (++i <= 30);
116                 }
117 
118                 /// <summary>
119                 /// 百度坐标系 (BD-09)转火星坐标系 (GCJ-02)
120                 /// </summary>
121                 /// <param name="bdLat">百度坐标系纬度</param>
122                 /// <param name="bdLon">百度坐标系经度</param>
123                 /// <param name="mgLat">输出:GCJ-02坐标纬度</param>
124                 /// <param name="mgLon">输出:GCJ-02坐标经度</param>         
125                 public static void BD09ToGCJ02(double bdLat, double bdLon, out double mgLat, out double mgLon)
126                 {
127                     double x = bdLon - 0.0065;
128                     double y = bdLat - 0.006;
129                     double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * X_PI);
130                     double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * X_PI);
131                     mgLat = z * Math.Sin(theta);
132                     mgLon = z * Math.Cos(theta);
133                 }
134 
135                 /// <summary>
136                 /// 火星坐标系 (GCJ-02)转百度坐标系 (BD-09)
137                 /// </summary>
138                 /// <param name="mgLat">GCJ-02坐标纬度</param>
139                 /// <param name="mgLon">GCJ-02坐标经度</param>
140                 /// <param name="bdLat">输出:百度坐标系纬度</param>
141                 /// <param name="bdLon">输出:百度坐标系经度</param>
142                 public static void GCJ02ToBD09(double mgLat, double mgLon, out double bdLat, out double bdLon)
143                 {
144                     double x = mgLon;
145                     double y = mgLat;
146                     double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * X_PI);
147                     double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * X_PI);
148                     bdLat = z * Math.Sin(theta) + 0.006;
149                     bdLon = z * Math.Cos(theta) + 0.0065;
150                 }
151 
152                 /// <summary>
153                 /// WGS-84坐标系转百度坐标系 (BD-09)
154                 /// </summary>
155                 /// <param name="wgLat">WGS-84坐标纬度</param>
156                 /// <param name="wgLon">WGS-84坐标经度</param>
157                 /// <param name="bdLat">输出:百度坐标系纬度</param>
158                 /// <param name="bdLon">输出:百度坐标系经度</param>
159                 public static void WGS84ToBD09(double wgLat, double wgLon, out double bdLat, out double bdLon)
160                 {
161                     double mgLat;
162                     double mgLon;
163 
164                     WGS84ToGCJ02(wgLat, wgLon, out mgLat, out mgLon);
165                     GCJ02ToBD09(mgLat, mgLon, out bdLat, out bdLon);
166                 }
167 
168                 /// <summary>
169                 /// 百度坐标系 (BD-09)转WGS-84坐标系
170                 /// </summary>
171                 /// <param name="bdLat">百度坐标系纬度</param>
172                 /// <param name="bdLon">百度坐标系经度</param>
173                 /// <param name="wgLat">输出:WGS-84坐标纬度</param>
174                 /// <param name="wgLon">输出:WGS-84坐标经度</param>
175                 public static void BD09ToWGS84(double bdLat, double bdLon, out double wgLat, out double wgLon)
176                 {
177                     double mgLat;
178                     double mgLon;
179 
180                     BD09ToGCJ02(bdLat, bdLon, out mgLat, out mgLon);
181                     GCJ02ToWGS84(mgLat, mgLon, out wgLat, out wgLon);
182                 }
183 
184                 public static double Distance(double LatA, double LonA, double LatB, double LonB)
185                 {
186                     const double EarthR = 6371000.0;
187 
188                     double x = Math.Cos(LatA * PI / 180.0) * Math.Cos(LatB * PI / 180.0) * Math.Cos((LonA - LonB) * PI / 180);
189                     double y = Math.Sin(LatA * PI / 180.0) * Math.Sin(LatB * PI / 180.0);
190                     double s = x + y;
191                     if (s > 1) s = 1;
192                     if (s < -1) s = -1;
193 
194                     return Math.Acos(s) * EarthR;
195                 }
196 
197                 private static void Delta(double Lat, double Lon, out double dLat, out double dLon)
198                 {
199                     const double AXIS = 6378245.0;
200                     const double EE = 0.00669342162296594323;
201 
202                     dLat = TransformLat(Lon - 105.0, Lat - 35.0);
203                     dLon = TransformLon(Lon - 105.0, Lat - 35.0);
204                     double radLat = Lat / 180.0 * PI;
205                     double magic = Math.Sin(radLat);
206                     magic = 1 - EE * magic * magic;
207                     double sqrtMagic = Math.Sqrt(magic);
208                     dLat = (dLat * 180.0) / ((AXIS * (1 - EE)) / (magic * sqrtMagic) * PI);
209                     dLon = (dLon * 180.0) / (AXIS / sqrtMagic * Math.Cos(radLat) * PI);
210                 }
211 
212                 private static double TransformLat(double x, double y)
213                 {
214                     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));
215                     ret += (20.0 * Math.Sin(6.0 * x * PI) + 20.0 * Math.Sin(2.0 * x * PI)) * 2.0 / 3.0;
216                     ret += (20.0 * Math.Sin(y * PI) + 40.0 * Math.Sin(y / 3.0 * PI)) * 2.0 / 3.0;
217                     ret += (160.0 * Math.Sin(y / 12.0 * PI) + 320 * Math.Sin(y * PI / 30.0)) * 2.0 / 3.0;
218                     return ret;
219                 }
220 
221                 private static double TransformLon(double x, double y)
222                 {
223                     double ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x));
224                     ret += (20.0 * Math.Sin(6.0 * x * PI) + 20.0 * Math.Sin(2.0 * x * PI)) * 2.0 / 3.0;
225                     ret += (20.0 * Math.Sin(x * PI) + 40.0 * Math.Sin(x / 3.0 * PI)) * 2.0 / 3.0;
226                     ret += (150.0 * Math.Sin(x / 12.0 * PI) + 300.0 * Math.Sin(x / 30.0 * PI)) * 2.0 / 3.0;
227                     return ret;
228                 }
229             }

 

posted on 2020-06-09 16:56  高达  阅读(723)  评论(0)    收藏  举报

导航