基于winform的GIS离线地图

 基于winform的离线地图项目

1.下载GMap(一个国外开源控件,codeplex有源码),不了解的百度一下,

2.项目引入GMap.NET.Core和GMap.NET.WindowsForms

3.工具箱添加GMap控件,把GMapControl控件拖到新建窗体

4.窗体加载事件初始化该控件的属性或事件,OK!


一、加载地图

private void Form1_Load(object sender, EventArgs e)
        {
            gmap.BackColor = Color.Red;

            //gmap.CacheLocation = Environment.CurrentDirectory + "\\GMapCache\\DataExp.gmdb"; //缓存位置
            //设置控件的管理模式 (缓存、联网)
            //gmap.Manager.Mode = AccessMode.CacheOnly;
            gmap.Manager.Mode = AccessMode.ServerOnly;

            //设置控件显示的地图来源  
            //gmap.MapProvider = AMapSateliteProvider.Instance;
            //gmap.MapProvider = AMapProvider.Instance;
            //gmap.MapProvider = GMapProviders.GoogleChinaMap;
            gmap.MapProvider = AMapProvider.Instance;

            //载入离线缓存
            GMaps.Instance.ImportFromGMDB(Application.StartupPath + "\\GMapCache\\DataExp.gmdb");


            //设置控件显示的当前中心位置  
            // WGS84坐标系,即地球坐标系(通用坐标系)
            // =》 经过国家测绘局要求采用GCJ02算法加偏后即为“火星坐标”(Google中国、腾讯和高德)
            // =》百度在“火星坐标”的基础上又采用了自己的加偏算法BD09加偏后,得到“百度坐标”(搜狗、图吧都是)
            gmap.Position = new PointLatLng(30.606726, 114.424348);
            //gmap.Position = new PointLatLng(21.5053134635657, 67.8822576999664);//百度(BD09坐标)

            gmap.MaxZoom = 16;
            gmap.MinZoom = 3;
            gmap.Zoom = 13;

            //不显示中心十字点
            gmap.ShowCenter = false;

            //左键拖拽地图
            gmap.DragButton = MouseButtons.Left;


            gmap.Overlays.Add(_markersOverlay);
            gmap.Overlays.Add(_polygons);
            gmap.Overlays.Add(objects);

            gmap.MouseClick += mapControl_MouseClick; //右键添加标记
            gmap.MouseDoubleClick += mapControl_DoubleClick; //右键添加标记

            gmap.OnMarkerClick += gmap_OnMarkerClick;
            gmap.OnMarkerClick2 += gmap_OnMarkerClick2;

        }



gmap.MapProvider = GMapProviders.GoogleChinaMap; 默认控件加载的地图图层是谷歌中国,要想加载国内的高德、百度等图层,就要编写一个图层源的类。


高德:

AMapProviderBase

 public abstract class AMapProviderBase : GMapProvider
    {
        public AMapProviderBase()
        {
            MaxZoom = null;
            RefererUrl = "http://www.amap.com/";
            //Copyright = string.Format("©{0} 高德 Corporation, ©{0} NAVTEQ, ©{0} Image courtesy of NASA", DateTime.Today.Year);    
        }

        public override PureProjection Projection
        {
            get { return MercatorProjection.Instance; }
        }

        GMapProvider[] overlays;
        public override GMapProvider[] Overlays
        {
            get
            {
                if (overlays == null)
                {
                    overlays = new GMapProvider[] { this };
                }
                return overlays;
            }
        }
    }

AMapProvider

public class AMapProvider : AMapProviderBase
    {
        public static readonly AMapProvider Instance;

        readonly Guid id = new Guid("EF3DD303-3F74-4938-BF40-232D0595EE88");
        public override Guid Id
        {
            get { return id; }
        }

        readonly string name = "AMap";
        public override string Name
        {
            get
            {
                return name;
            }
        }

        static AMapProvider()
        {
            Instance = new AMapProvider();
        }

        public override PureImage GetTileImage(GPoint pos, int zoom)
        {
            try
            {
                string url = MakeTileImageUrl(pos, zoom, LanguageStr);
                return GetTileImageUsingHttp(url);
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        string MakeTileImageUrl(GPoint pos, int zoom, string language)
        {
            var num = (pos.X + pos.Y) % 4 + 1;
            //string url = string.Format(UrlFormat, num, pos.X, pos.Y, zoom);
            string url = string.Format(UrlFormat, pos.X, pos.Y, zoom);
            return url;
        }

        //static readonly string UrlFormat = "http://webrd04.is.autonavi.com/appmaptile?x={0}&y={1}&z={2}&lang=zh_cn&size=1&scale=1&style=7";
        //static readonly string UrlFormat = "http://webrd01.is.autonavi.com/appmaptile?lang=zh_cn&size=1&scale=1&style=7&x={0}&y={1}&z={2}";
        static readonly string UrlFormat = "http://localhost:8081/788865972/{2}/{0}/{1}.png"; //本地部署的GIS服务
    }


百度:

/// <summary>
    /// 百度地图(BD09坐标)
    /// 转换:http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition
    /// </summary>
    public class BaiduMapProvider : BaiduMapProviderBase
    {
        readonly string name = "BaiduMap";
        public static readonly BaiduMapProvider Instance;
        readonly Guid id = new Guid("47C1561B-C785-4EBF-9EC3-2CF0E416E219");

        static BaiduMapProvider()
        {
            Instance = new BaiduMapProvider();
        }

        public override Guid Id
        {
            get { return id; }
        }

        public override string Name
        {
            get
            {
                return name;
            }
        }

        public override PureImage GetTileImage(GPoint pos, int zoom)
        {
            string url = MakeTileImageUrl(pos, zoom, LanguageStr);

            return GetTileImageUsingHttp(url);
        }

        string MakeTileImageUrl(GPoint pos, int zoom, string language)
        {
            zoom = zoom - 1;
            var offsetX = Math.Pow(2, zoom);
            var offsetY = offsetX - 1;

            var numX = pos.X - offsetX;
            var numY = -pos.Y + offsetY;

            zoom = zoom + 1;

            var num = (pos.X + pos.Y) % 8 + 1;
            var x = numX.ToString().Replace("-", "M");
            var y = numY.ToString().Replace("-", "M");

            //原来:http://q3.baidu.com/it/u=x=721;y=209;z=12;v=014;type=web&fm=44
            //更新:http://online1.map.bdimg.com/tile/?qt=tile&x=23144&y=6686&z=17&styles=pl
            //string url = string.Format(UrlFormat, num, x, y, zoom, "014", "web", "44"); 
            string url = string.Format(UrlFormat, x, y, zoom);
            return url;
        }

        //static readonly string UrlFormat = "http://q{0}.baidu.com/it/u=x={1};y={2};z={3};v={4};type={5}&fm={6}";
        static readonly string UrlFormat = "http://online1.map.bdimg.com/tile/?qt=tile&x={0}&y={1}&z={2}&styles=pl";

    }

引用: gmap.MapProvider = AMapProvider.Instance;


二、自定义Marker

 
[Serializable]
    public class GMapMarkerCircle : GMapMarker, ISerializable
    {
        /// <summary>
        /// 实际半径距离,单位为米
        /// </summary>
        public double RawRadius;

        /// <summary>
        /// specifies how the outline is painted
        /// </summary>
        [NonSerialized]
        public Pen Stroke = new Pen(Color.FromArgb(155, Color.MidnightBlue));

        /// <summary>
        /// background color
        /// </summary>
        [NonSerialized]
        public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.AliceBlue));

        /// <summary>
        /// is filled
        /// </summary>
        public bool IsFilled = true;

        public GMapMarkerCircle(PointLatLng p, int radius)
            : base(p)
        {
           
            //IsHitTestVisible = false;
        }

        public override void OnRender(Graphics g)
        {
            //将距离转换成像素长度
            int R = (int)(RawRadius / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat)) * 2;
           
            if (IsFilled)
            {
                g.FillEllipse(Fill, new Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R));
            }
            g.DrawEllipse(Stroke, new Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R));
        }

        public override void Dispose()
        {
            if (Stroke != null)
            {
                Stroke.Dispose();
                Stroke = null;
            }

            if (Fill != null)
            {
                Fill.Dispose();
                Fill = null;
            }

            base.Dispose();
        }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);

            // TODO: Radius, IsFilled
        }

        protected GMapMarkerCircle(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
            // TODO: Radius, IsFilled
        }

        #endregion
    }

矩形:

[Serializable]
    public class GMapMarkerRect : GMapMarker, ISerializable
    {
        [NonSerialized]
        public Pen Stroke=new Pen(Brushes.Blue);

        [NonSerialized]
        public GMarkerGoogle InnerMarker;

        [NonSerialized]
        public int BorderWidth =5;

        [NonSerialized]
        public Size RectSize =new Size(1000, 1000);

        public GMapMarkerRect(PointLatLng p)
            : base(p)
        {
            //IsHitTestVisible = false;
            Stroke.Width= BorderWidth;

            // do not forget set Size of the marker
            // if so, you shall have no event on it ;}
        }

        public override void OnRender(Graphics g)
        {
            //将距离转换成像素长度
            int R = (int)(RectSize.Width / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat));

            //每次重新渲染的时候,重新计算Marker的大小和偏移。OnMarkerClick事件按Size和Offset的Marker来进行触发
            Offset = new Point(-R / 2, -R / 2); 
            Size = new Size(R, R);

            g.DrawRectangle(Stroke, new Rectangle(LocalPosition.X , LocalPosition.Y , R, R));
        }

        public override void Dispose()
        {
            if (Stroke != null)
            {
                Stroke.Dispose();
                Stroke = null;
            }

            if (InnerMarker != null)
            {
                InnerMarker.Dispose();
                InnerMarker = null;
            }

            base.Dispose();
        }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }

        protected GMapMarkerRect(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        #endregion
    }

扇形:

 [Serializable]
    public class GMapMarkerSector : GMapMarker, ISerializable
    {
        [NonSerialized]
        public Pen Stroke = new Pen(Brushes.Blue);

        [NonSerialized]
        public GMarkerGoogle InnerMarker;

        [NonSerialized]
        public int BorderWidth = 3;

        //[NonSerialized]
        //public int Angle = 90;

        [NonSerialized]
        public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.Aqua));

        [NonSerialized]
        public int RawRadius = 100;

        public GMapMarkerSector(PointLatLng p, int radius)
            : base(p)
        {
            //IsHitTestVisible = false;
            Radius = RawRadius = radius;
            //Size = new Size(RawRadius / 2, RawRadius / 2);
        }

        public override void OnRender(Graphics g)
        {
            int R = (int)(RawRadius*2 / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat)) * 2;
            Radius = R;
            
            g.FillPie(Fill, new Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R), (float)(-90 + (FwAngle - Angle)), Angle * 2);
            g.DrawPie(Stroke, new Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R), (float)(-90 + (FwAngle - Angle)), Angle * 2);
        }

        public override void Dispose()
        {
            if (Stroke != null)
            {
                Stroke.Dispose();
                Stroke = null;
            }
            if (Fill != null)
            {
                Fill.Dispose();
                Fill = null;
            }
            if (InnerMarker != null)
            {
                InnerMarker.Dispose();
                InnerMarker = null;
            }
            base.Dispose();
        }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }

        protected GMapMarkerSector(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        #endregion

    }

箭头:

 [Serializable]
    public class GMarkerArrow : GMapMarker, ISerializable
    {
        [NonSerialized]
        public Brush Fill = new SolidBrush(Color.FromArgb(155, Color.Blue));

        //[NonSerialized]
        //public Pen Pen = new Pen(Brushes.Blue, 5);

        static readonly Point[] Arrow = { new Point(-7, 7), new Point(0, -22), new Point(7, 7), new Point(0, 2) };

        public float Bearing = 0;
        private float scale = 1;

        public float Scale
        {
            get
            {
                return scale;
            }
            set
            {
                scale = value;

                Size = new Size((int)(14 * scale), (int)(14 * scale));
                Offset = new Point(-Size.Width / 2, (int)(-Size.Height / 1.4));
            }
        }

        public GMarkerArrow(PointLatLng p)
            : base(p)
        {
            Scale = 1;
        }

        public override void OnRender(Graphics g)
        {
            //g.DrawRectangle(Pen, new System.Drawing.Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height));
            {
                g.TranslateTransform(ToolTipPosition.X, ToolTipPosition.Y);
                var c = g.BeginContainer();
                {
                    g.RotateTransform(Bearing - Overlay.Control.Bearing);
                    g.ScaleTransform(Scale, Scale);

                    g.FillPolygon(Fill, Arrow);
                }
                g.EndContainer(c);
                g.TranslateTransform(-ToolTipPosition.X, -ToolTipPosition.Y);
            }
        }

        public override void Dispose()
        {
            //if(Pen != null)
            //{
            //   Pen.Dispose();
            //   Pen = null;
            //}

            if (Fill != null)
            {
                Fill.Dispose();
                Fill = null;
            }

            base.Dispose();
        }

        #region ISerializable Members

        void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
        }

        protected GMarkerArrow(SerializationInfo info, StreamingContext context)
            : base(info, context)
        {
        }

        #endregion
    }

调用

  //画圆
        void AddCircle(PointLatLng point)
        {
            var cc = new GMapMarkerCircle(point, 1000)
            {
                //背景色填充
                Fill = new SolidBrush(Color.FromArgb(100, Color.CadetBlue)),
                //边框颜色
                Stroke = new Pen(Color.FromArgb(100, Color.Aqua)),
                ToolTipText = "测试圆",
                ToolTipMode = MarkerTooltipMode.OnMouseOver,
                IsCircle = true
            };
            objects.Markers.Add(cc);
        }

        //画矩形
        void AddRect(PointLatLng point)
        {
            GMapMarkerRect mBorders = new GMapMarkerRect(point)
            {
                ToolTipMode = MarkerTooltipMode.OnMouseOver,
                ToolTipText = "123",
                //滚轮放大放小地图不受影响
                //IsHitTestVisible = false,
                BorderWidth = 1,
                Stroke = new Pen(Brushes.DarkCyan)
            };
            objects.Markers.Add(mBorders);
        }

        //画箭头
        void AddArrow(PointLatLng point)
        {
            GMapMarker marker = new GMarkerArrow(point)
            {
                Fill = new SolidBrush(Color.FromArgb(255, Color.Coral)),
                Scale = 2,
                Bearing = 2
            };
            objects.Markers.Add(marker);
        }

        //画扇形
        void AddSector(PointLatLng point)
        {
            GMapMarkerSector st = new GMapMarkerSector(point,1000)
            {
                //填充颜色
                Fill = new SolidBrush(Color.FromArgb(100, Color.CadetBlue)),
                //边框颜色、宽度
                Stroke = new Pen(Color.FromArgb(100, Color.DodgerBlue), 1),
                Angle = 60,
                FwAngle = 0,
                Radius = 1000,
                IsSector = true,
                ToolTipMode = MarkerTooltipMode.OnMouseOver,
                ToolTipText = "123",
            };
            _markersOverlay.Markers.Add(st);
        }

三、GMap机制和重写

1.GMarker底层机制默认IsHitTestVisible=true,导致鼠标在Marker上的时候拖动不了地图图层和滚轮缩放地图。个人之前开发惯B端地图项目,觉得这是一个很不好的体验。改改改,GMapControl改底层事件

2.GMarker底层区域是一个矩形,无论你自定义什么样的图形(圆、扇形)。它的底层捕捉都是基于GMarker的Size属性所画一个矩形区域,所有导致圆形、扇形这些图形的地图点击事件范围扩大成一个矩形,这个不是我想要的效果,而且当marker集中在一个区域的时候这个问题将会放大!so,重写点击事件机制

3.重写ToolTipText提示文本显示,GMapToolTip和GMapRoundedToolTip这两个类

4.修改GMarker点击事件,原来只返回一个GMarker对象,重写后返回匹配的所有GMarker列表。

 gmap.OnMarkerClick2 += gmap_OnMarkerClick2;
void gmap_OnMarkerClick2(List<GMapMarker> item, MouseEventArgs e){}

下载地址



  • 2
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值