How to draw circle on the MAP using GMAP.NET in C#

18,978

Solution 1

The only way that I am aware of that can achieve such a result is to create a list with PointLatLng points and draw them as a polygon. Here is an example:

private void CreateCircle(PointF point, double radius, int segments)
{

    List<PointLatLng> gpollist = new List<PointLatLng>();

    double seg = Math.PI * 2 / segments;

    for (int i = 0; i < segments; i++)
    {
        double theta = seg * i;
        double a = point.X + Math.Cos(theta) * radius;
        double b = point.Y + Math.Sin(theta) * radius;
    
        PointLatLng gpoi = new PointLatLng(a,b);

        gpollist.Add(gpoi);
     }
     GMapPolygon gpol = new GMapPolygon(gpollist, "pol");

     overlayOne.Polygons.Add(gpol);
 }

Solution 2

If you want to use the typical GDI features associated with the drawing class, you can simply inherit the GMapMarker class. This allows you to draw simple shapes, like circles, and create custom properties (for instance, one that will calculate the radius in miles of the shape):

public class GMapPoint : GMap.NET.WindowsForms.GMapMarker
{
    private PointLatLng point_;
    private float size_;
    public PointLatLng Point
    {
        get
        {
            return point_;
        }
        set
        {
            point_ = value;
        }
    }
    public GMapPoint(PointLatLng p, int size)
        : base(p)
    {
        point_ = p;
        size_ = size;
    }

    public override void OnRender(Graphics g)
    {
        g.FillRectangle(Brushes.Black, LocalPosition.X, LocalPosition.Y, size_, size_); 
        //OR 
        g.DrawEllipse(Pens.Black, LocalPosition.X, LocalPosition.Y, size_, size_);
        //OR whatever you need

    }
 }

To draw points on the map:

        GMapOverlay points_ = new GMapOverlay("pointCollection");
        points_.Markers.Add(new GMapPoint(new PointLatLng(35.06, -106.36), 10));

        gMapControl1.Overlays.Add(points_);

(And because I had some questions about it) Since we are inhereting from the markers class, we can still take advantage of the tooltiptext capability:

        GMapPoint pnt = new GMapPoint(new PointLatLng(35.06, -106.36), 10);
        pnt.Size = new Size(10,10);
        pnt.ToolTipText = "Text Here";
        pnt.ToolTipMode = MarkerTooltipMode.Always;
        points_.AddMarker(pnt);

Solution 3

   private void CreateCircle(Double lat, Double lon, double radius, int ColorIndex)
    {
        PointLatLng point = new PointLatLng(lat, lon);
        int segments = 1080;

        List<PointLatLng> gpollist = new List<PointLatLng>();

        for (int i = 0; i < segments; i++)
        {
            gpollist.Add(FindPointAtDistanceFrom(point, i*(Math.PI/180), radius / 1000));
        }

        GMapPolygon polygon = new GMapPolygon(gpollist, "Circle");
        switch (ColorIndex) {

            case 1:
                polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Red));
                break;
            case 2:
                polygon.Fill = new SolidBrush(Color.FromArgb(80, Color.Orange));
                break;
            case 3:
                polygon.Fill = new SolidBrush(Color.FromArgb(20, Color.Aqua));
                break;
            default:
                MessageBox.Show("No search zone found!");
                break;
        }


        polygon.Stroke = new Pen(Color.Red, 1);
        markers.Polygons.Add(polygon);
        gMapCtl.Overlays.Add(markers);
    }


    public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
    {
        const double radiusEarthKilometres = 6371.01;
        var distRatio = distanceKilometres / radiusEarthKilometres;
        var distRatioSine = Math.Sin(distRatio);
        var distRatioCosine = Math.Cos(distRatio);

        var startLatRad = DegreesToRadians(startPoint.Lat);
        var startLonRad = DegreesToRadians(startPoint.Lng);

        var startLatCos = Math.Cos(startLatRad);
        var startLatSin = Math.Sin(startLatRad);

        var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));
        var endLonRads = startLonRad + Math.Atan2(Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,distRatioCosine - startLatSin * Math.Sin(endLatRads));

        return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
    }

    public static double DegreesToRadians(double degrees)
    {
        const double degToRadFactor = Math.PI/180;
        return degrees * degToRadFactor;
    }

    public static double RadiansToDegrees(double radians)
    {
        const double radToDegFactor = 180/Math.PI;
        return radians * radToDegFactor;
    }



    public static double DistanceTwoPoint(double startLat, double startLong, double endLat, double endLong) {

        var startPoint = new GeoCoordinate(startLat, startLong);
        var endPoint = new GeoCoordinate(endLat, endLong);

        return startPoint.GetDistanceTo(endPoint);
    }

Solution 4

I hit the same problem and on entry I had Lon, Lat and radius, here is my solution. It works like a charm :)

private void CreateCircle(Double lat, Double lon, double radius)
{
   PointLatLng point = new PointLatLng(lat, lon);
   int segments = 1000;

   List<PointLatLng> gpollist = new List<PointLatLng>();

   for (int i = 0; i < segments; i++)
      gpollist.Add(FindPointAtDistanceFrom(point, i, radius / 1000));

   GMapPolygon gpol = new GMapPolygon(gpollist, "pol");

   markers.Polygons.Add(gpol);
}

public static GMap.NET.PointLatLng FindPointAtDistanceFrom(GMap.NET.PointLatLng startPoint, double initialBearingRadians, double distanceKilometres)
{
   const double radiusEarthKilometres = 6371.01;
   var distRatio = distanceKilometres / radiusEarthKilometres;
   var distRatioSine = Math.Sin(distRatio);
   var distRatioCosine = Math.Cos(distRatio);

   var startLatRad = DegreesToRadians(startPoint.Lat);
   var startLonRad = DegreesToRadians(startPoint.Lng);

   var startLatCos = Math.Cos(startLatRad);
   var startLatSin = Math.Sin(startLatRad);

   var endLatRads = Math.Asin((startLatSin * distRatioCosine) + (startLatCos * distRatioSine * Math.Cos(initialBearingRadians)));

   var endLonRads = startLonRad + Math.Atan2(
                 Math.Sin(initialBearingRadians) * distRatioSine * startLatCos,
                 distRatioCosine - startLatSin * Math.Sin(endLatRads));

   return new GMap.NET.PointLatLng(RadiansToDegrees(endLatRads), RadiansToDegrees(endLonRads));
}

public static double DegreesToRadians(double degrees)
{
  const double degToRadFactor = Math.PI / 180;
  return degrees * degToRadFactor;
}

public static double RadiansToDegrees(double radians)
{
  const double radToDegFactor = 180 / Math.PI;
  return radians * radToDegFactor;
}

call

CreateCircle(51.640980, -2.673544, 1143.899431);
Share:
18,978

Related videos on Youtube

Shax
Author by

Shax

Updated on June 04, 2022

Comments

  • Shax
    Shax almost 2 years

    I am using GMAP.NET in c#. I am able to display the map on the form, now i am trying to draw a CIRCLE mouse by clicking on a certian point, keeping the left mouse button and dragging the mouse upto specific place. Once the circle is drawn I want to get its radius in miles from the center point which I am sure GMAP is capable of doing it. I am using Opentstreet maps.

    I am just unable to achive this functionly, anybody who has played with GMAP control kindly share your experience with some code which will work.

    Thanks

  • TonyG
    TonyG about 10 years
    Good code, thanks. Minor tweak: Math.Cos and Math.Sin, note caps, and radius needs to be VERY tiny like .01 if you're mapping to a scale of a mile or two.
  • Admin
    Admin almost 7 years
    @JAlecksen, May i know how to do the same with WPF?
  • T James
    T James almost 7 years
    @Manish Jain Unfortunately I have not had any experience with WPF and Gmap. Some day I will have to transition over but I am not looking forward to that learning curve :P
  • Admin
    Admin almost 7 years
    Thanks ! With slight changes, I am able to perform the same in wpf
  • The Newbie
    The Newbie over 5 years
    Thank you for this piece of code. I converted it to VB.NET and it worked beautifully. I was wondering since we're drawing the dot on the overlay, how can those dots become markers with tooltips?
  • T James
    T James over 5 years
    @TheNewbie Glad It helped. Since you are inheriting from the markers class, you should be able to add the tooltips in the same way that you do it for any other markers.
  • The Newbie
    The Newbie over 5 years
    This is how I am creating a marker "Dim marker As GMarkerGoogle = New GMarkerGoogle(New PointLatLng(lat, lng), GMarkerGoogleType.green)". This marker variable has a ToolTip function in it, whereas the new class you wrote doesn't have a tooltip function. I'm not quite sure how to assign a tooltip to the markers created by your class
  • The Newbie
    The Newbie over 5 years
    By the way, drawing the marker on the map instead of using the default way is much faster. THe map doesn't lag as much !
  • T James
    T James over 5 years
    @TheNewbie Yeah, drawing bitmaps takes significantly longer than the raw drawing functions. Assuming you are using the sample code above, you should be able to add the tooltip stuff to the GMapPoint, like this: GMapPoint p = new …; p.ToolTipMode = MarkerTooltipMode.Always; and m.ToolTipText = "Text"; than add it to the layer: points_.AddMarker(p); I tested this and it seems to work fine. Hope this helps
  • The Newbie
    The Newbie over 5 years
    Thank you, it seems to work perfectly fine if the ToolTipMode is set to always, however, that cover up the tooltips of one another if the Lat/Long are next to each other. Could it also retain the ability to only show the tooltip when hovered? I already tried setting the ToolTipMode to OnMouseOver but I don't think thats being handled. Thank you once again!
  • T James
    T James over 5 years
    @TheNewbie Have you tried doing MarkerTooltipMode.OnMouseOver instead?
  • The Newbie
    The Newbie over 5 years
    Yup, I did that. Doesn't seem to show when I hover over it
  • The Newbie
    The Newbie over 5 years
    Here's how I create a new layer and marker and adding it to my map. Dim marker As GMapPoint marker = New GMapPoint(New PointLatLng(lat, lng), 15) marker.ToolTip = New GMapToolTip(marker) marker.ToolTipMode = MarkerTooltipMode.OnMouseOver marker.ToolTipText = "test"
  • T James
    T James over 5 years
    @TheNewbie So it looks like the OnMouseOver uses the size of the marker to determine if the cursor is over the marker or not. If you are using my class above as-is, then you are never setting the known size within the marker class. In addition to what you have, you will need to do something like this: pnt.Size = new Size(10, 10); or whatever you want your hover tolerance to be.
  • The Newbie
    The Newbie over 5 years
    That works like a charm. You rock man. Also if you don't mind, it looks like you have used this before, do you have any tips/tricks to spice up Gmap even more? Or are you just looking over the source code of Gmaps and figuring it out that way? Regardless, us noobs thank people like you to help us. Have an awesome day!
  • T James
    T James over 5 years
    @TheNewbie I am simply looking over the source code to see how it works. I am a noob on many topics and am always using this site to get help. I am happy to give back as much as possible! Have a fantastic day!