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);
            }

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM