<一>基本操作

一、一些基本设置

如中心点、最大最小当前比例尺设置、地图、还有
这些都写在gMapControl1_Load(),加载函数里,我为了方便将GMapControl控件命名为了gmap

  1. private void gmap_Load(object sender, EventArgs e)
  2. {
  3. //加载谷歌中国地图
  4. GMapProvider.TimeoutMs = 0;
  5. gmap.MapProvider = GMapProviders.GoogleChinaMap;
  6. gmap.MapProvider = GMap.NET.MapProviders.GoogleChinaMapProvider.Instance;
  7. ////加载谷歌卫星地图
  8. //gmap.MapProvider = GMapProviders.GoogleChinaSatelliteMap;
  9. //GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
  10. gmap.DragButton = System.Windows.Forms.MouseButtons.Left;//地图拖拽使用鼠标左键
  11. gmap.Zoom = 12;//当前的比例尺
  12. gmap.ShowCenter = false;//是否显示红色十字标
  13. gmap.MaxZoom = 24;//最大比例尺
  14. gmap.MinZoom = 2;//最小比例尺
  15. this.gmap.Position = new PointLatLng(39.923518, 116.539009);//gmapControl地图的中心位置
  16. this.gmap.IsAccessible = false;//
  17. GMapProvider.TimeoutMs = 1000;
  18. TopologyElement.Point pt = new TopologyElement.Point();
  19. pt.Lat = 39.923518;
  20. pt.Lon = 116.539009;
  21. pt.ID = 1;
  22. }

GMapProvider类是提供地图、目前支持谷歌地图、百度地图、高德地图及其卫星地图

二、添加点、路线

GMapMarker是GMap.NET的图标类
GMarkerGoogle是枚举类型
所以设置一个GMapMarker通过给定位置信息和图标种类,并将该图标加入到图层,并把图层加入到gmapControl既可以实时显示了

  1. //点PointLatLng、图标GMapMarker
  2. GMapMarker gMapMarker = new GMarkerGoogle(new PointLatLng(38.0122.0), GMarkerGoogleType.green);
  3. gMapMarker.ToolTipText = string.Format("点编号{0}:经度{1},纬度{2}", 1, gMapMarker.Position.Lon, gMapMarker.Position.Lat);
  4. gMapMarker.ToolTip.Foreground = Brushes.Black;//设置提示框
  5. gMapMarker.ToolTip.TextPadding = new Size(20, 10);
  6. //图层
  7. GMapOverlay overlay = new GMapOverlay("图层名称");
  8. //图标加入到图层中
  9. overlay.Markers.Add(gMapMarker);
  10. //路线--需要添加点集合如List<PointLatLng>
  11. List<PointLatLng> points=new List<PointLatLng>();
  12. points.Add(new PointLatLng(38.0,122.0));
  13. points.Add(new PointLatLng(38.1,122,1));//至此两个点确定了一条直线
  14. GMapRoute route=new GMapRoute(points,"路线名称");
  15. //路线加入到图层中
  16. overlay.Routes.Add(route);
  17. //图层加入到控件中
  18. this.gmap.Overlays.Add(overlay)

三、切换地图源操作

我用了三个RadioButton来实现这个
所以在CheckChanged事件中写

  1. private void rb_SatelliteMap_CheckedChanged(object sender, EventArgs e)
  2. {
  3. if (rb_SatelliteMap.Checked)
  4. {
  5. gmap.MapProvider = GMapProviders.GoogleChinaSatelliteMap;
  6. GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
  7. gmap.ReloadMap();
  8. GMapProvider.TimeoutMs = 1000;
  9. }
  10. }
  11. private void rb_OthersMap_CheckedChanged(object sender, EventArgs e)
  12. {
  13. if (rb_OthersMap.Checked)
  14. {
  15. gmap.MapProvider = GMapProviders.EmptyProvider;
  16. GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
  17. gmap.ReloadMap();
  18. GMapProvider.TimeoutMs = 1000;
  19. }
  20. }
  21. private void map_Normal_CheckedChanged(object sender, EventArgs e)
  22. {
  23. if (map_Normal.Checked)
  24. {
  25. gmap.MapProvider = GMapProviders.GoogleChinaMap;
  26. gmap.MapProvider = GMap.NET.MapProviders.GoogleChinaMapProvider.Instance; GMap.NET.GMaps.Instance.Mode = GMap.NET.AccessMode.ServerAndCache;
  27. gmap.ReloadMap();
  28. GMapProvider.TimeoutMs = 1000;
  29. }
  30. }

<二>拓展操作

一、设置全屏幕

其实原理就是找到图层的最大/最小纬度/经度,组成一个矩形,利用GMap自己的方法this.gmap.SetZoomToFitRect(area);

  1. #region 设置最佳视图
  2. /// <summary>
  3. /// 是否显示最佳视图
  4. /// </summary>
  5. /// <param name="isCurrentOverlay">是否设置当前图层</param>
  6. /// <param name="isSetPerfectPos">是否设置最佳视图</param>
  7. /// <param name="overlay">tuc</param>
  8. private void SetPerfectPos(bool isCurrentOverlay, bool isSetPerfectPos, GMapOverlay overlay)
  9. {
  10. if (isCurrentOverlay)
  11. {
  12. currentOverlay = overlay;
  13. txtCurrentOverlay.Caption = string.Format("当前图层:{0}", overlay.Id);
  14. }
  15. if (isSetPerfectPos)
  16. {
  17. SetPerfectPos(overlay.Markers);
  18. }
  19. }
  20. /// <summary>
  21. /// 设置最佳视图
  22. /// </summary>
  23. /// <param name="gpoints">所有点的范围</param>
  24. private void SetPerfectPos(List<PointLatLng> gpoints)
  25. {
  26. if (gpoints.Count != 0)
  27. {
  28. double minlat = gpoints.Min(a => a.Lat);
  29. double maxlat = gpoints.Max(a => a.Lat);
  30. double minlng = gpoints.Min(a => a.Lng);
  31. double maxlng = gpoints.Max(a => a.Lng);
  32. PointLatLng lefttop = new PointLatLng(minlat, minlng);
  33. PointLatLng center = new PointLatLng((minlat + maxlat) / 2.0, (minlng + maxlng) / 2.0);
  34. lefttop.Lat += maxlat - minlat;
  35. RectLatLng area = new RectLatLng();
  36. area.LocationTopLeft = lefttop;
  37. area.Size = new SizeLatLng(maxlat - minlat, maxlng - minlng);
  38. this.gmap.SelectedArea = area;
  39. this.gmap.SetZoomToFitRect(area);
  40. }
  41. }
  42. /// <summary>
  43. /// 设置最佳视图
  44. /// </summary>
  45. /// <param name="gMarkers">GMarkers</param>
  46. private void SetPerfectPos(GMap.NET.ObjectModel.ObservableCollectionThreadSafe<GMapMarker> gMarkers)
  47. {
  48. List<PointLatLng> points = new List<PointLatLng>();
  49. foreach (GMapMarker m in gMarkers)
  50. {
  51. points.Add(m.Position);
  52. }
  53. SetPerfectPos(points);
  54. }
  55. #endregion
  56. #region 适应全屏幕
  57. private void btn_ViewAll_ItemClick(object sender, ItemClickEventArgs e)
  58. {
  59. try
  60. {
  61. ///
  62. if (gMapOverlays.Count != 0)//如果没有打开地图文件
  63. {
  64. List<PointLatLng> points = new List<PointLatLng>();
  65. foreach (GMapOverlay overlay in gMapOverlays)
  66. {
  67. if (overlay.Markers.Count != 0)
  68. { points.AddRange(SearchCertainPoint(overlay)); }
  69. }
  70. SetPerfectPos(points);
  71. }
  72. }
  73. catch (Exception ex)
  74. {
  75. WriteLog(ex.Message);
  76. XtraMessageBox.Show(ex.Message);
  77. }
  78. }
  79. /// <summary>
  80. /// 找到图层中的左上和右下的地理点
  81. /// </summary>
  82. /// <returns></returns>
  83. private List<PointLatLng> SearchCertainPoint(GMapOverlay overlay)
  84. {
  85. GMap.NET.ObjectModel.ObservableCollectionThreadSafe<GMapMarker> markers = overlay.Markers;
  86. var minlat = markers.Min(a => a.Position.Lat);
  87. var maxlat = markers.Max(a => a.Position.Lat);
  88. var minlng = markers.Min(a => a.Position.Lng);
  89. var maxlng = markers.Max(a => a.Position.Lng);
  90. PointLatLng lefttop = new PointLatLng(maxlat, minlng);
  91. PointLatLng rightbottom = new PointLatLng(minlat, maxlng);
  92. return new List<PointLatLng>() { lefttop, rightbottom };
  93. }
  94. #endregion

二、测距算法

原理:坐标系的转换和欧式距离的计算

 #region 计算距离
        private const double EARTH_RADIUS = 6378137.0;//地球赤道半径(单位:m。6378137m是1980年的标准,比1975年的标准6378140少3m)
        /// <summary>
        /// 角度数转换为弧度公式
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double radians(double d)
        {
            return d * Math.PI / 180.0;
        }
        /// <summary>
        /// 弧度转换为角度数公式
        /// </summary>
        /// <param name="d"></param>
        /// <returns></returns>
        private static double degrees(double d)
        {
            return d * (180 / Math.PI);
        }
        /// <summary>
        /// 计算两点之间的距离
        /// 单位:米
        /// </summary>
        /// <param name="Degree1"></param>
        /// <param name="Degree2"></param>
        /// <returns></returns>
        public static double GetDistance(PointLatLng PointLatLng1, PointLatLng PointLatLng2)
        {
            double radLat1 = radians(PointLatLng1.Lat);
            double radLat2 = radians(PointLatLng2.Lat);
            double a = radLat1 - radLat2;
            double b = radians(PointLatLng1.Lng) - radians(PointLatLng2.Lng);
            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;
        }
        double CalcDistance(double fromX,double fromY,double toX,double toY)
        {
            double rad = 6371 * 1000; //Earth radius in m
            double p1X = fromX / 180 * Math.PI;
            double p1Y = fromY / 180 * Math.PI;
            double p2X = toX / 180 * Math.PI;
            double p2Y = toY / 180 * Math.PI;
            double d = Math.Acos(Math.Sin(p1Y) * Math.Sin(p2Y) +
                Math.Cos(p1Y) * Math.Cos(p2Y) * Math.Cos(p2X - p1X)) * rad;
            return d;
        }

        public static double GetDistance(double lat1,double lng1, double lat2,double lng2)
        {
            double radLat1 = lat1 * Math.PI / 180;
            double radLat2 = lat2 * Math.PI / 180;
            double a = radLat1 - radLat2;
            double b = lng1 * Math.PI / 180 - lng2 * Math.PI / 180;
            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 * 6378137.0;// 取WGS84标准参考椭球中的地球长半径(单位:m)
            s = Math.Round(s * 10000) / 10000;
            return s;
        }



        /// <summary>
        /// 计算两个经纬度之间的直接距离(google 算法)
        /// </summary>
        public static double GetDistanceGoogle(PointLatLng pointlatlng1, PointLatLng pointlatlng2)
        {
            double radLat1 = radians(pointlatlng1.Lat);
            double radLng1 = radians(pointlatlng1.Lng);
            double radLat2 = radians(pointlatlng2.Lat);
            double radLng2 = radians(pointlatlng2.Lng);
            double s = Math.Acos(Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Cos(radLng1 - radLng2) + Math.Sin(radLat1) * Math.Sin(radLat2));
            s = s * EARTH_RADIUS;
            s = Math.Round(s * 10000) / 10000;
            return s;
        }
        public static double GetDistanceGoogle(double Lat1,double Lng1,double Lat2,double Lng2)
        {
            double radLat1 = radians(Lat1);
            double radLng1 = radians(Lng1);
            double radLat2 = radians(Lat2);
            double radLng2 = radians(Lng2);
            double s = Math.Acos(Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Cos(radLng1 - radLng2) + Math.Sin(radLat1) * Math.Sin(radLat2));
            s = s * EARTH_RADIUS;
            s = Math.Round(s * 10000) / 10000;
            return s;
        }
        /// <summary>
        /// 以一个经纬度为中心计算出四个顶点
        /// </summary>
        /// <param name="Degree1">中心点</param>
        /// <param name="distance">半径(米)</param>
        /// <returns></returns>
        public static PointLatLng[] GetDegreeCoordinates(PointLatLng pointlatlng, double distance)
        {
            double dlng = 2 * Math.Asin(Math.Sin(distance / (2 * EARTH_RADIUS)) / Math.Cos(pointlatlng.Lng));
            dlng = degrees(dlng);//一定转换成角度数
            double dlat = distance / EARTH_RADIUS;
            dlat = degrees(dlat);//一定转换成角度数
            return new PointLatLng[] { new PointLatLng( Math.Round(pointlatlng.Lat + dlat,6),Math.Round(pointlatlng.Lng - dlng,6)),//left-top
                                   new PointLatLng(Math.Round(pointlatlng.Lat- dlat,6),Math.Round(pointlatlng.Lng - dlng,6)),//left-bottom
                                   new PointLatLng( Math.Round(pointlatlng.Lat + dlat,6),Math.Round(pointlatlng.Lng + dlng,6)),//right-top
                                   new PointLatLng(Math.Round(pointlatlng.Lat - dlat,6),Math.Round(pointlatlng.Lng + dlng,6)) //right-bottom
            };
        }
        #endregion

三、查找周围点

 #region 查找周围点操作
        //度 转换成 弧度
        public static double DegreesToRadians(double degrees)
        {
            const double degToRadFactor = Math.PI / 180;
            return degrees * degToRadFactor;
        }
        //弧度 转换成 度
        public static double RadiansToDegrees(double radians)
        {
            const double radToDegFactor = 180 / Math.PI;
            return radians * radToDegFactor;
        }
        /**
        * 求B点经纬度
        * @param A 已知点的经纬度,
        * @param distance   AB两地的距离  单位km
        * @param angle  AB连线与正北方向的夹角(0~360)
        * @return  B点的经纬度
        */
        public static MyLatLng getMyLatLng(MyLatLng A, double distance, double angle)
        {
            double dx = distance * 1000 * Math.Sin(DegreesToRadians(angle));
            double dy = distance * 1000 * Math.Cos(DegreesToRadians(angle));
            double bjd = (dx / A.Ed + A.m_RadLo) * 180 / Math.PI;
            double bwd = (dy / A.Ec + A.m_RadLa) * 180 / Math.PI;
            return new MyLatLng(bjd, bwd);
        }
        /**
        * 求B点经纬度
        * @param A 已知点的经纬度,
        * @param distance   AB两地的距离  单位m
        * @param angle  AB连线与正北方向的夹角(0~360)
        * @return  B点的经纬度
        */
        public static MyLatLng getMyLatLng2(MyLatLng A, double distance, double angle)
        {
            double dx = distance * Math.Sin(DegreesToRadians(angle));
            double dy = distance * Math.Cos(DegreesToRadians(angle));
            double bjd = (dx / A.Ed + A.m_RadLo) * 180 / Math.PI;
            double bwd = (dy / A.Ec + A.m_RadLa) * 180 / Math.PI;
            return new MyLatLng(bjd, bwd);
        }
        //描述:以centerP为圆心,绘制半径为radius的圆
        //gMapControl:Gmap控制器        overlay:图层
        //centerP:圆心点     radius:圆半径(单位:m)
        public static void DrawEllipse2(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, int radius)
        {
            try
            {
                if (radius <= 0)
                    return;
                List<PointLatLng> latLngs = new List<PointLatLng>();
                MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);
                // 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
                for (int i = 0; i < 360; i++)
                {
                    //获取目标经纬度,单位为m
                    MyLatLng tempLatLng = getMyLatLng2(centerLatLng, radius, i);
                    //将自定义的经纬度类 转换成 标准经纬度类
                    PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
                    //通过绘制标记点的方式绘制圆
                    GMapMarker gMapMarker = new GMarkerGoogle(p, GMarkerGoogleType.red);
                    overlay.Markers.Add(gMapMarker);
                }
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
            }
        }
        //描述:以centerP为圆心,绘制半径为radius的圆
        //gMapControl:Gmap控制器        overlay:图层
        //centerP:圆心点     radius:圆半径(单位: km)  name:多边形id
        public static void DrawEllipse2(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, int radius, string name)
        {
            try
            {
                if (radius <= 0)
                    return;
                List<PointLatLng> latLngs = new List<PointLatLng>();
                MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);
                // 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
                for (int i = 0; i < 360; i++)
                {
                    //获取目标经纬度
                    MyLatLng tempLatLng = getMyLatLng2(centerLatLng, radius, i);
                    //将自定义的经纬度类 转换成 标准经纬度类
                    PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
                    latLngs.Add(p);
                }
                //安全性检查
                if (latLngs.Count < 20)
                {
                    return;
                }
                //通过绘制多边形的方式绘制圆
                GMapPolygon gpol = new GMapPolygon(latLngs, name);
                gpol.Stroke = new Pen(System.Drawing.Color.Red, 1.0f);
                gpol.Fill = new SolidBrush(System.Drawing.Color.FromArgb(20, System.Drawing.Color.Red));
                gpol.IsHitTestVisible = true;
                overlay.Polygons.Add(gpol);
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
            }
        }
        //描述:以centerP为圆心,绘制半径为radius的圆
        //gMapControl:Gmap控制器        overlay:图层
        //centerP:圆心点     radius:圆半径(单位: km)  name:多边形id
        public static void DrawEllipse2(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, double radius, string name)
        {
            try
            {
                if (radius <= 0)
                    return;
                List<PointLatLng> latLngs = new List<PointLatLng>();
                MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);
                // 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
                for (int i = 0; i < 360; i++)
                {
                    //获取目标经纬度
                    MyLatLng tempLatLng = getMyLatLng2(centerLatLng, radius, i);
                    //将自定义的经纬度类 转换成 标准经纬度类
                    PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
                    latLngs.Add(p);
                }
                //安全性检查
                if (latLngs.Count < 20)
                {
                    return;
                }
                //通过绘制多边形的方式绘制圆
                GMapPolygon gpol = new GMapPolygon(latLngs, name);
                gpol.Stroke = new Pen(System.Drawing.Color.Red, 1.0f);
                gpol.Fill = new SolidBrush(System.Drawing.Color.FromArgb(20, System.Drawing.Color.Red));
                gpol.IsHitTestVisible = true;
                overlay.Polygons.Add(gpol);
            }
            catch (Exception ex)
            {
                WriteLog(ex.Message);
            }
        }
        private void btnSearch_Click(object sender, EventArgs e)
        {
            try
            {
                currentOverlay.Polygons.Clear();
                searchResultCombox.Properties.Items.Clear();
                string s = txt_centerPos.Text.Trim();
                double radius = Convert.ToDouble(txt_Radius.EditValue);
                string[] centerlatlng = s.Split(new char[] { ',', ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
                PointLatLng centerP = new PointLatLng(Convert.ToDouble(centerlatlng[1]), Convert.ToDouble(centerlatlng[0]));
                DrawEllipse2(this.gmap, currentOverlay, centerP, radius, "Circle");
                foreach (GMapOverlay o in this.gmap.Overlays)
                {
                    string oname = o.Id;
                    foreach (GMapMarker m in o.Markers)
                    {
                        bool flag = isInsidePolygon(m.Position, centerP, radius);
                        if (flag)
                        {
                            string ss = string.Format("{0},{1},{2},{3}", oname, m.ToolTipText.Substring(0, m.ToolTipText.LastIndexOf(':')), m.Position.Lng, m.Position.Lat);
                            searchResultCombox.Properties.Items.Add(ss);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                XtraMessageBox.Show(ex.Message);
                WriteLog(ex.Message);
            }
        }
        private bool isInsidePolygon(PointLatLng p, PointLatLng centerP, double radius)
        {
            bool flag = false;
            double length = GetDistance(p, centerP);
            if (0 < length && length <= radius)
            {
                flag = true;
            }
            return flag;
        }
        private void btnClearResult_Click(object sender, EventArgs e)
        {
            txt_centerPos.EditValue = null;
            txt_Radius.Text = null;
            searchResultCombox.Properties.Items.Clear();
            searchResultCombox.Text = null;
            if (this.gmap.Overlays.Count != 0)
            {
                foreach (GMapOverlay o in this.gmap.Overlays)
                {
                    if (o.Polygons.Count != 0)
                    {
                        o.Polygons.Clear();
                    }
                }
            }
        }
        #endregion

四、GPS纠偏算法

 #region GPS纠偏算法
        /**
        * gps纠偏算法,适用于google,高德体系的地图
        */
        //public static double pi = 3.1415926535897932384626;
        public static double x_pi = 3.14159265358979324 * 3000.0 / 180.0;
        public static double a = 6378245.0;
        public static double ee = 0.00669342162296594323;
        public 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;
        }
        public 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;
        }
        /// <summary>
        /// 纠偏GCJ02之后
        /// </summary>
        /// <param name="lat">WGS84下纬度</param>
        /// <param name="lon">WGS84下经度</param>
        /// <returns>double[0]=lat,double[1]=lng</returns>
        public static double[] transform(double lat, double lon)
        {
            if (outOfChina(lat, lon))
            {
                return new double[] { lat, lon };
            }
            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = 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);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
            double mgLat = lat + dLat;
            double mgLon = lon + dLon;
            return new double[] { mgLat, mgLon };
        }
        public static bool 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;
        }
        /** 
         * 84 to 火星坐标系 (GCJ-02) World Geodetic System ==> Mars Geodetic System 
         * 
         * @param lat 
         * @param lon 
         * @return 
         */
        public static double[] gps84_To_Gcj02(double lat, double lon)
        {
            if (outOfChina(lat, lon))
            {
                return new double[] { lat, lon };
            }
            double dLat = transformLat(lon - 105.0, lat - 35.0);
            double dLon = transformLon(lon - 105.0, lat - 35.0);
            double radLat = 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);
            dLon = (dLon * 180.0) / (a / sqrtMagic * Math.Cos(radLat) * pi);
            double mgLat = lat + dLat;
            double mgLon = lon + dLon;
            return new double[] { mgLat, mgLon };
        }
        /** 
         * * 火星坐标系 (GCJ-02) to 84 * * @param lon * @param lat * @return 
         * */
        public static double[] gcj02_To_Gps84(double lat, double lon)
        {
            double[] gps = transform(lat, lon);
            double lontitude = lon * 2 - gps[1];
            double latitude = lat * 2 - gps[0];
            return new double[] { latitude, lontitude };
        }
        /** 
         * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 将 GCJ-02 坐标转换成 BD-09 坐标 
         * 
         * @param lat 
         * @param lon 
         */
        public static double[] gcj02_To_Bd09(double lat, double lon)
        {
            double x = lon, y = lat;
            double z = Math.Sqrt(x * x + y * y) + 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) + 0.000003 * Math.Cos(x * x_pi);
            double tempLon = z * Math.Cos(theta) + 0.0065;
            double tempLat = z * Math.Sin(theta) + 0.006;
            double[] gps = { tempLat, tempLon };
            return gps;
        }
        /** 
         * * 火星坐标系 (GCJ-02) 与百度坐标系 (BD-09) 的转换算法 * * 将 BD-09 坐标转换成GCJ-02 坐标 * * @param 
         * bd_lat * @param bd_lon * @return 
         */
        public static double[] bd09_To_Gcj02(double lat, double lon)
        {
            double x = lon - 0.0065, y = lat - 0.006;
            double z = Math.Sqrt(x * x + y * y) - 0.00002 * Math.Sin(y * x_pi);
            double theta = Math.Atan2(y, x) - 0.000003 * Math.Cos(x * x_pi);
            double tempLon = z * Math.Cos(theta);
            double tempLat = z * Math.Sin(theta);
            double[] gps = { tempLat, tempLon };
            return gps;
        }
        /**将gps84转为bd09 
         * @param lat 
         * @param lon 
         * @return 
         */
        public static double[] gps84_To_bd09(double lat, double lon)
        {
            double[] gcj02 = gps84_To_Gcj02(lat, lon);
            double[] bd09 = gcj02_To_Bd09(gcj02[0], gcj02[1]);
            return bd09;
        }
        public static double[] bd09_To_gps84(double lat, double lon)
        {
            double[] gcj02 = bd09_To_Gcj02(lat, lon);
            double[] gps84 = gcj02_To_Gps84(gcj02[0], gcj02[1]);
            //保留小数点后六位  
            gps84[0] = retain6(gps84[0]);
            gps84[1] = retain6(gps84[1]);
            return gps84;
        }
        /**保留小数点后六位 
         * @param num 
         * @return 
         */
        private static double retain6(double num)
        {
            string result = String.Format("%.6f", num);
            return Convert.ToDouble(result);
        }
        #endregion