DragPolygon and IsMouseOverPolygon

Topics: Windows Forms
Jun 28, 2012 at 3:35 PM
Edited Aug 9, 2012 at 9:09 PM

Hi radioman,

I'm in need of drag a polygon instead of the entire map, so I managed to implement this functionality and I'll show it here, so you can use my coding, if you want.

It'd be great if I could contribute to your project.

So, first I added the property "IsMouseOverPolygon" to GMap.NET.WindowsForms.GMapControl, as follows:

      /// <summary>
      /// is mouse over polygon
      /// </summary>
      [DesignerSerializationVisibility( DesignerSerializationVisibility.Hidden )]
      [Browsable( false )]
      public bool IsMouseOverPolygon { get; set; }

To maintain compatibility with already implemented maps, I added another property to GMap.NET.WindowsForms.GMapControl:

      /// <summary>
      /// if the mouse is over a polygon when drag, the polygon will be gragged instead of the map
      /// </summary>
      [Category( "GMap.NET" )]
      public bool CanDragPolygon { get; set; }

Now, I need to implement the check of the polygon under mouse pointer and drag of the polygon instead of the map. So I added three variables to the code:

 

PointLatLng lastDragPolygon = PointLatLng.Empty;
Cursor cursorDragBefore = Cursors.Default;
List<GMapPolygon> movingPolygons = new List<GMapPolygon>();

 

With that I can store the last drag point, the previous cursor, so it it won't conflict with hit test cursor, and the polygons to move.

Then I modified the follwoing methods:

GMap.NET.WindowsForms.GMapControl.OnMouseDown:

 

protected override void OnMouseDown(MouseEventArgs e)
      {
         if(!IsMouseOverMarker && (!CanDragPolygon || !IsMouseOverPolygon))//let the map be dragged if cannot drag polygon or ther isn't any under the mouse
         {
#if !PocketPC
            if(e.Button == DragButton && CanDragMap)
#else
            if (CanDragMap)
#endif
            {
#if !PocketPC
               Core.mouseDown = ApplyRotationInversion(e.X, e.Y);
#else
               Core.mouseDown = new GPoint(e.X, e.Y);
#endif
               this.Invalidate();
            }
            else if(!isSelected && !DisableSelectArea)
            {
               isSelected = true;
               SelectedArea = RectLatLng.Empty;
               selectionEnd = PointLatLng.Empty;
               selectionStart = FromLocalToLatLng(e.X, e.Y);
            }
         }
         else if ( CanDragPolygon && IsMouseOverPolygon )//if I can drag the polygons and I have at least one under the mouse
         {
             lastDragPolygon = FromLocalToLatLng(e.X, e.Y);//mark the initial point
#if !PocketPC
             cursorDragBefore = this.Cursor;//store current cursor using the alternative variable
             this.Cursor = Cursors.SizeAll;//change the cursor to sizeall
#endif
         }

         base.OnMouseDown(e);
      }

 

GMap.NET.WindowsForms.GMapControl.OnMouseUp:

 

protected override void OnMouseUp(MouseEventArgs e)
      {
         base.OnMouseUp(e);

         if(isSelected)
         {
            isSelected = false;
         }
         //clans every polygon used variable to maintain normal behaviour
         if ( !lastDragPolygon.IsEmpty )
         {
             lastDragPolygon = PointLatLng.Empty;
#if !PocketPC
             this.Cursor = cursorDragBefore;
#endif
             movingPolygons.Clear();
         }

         if(Core.IsDragging)
         {
            if(isDragging)
            {
               isDragging = false;
               Debug.WriteLine("IsDragging = " + isDragging);
#if !PocketPC
               this.Cursor = cursorBefore;
               cursorBefore = null;
#endif
            }
            Core.EndDrag();

            if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
            {
               if(Core.LastLocationInBounds.HasValue)
               {
                  Position = Core.LastLocationInBounds.Value;
               }
            }
         }
         else
         {
#if !PocketPC
            if(e.Button == DragButton)
            {
               Core.mouseDown = GPoint.Empty;
            }

            if(!selectionEnd.IsEmpty && !selectionStart.IsEmpty)
            {
               if(!SelectedArea.IsEmpty && Form.ModifierKeys == Keys.Shift)
               {
                  SetZoomToFitRect(SelectedArea);
               }
            }
            else
            {
               Invalidate();
            }
#endif
         }
      }

 

GMap.NET.WindowsForms.GMapControl.OnMouseMove:

      protected override void OnMouseMove(MouseEventArgs e)
      {
         if(!Core.IsDragging && !Core.mouseDown.IsEmpty && lastDragPolygon.IsEmpty) //let drag the map if the lastPolygon wasn't set
         {
#if PocketPC
                GPoint p = new GPoint(e.X, e.Y);
#else
            GPoint p = ApplyRotationInversion(e.X, e.Y);
#endif
            if(Math.Abs(p.X - Core.mouseDown.X) * 2 >= DragSize.Width || Math.Abs(p.Y - Core.mouseDown.Y) * 2 >= DragSize.Height)
            {
               Core.BeginDrag(Core.mouseDown);
            }
         }
         else if ( !lastDragPolygon.IsEmpty )
         {
             //if I don't have any polygons to move yet
             if(movingPolygons.Count == 0)
             {
                  //gather them through the layers
                  foreach (GMapOverlay layer in Overlays)
                  {
                      //and through the polygons
                      foreach ( GMapPolygon poly in layer.Polygons )
                      {
                          if ( poly.IsMouseOver )
                          {
                              movingPolygons.Add( poly );
                          }
                      }
                  }
             }
                       
             //grab mouse current position
             PointLatLng mouse = FromLocalToLatLng( e.X, e.Y );
             List<PointLatLng> points;

             //loop through moving polygons
             foreach ( GMapPolygon poly in movingPolygons )
             {
                 //copy each point to a new array
                 points = new List<PointLatLng>( poly.Points );
                 //clears the original, so we can put new values to them
                 poly.Points.Clear();

                 //and chage every point
                 foreach (PointLatLng point in points)
	             {
                     //move to correct position
                     point.Offset( -(mouse.Lat - lastDragPolygon.Lat), mouse.Lng - lastDragPolygon.Lng );
                     poly.Points.Add( point );
	             }

                 //update that polygon position
                 this.UpdatePolygonLocalPosition( poly );
             }

             lastDragPolygon = mouse;

             base.Invalidate();
         }

         if(Core.IsDragging)
         {
            if(!isDragging)
            {
               isDragging = true;
               Debug.WriteLine("IsDragging = " + isDragging);

#if !PocketPC
               cursorBefore = this.Cursor;
               this.Cursor = Cursors.SizeAll;
#endif
            }

            if(BoundsOfMap.HasValue && !BoundsOfMap.Value.Contains(Position))
            {
               // ...
            }
            else
            {
#if !PocketPC
               Core.mouseCurrent = ApplyRotationInversion(e.X, e.Y);
#else
                    Core.mouseCurrent = new GPoint(e.X, e.Y);
#endif
               Core.Drag(Core.mouseCurrent);

#if !PocketPC
               if(MobileMode)
               {
                  ForceUpdateOverlays();
               }
#else
                    ForceUpdateOverlays();
#endif

               base.Invalidate();
            }
         }
         else
         {
#if !PocketPC
            if(isSelected && !selectionStart.IsEmpty && (Form.ModifierKeys == Keys.Alt || Form.ModifierKeys == Keys.Shift || DisableAltForSelection))
            {
               selectionEnd = FromLocalToLatLng(e.X, e.Y);
               {
                  GMap.NET.PointLatLng p1 = selectionStart;
                  GMap.NET.PointLatLng p2 = selectionEnd;

                  double x1 = Math.Min(p1.Lng, p2.Lng);
                  double y1 = Math.Max(p1.Lat, p2.Lat);
                  double x2 = Math.Max(p1.Lng, p2.Lng);
                  double y2 = Math.Min(p1.Lat, p2.Lat);

                  SelectedArea = new RectLatLng(y1, x1, x2 - x1, y1 - y2);
               }
            }
            else
#endif
               if(Core.mouseDown.IsEmpty)
               {
                 //remove any trace of polygons under the mouse pointer
                 IsMouseOverPolygon = false;

                  for(int i = Overlays.Count - 1; i >= 0; i--)
                  {
                     GMapOverlay o = Overlays[i];
                     if(o != null && o.IsVisibile)
                     {
                        foreach(GMapMarker m in o.Markers)
                        {
                           if(m.IsVisible && m.IsHitTestVisible)
                           {
                              #region -- check --
#if !PocketPC
                              if((MobileMode && m.LocalArea.Contains(e.X, e.Y)) || (!MobileMode && m.LocalAreaInControlSpace.Contains(e.X, e.Y)))
#else
                                    if (m.LocalArea.Contains(e.X, e.Y))
#endif
                              {
                                 if(!m.IsMouseOver)
                                 {
#if !PocketPC
                                    cursorBefore = this.Cursor;
                                    this.Cursor = Cursors.Hand;
#endif
                                    m.IsMouseOver = true;

                                    if(OnMarkerEnter != null)
                                    {
                                       OnMarkerEnter(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              else if(m.IsMouseOver)
                              {
#if !PocketPC
                                 this.Cursor = this.cursorBefore;
                                 cursorBefore = null;
#endif
                                 m.IsMouseOver = false;

                                 if(OnMarkerLeave != null)
                                 {
                                    OnMarkerLeave(m);
                                 }

                                 Invalidate();
                              }
                              #endregion
                           }
                        }

#if !PocketPC
                        foreach(GMapRoute m in o.Routes)
                        {
                           if(m.IsVisible && m.IsHitTestVisible)
                           {
                              #region -- check --

                              GPoint rp = new GPoint(e.X, e.Y);
#if !PocketPC
                              if(!MobileMode)
                              {
                                 rp.OffsetNegative(Core.renderOffset);
                              }
#endif
                              if(m.IsInside((int)rp.X, (int)rp.Y))
                              {
                                 if(!m.IsMouseOver)
                                 {
#if !PocketPC
                                    cursorBefore = this.Cursor;
                                    this.Cursor = Cursors.Hand;
#endif
                                    m.IsMouseOver = true;

                                    if(OnRouteEnter != null)
                                    {
                                       OnRouteEnter(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              else
                              {
                                 if(m.IsMouseOver)
                                 {
#if !PocketPC
                                    this.Cursor = this.cursorBefore;
                                    cursorBefore = null;
#endif
                                    m.IsMouseOver = false;

                                    if(OnRouteLeave != null)
                                    {
                                       OnRouteLeave(m);
                                    }

                                    Invalidate();
                                 }
                              }
                              #endregion
                           }
                        }
#endif
                        foreach(GMapPolygon m in o.Polygons)
                        {
                           if(m.IsVisible && (m.IsHitTestVisible || CanDragPolygon)) //check when I can drag the polygon too
                           {
                              #region -- check --
                              if(m.IsInside(FromLocalToLatLng(e.X, e.Y)))
                              {
                                 //keep the value that there are polygons under mouse pointer
                                 IsMouseOverPolygon = true;
                                 if(!m.IsMouseOver)
                                 {
                                     m.IsMouseOver = true;
                                     if ( m.IsHitTestVisible ) //only fires event if it IsHitTestVisible
                                     {
#if !PocketPC
                                        cursorBefore = this.Cursor;
                                        this.Cursor = Cursors.Hand;
#endif

                                        if ( OnPolygonEnter != null )
                                        {
                                            OnPolygonEnter( m );
                                        }
                                    }
                                    Invalidate();
                                 }
                              }
                              else
                              {
                                 if(m.IsMouseOver)
                                 {
                                     m.IsMouseOver = false;
                                     if ( m.IsHitTestVisible ) //only fires event if it IsHitTestVisible
                                     {
#if !PocketPC
                                         this.Cursor = this.cursorBefore;
                                         cursorBefore = null;
#endif
                                         if ( OnPolygonLeave != null )
                                         {
                                             OnPolygonLeave( m );
                                         }
                                     }
                                    Invalidate();
                                 }
                              }
                              #endregion
                           }
                        }
                     }
                  }
               }
         }
         base.OnMouseMove(e);
      }

With all that, I managed to drag every polygon under the mouse instead of the map.

For informational propouses, I also added the following property:

 

      /// <summary>
      /// is a polygon being dragged
      /// </summary>
      public bool IsDraggingPolygon { get { return !lastDragPolygon.IsEmpty; } }

 

It'd be great if this functionality was added to the project and I hope my code is useful to you.

 

Regards,

Cleverson Nascimento

Coordinator
Jul 16, 2012 at 3:52 PM

thanks i'll check it

Aug 9, 2012 at 9:05 PM

Just a correction:

the line that says:

//remove any trace of polygons under the mouse pointer
IsMouseOverPolygon = false;

Must be inserted before the overlays loop.

I've updated the post.

 

Regards,

Cleverson Nascimento