GIS常用

打造地图拼接利器(四)数据交互

2021-06-27  本文已影响0人  安静的林哥

这里的数据交互,主要指在地图上可以选择一个范围,这个范围可以调节,同时返回所选范围的经纬度值。

GMap.net提供一个绘制矩形的函数,但我们还需要加入一些控制点,用来随意调整区域的大小和位置。内置函数GMapPolygon可以生成一个矩形对象,然后添加到地图上。

新建一个类SelectArea,将地图控件作为构造函数的参数传入。

  public SelectArea(GMapControl control)
        {
            this.control = control;
            //获取两个层,分别用于放置区域和控制点,如果没有,测创建
            InitOverlay(control);
            //绑定事件
            InitEvent(control);
        }

同时,生成两个层,分别用来放置图形和控制点。这也是我们制作标绘的思路,即通过控制点,生成复杂图形。

 /// <summary>
        /// 初始化图层,拖动层和显示层,如果有则不创建
        /// </summary>
        /// <param name="control"></param>
        private void InitOverlay(GMapControl control)
        {
            bool haspolygons = false, hasdrags = false;
            foreach (GMapOverlay overlay in control.Overlays)
            {
                if (overlay.Id.Equals("polygons"))
                {
                    haspolygons = true;
                    this.polygonOverlay = overlay;
                    continue;
                }
                if (overlay.Id.Equals("drags"))
                {
                    hasdrags = true;
                    this.dragOverlay = overlay;
                    break;
                }
            }
            if (!haspolygons)
            {
                polygonOverlay = new GMapOverlay("polygons");
                control.Overlays.Insert(0, polygonOverlay);
            }
            if (!hasdrags)
            {
                dragOverlay = new GMapOverlay("drags");
                control.Overlays.Add(dragOverlay);
            }
        }

在类中设置左上和右下两个关键点P1、P2,绑定鼠标按下、移动和抬起事件。当鼠标按下时,记录第一个点,当鼠标移动时,更新第二个点,当鼠标抬起时,停止更新,同步在polygons层里绘制矩形。

 /// <summary>
        /// 根据2个关键点坐标,获取矩形坐标
        /// </summary>
        /// <param name="p1"></param>
        /// <param name="p2"></param>
        /// <returns></returns>
        List<PointLatLng> GetPolygonPoints(PointLatLng p1, PointLatLng p2)
        {
            return new List<PointLatLng>(){
                new PointLatLng(p1.Lat,p1.Lng),
                new PointLatLng(p1.Lat,p2.Lng),
                new PointLatLng(p2.Lat,p2.Lng),
                new PointLatLng(p2.Lat,p1.Lng)
            };
        }

鼠标抬起后,生成控制点。这里需要说明,其实控制点也是一个polygon矩形,只不过比较小,再加上描边效果,看起来像一个控制柄。控制点有3个,p1、p2和中点,分别为drag1、drag2和dragcenter,每个控制点根据中心坐标,算出边距为10的小矩形。

Polygon对象有一个.IsMouseOver属性,可以判断是否鼠标点击在上面,但实测不好使,所以写了一个检测函数,用来判断控制点是否选中:

  /// <summary>
        /// 判断点是否在区域范围内
        /// </summary>
        /// <param name="p"></param>
        /// <param name="pm"></param>
        /// <returns></returns>
        bool isInside(GPoint p, PointLatLng pm,int radius)
        {
            bool isinside = false;
            GPoint pa = control.FromLatLngToLocal(pm);
            if (p.X > pa.X - radius && p.X < pa.X + radius && p.Y > p.Y - radius && p.Y < pa.Y + radius)
            {
                isinside = true;
            }
            return isinside;
        }

当鼠标按下时,判断选择哪个控制点,并用state标记:

    void control_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            control.DragButton = System.Windows.Forms.MouseButtons.Right;
            isDrag = true;
            if (polygon == null&&state==0)
            {
                p1=control.FromLocalToLatLng(e.X, e.Y);
                p2=control.FromLocalToLatLng(e.X, e.Y);
                List<PointLatLng> points = GetPolygonPoints(p1, p2);
                polygon = new GMapPolygon(points, "polygon");
                polygon.Stroke =new Pen( new SolidBrush(Color.Red),3);
                polygonOverlay.Polygons.Add(polygon);
            }
            if (drag1 != null && isInside(new GPoint(e.X, e.Y), p1,5))
            {
                state = 1;
            }
            if (drag2 != null && isInside(new GPoint(e.X, e.Y), p2, 5))
            {
                state = 2;
            }
            if (dragcenter != null && isInside(new GPoint(e.X, e.Y), GetDragCenterPointsLatLng(p1, p2), 5))
            {
                state = 3;
            }


        }

添加一个代理事件,用于在矩形变化时将坐标返回主界面的左侧区域。

\\类外:
public  delegate  void  showInfo(SelectInfo selectinfo);
\\类内:
 public  event  showInfo MyShowInfo;
[\\mouseMove](file://mouseMove)事件中回馈
   SelectInfo cinfo = new SelectInfo();
                cinfo.StartPoint = p1;
                cinfo.EndPoint = p2;
                MyShowInfo(cinfo);

最终效果如下图:


控制点效果图
上一篇下一篇

猜你喜欢

热点阅读