• GMap.NET开发技巧 开发可以根据地图放大缩小而缩放的图元


    在GMap.NET 当中,我们可以自定义Marker,进行画圆形、矩形和多边形等操作,这个功能在GPS软件中很重要,需要基于此功能设置区域,就是我们常说的电子围栏。但是很多人做的时候,是基于窗口像素来进行画图操作,这样会造成画图的时候,严重失真,因为同一个像素长度,在不同的Zoom比例尺下,换算成地图距离是不一样的。这样会造成画出来的电子围栏非常不准确,再次打开地图重新加载的时候,围栏可能变大或者变小。

    所以我们在保存图元的时候,例如保存一个圆,需要一个圆心和半径,半径需要保存的不是像素长度,而是地图距离,然后再加载图元的时候,在图元渲染函数里,将距离根据当前地图的Zoom值换算成像素长度,这样图元就可以根据不同的Zoom而缩放了。

     如下是圆形Marker的源码:

    namespace GpsNET.Marker
    {
       [Serializable]
       public class GMapMarkerCircle : GMapMarker, ISerializable
       {
          /// <summary>
          /// 距离,单位为米
          /// </summary>
          public int Radius;
    
          /// <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 _raidus)
             : base(p)
          {
              Radius = _raidus; // 100m
             IsHitTestVisible = false;
          }
    
          public override void OnRender(Graphics g)
          {
             //将距离转换成像素长度
             int R = (int)((Radius) / Overlay.Control.MapProvider.Projection.GetGroundResolution((int)Overlay.Control.Zoom, Position.Lat)) * 2;
    
             if(IsFilled)
             {
                g.FillEllipse(Fill, new System.Drawing.Rectangle(LocalPosition.X - R / 2, LocalPosition.Y - R / 2, R, R));
             }
             g.DrawEllipse(Stroke, new System.Drawing.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
       }
    }
    

      这样我们在MouseMove事件中,需要不断的换算出当前点和初始点之间的地图距离,然后生成图元,就随着鼠标移动,而画出不同大小的圆了。

    if (MapClickAction == MAP_ACTION_ENCLOSURE_CIRCLE && e.Button == MouseButtons.Left)
                {
                    //在鼠标移动的时候,画矩形选择框
                    int w = e.X - originX;
                    int h = e.Y - originY;
                    tempOverlay.Markers.Clear(); //擦出掉以前的marker
    
                    //换算成以米为单位的距离
                    int radius = (int)distanceByMeter(lastPosition, latLng);
    
                    lastCircleMarker = new GMapMarkerCircle(lastPosition, radius);
                    tempOverlay.Markers.Add(lastCircleMarker);
                }
    

      

    我的微信号: jt808_com 添加微信
  • 相关阅读:
    linux-centos7-vmware 虚拟机 设置静态 ip 地址,采用 nat 模式,实现连接公网
    mysql_5.7.20 二进制包 在Linux系统中的 安装和配置
    解决windows系统80端口被占用问题
    应用系统架构演变初探
    fastdfs-nginx扩展模块源码分析
    心已落定,入驻博客园
    mac iterm 提示符序列调整
    Background removal with deep learning
    git push fatal: The remote end hung up unexpectedly
    mac sed 使用踩坑实录
  • 原文地址:https://www.cnblogs.com/productivity/p/3115837.html
Copyright © 2020-2023  润新知