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

9

5

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

Almira answered 16/2, 2012 at 9:32 Comment(0)
I
10

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);
 }
If answered 20/3, 2012 at 13:0 Comment(1)
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.Bounce
E
6

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);
Eastnortheast answered 8/12, 2015 at 18:52 Comment(14)
@JAlecksen, May i know how to do the same with WPF?Saltpeter
@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 :PEastnortheast
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?Altonaltona
@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.Eastnortheast
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 classAltonaltona
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 !Altonaltona
@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 helpsEastnortheast
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!Altonaltona
@TheNewbie Have you tried doing MarkerTooltipMode.OnMouseOver instead?Eastnortheast
Yup, I did that. Doesn't seem to show when I hover over itAltonaltona
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" Altonaltona
@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.Eastnortheast
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!Altonaltona
@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!Eastnortheast
S
5
   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);
    }
Soup answered 21/11, 2017 at 4:16 Comment(0)
N
2

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);
Nib answered 8/9, 2016 at 15:35 Comment(1)
Thanks ! With slight changes, I am able to perform the same in wpfSaltpeter
S
0
private void CreateCircle(PointF point, double radius, int segments)
{

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

double seg = Math.PI * 2 / segments;

int y = 0;
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);
 }`enter code here`

so the apartment is not going ellipses

Server answered 16/8, 2015 at 11:42 Comment(0)
N
0

Here's how to draw a red circle, with black border on the map in WPF:

public class YourMapControl : GMapControl
{
   protected override void OnRender(DrawingContext drawingContext)
   {
      base.OnRender(drawingContext);

      Point center(40.730610, -73.935242);
      double radius = 0.1;

      drawingContext.DrawEllipse(Brushes.Red, Pens.Black, center, radius, radius);
   }
}

As far as the second part of the question itself, you would use the following built-in MapControl functions:

public bool DisableAltForSelection; //if true, selects area just by holding mouse and moving
public bool SelectionUseCircle; //use circle for selection
public event SelectionChange OnSelectionChange; //occurs when mouse selection is changed
public RectLatLng SelectedArea { get; set; } //returns rect with coordinates of the selected area
Nutwood answered 2/6, 2017 at 17:26 Comment(0)
M
0
        GMapOverlay markers = new GMapOverlay("markers");
        private void CreateCircle(Double lat, Double lon, double radius, int segments)
        {
            markers.Polygons.Clear();
            PointLatLng point = new PointLatLng(lat, lon);

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

            List<PointLatLng> gpollistR = new List<PointLatLng>();
            List<PointLatLng> gpollistL = new List<PointLatLng>();
            foreach (var gp in gpollist)
            {
                if (gp.Lng > lon)
                {
                    gpollistR.Add(gp);
                }
                else
                {
                    gpollistL.Add(gp);
                }
            }
            gpollist.Clear();

            List<PointLatLng> gpollistRT = new List<PointLatLng>();
            List<PointLatLng> gpollistRB = new List<PointLatLng>();
            foreach (var gp in gpollistR)
            {
                if (gp.Lat > lat)
                {
                    gpollistRT.Add(gp);
                }
                else
                {
                    gpollistRB.Add(gp);
                }
            }
            gpollistRT.Sort(new LngComparer());
            gpollistRB.Sort(new Lng2Comparer());
            gpollistR.Clear();
            List<PointLatLng> gpollistLT = new List<PointLatLng>();
            List<PointLatLng> gpollistLB = new List<PointLatLng>();
            foreach (var gp in gpollistL)
            {
                if (gp.Lat > lat)
                {
                    gpollistLT.Add(gp);
                }
                else
                {
                    gpollistLB.Add(gp);
                }
            }
            //gpollistLT.Sort(new LngComparer());
            gpollistLB.Sort(new Lng2Comparer());
            gpollistLT.Sort(new LngComparer());
            gpollistL.Clear();


            gpollist.AddRange(gpollistRT);
            gpollist.AddRange(gpollistRB);
            gpollist.AddRange(gpollistLB);
            gpollist.AddRange(gpollistLT);
            GMapPolygon gpol = new GMapPolygon(gpollist, "pol");
            gpol.Stroke = new Pen(Color.Red, 1);
            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;
        }

and this class

class LngComparer : IComparer<PointLatLng>
    {
        #region IComparer Members

        public int Compare(PointLatLng x, PointLatLng y)
        {
            if (x == null || y == null)
                throw new ArgumentException("At least one argument is null");
            if (x.Lng == y.Lng)
            {
                if (x.Lat > y.Lat)
                {
                    return 1;
                }
                else if (x.Lat < y.Lat)
                {
                    return -1;
                }
                else
                {
                    return 0;
                }
            }
            if (x.Lng < y.Lng) return -1;
            return 1;
        }

        #endregion
    }
    class Lng2Comparer : IComparer<PointLatLng>
    {
        #region IComparer Members

        public int Compare(PointLatLng x, PointLatLng y)
        {
            if (x == null || y == null)
                throw new ArgumentException("At least one argument is null");
            if (x.Lng == y.Lng)
            {
                if (x.Lat > y.Lat)
                {
                    return 1;
                }
                else if (x.Lat > y.Lat)
                {
                    return -1;
                }
                else
                {
                    return 0;
                }
            }
            if (x.Lng > y.Lng) return -1;
            return 1;
        }

        #endregion
    }
Matz answered 11/1, 2019 at 20:15 Comment(0)
D
0

My code draws arcs and inherits from GMapMarker too. The arc sweeps from point A to point B with the pivot point at C. Where point A and B are coincidental, a circle will be drawn.

    public class CustomArc : GMapMarker, ISerializable {
    [NonSerialized]
    public Pen pen;

    private int radius = 20;
    private int pen_width = 2;

    private float start = 0.0f;
    private float sweep = 0.0f;

    private GPoint ptA;
    private GPoint ptB;
    private GPoint ptC;
    private List<PointF> points;

    private static Logger logger = LogManager.GetCurrentClassLogger();

    public CustomArc(GPoint ptA, GPoint ptB, GPoint ptC, PointLatLng geo) : base(geo) {
        this.ptA = ptA;
        this.ptB = ptB;
        this.ptC = ptC;
        initialise();
    }

    private void initialise() {
        this.pen = new Pen(Brushes.White, this.pen_width);
        this.radius = (int)UIMaths.distance(ptC, ptA);

        this.points = new List<PointF>();

        if (ptA == ptB) {
            this.sweep = 360.0f;
        } else {
            // Calculate the radius
            this.sweep = (float)UIMaths.sweepAngleDeg(ptA, ptB, ptC);
        }
        this.start = (float)UIMaths.startAngle(ptC, ptB);
        Size = new Size(2 * radius, 2 * radius);
        Offset = new Point(-Size.Width / 2, -Size.Height / 2);

        Console.Out.WriteLine("Radius {0}, Start {1:0.0}, Sweep {2:0.0}", radius, start, sweep);
    }



    public override void OnRender(Graphics g) {
        try {
            Rectangle rect = new Rectangle(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height);
            g.DrawArc(pen, rect, start, sweep);

        } catch (ArgumentException ex) {
            logger.Error(ex.Message);
        }
    }

    public sealed override void Dispose() {
        if (pen != null) {
            pen.Dispose();
            pen = null;
        }

        base.Dispose();
    }

    #region ISerializable Members

    void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
        base.GetObjectData(info, context);
    }

    protected CustomArc(SerializationInfo info, StreamingContext context)
     : base(info, context) {
    }
    #endregion

}
Dominations answered 14/2, 2020 at 8:52 Comment(0)
H
0

My approach was to override paint event then define a rectangle. Once you define a rectangle you can draw circle or arc or pie.

private void MainMap_Paint(object sender, PaintEventArgs e)
{
   drawPie(e.Graphics, 50, 22.321, 45.44498);   
 }

private void drawPie(Graphics g, int angle, double latitude, double longitude)
{
    PointLatLng pn = new PointLatLng(latitude , longitude );
    double dist = 295; // 200 km
    // define rectangle points
    PointLatLng p1 = FindPointAtDistanceFrom(pn, 315 * constants.DEGREES_TO_RADIAN, dist);
    PointLatLng p2 = FindPointAtDistanceFrom(pn, 45 * constants.DEGREES_TO_RADIAN, dist);
    PointLatLng p3 = FindPointAtDistanceFrom(pn, 135 * constants.DEGREES_TO_RADIAN, dist);
    PointLatLng p4 = FindPointAtDistanceFrom(pn, 225 * constants.DEGREES_TO_RADIAN, dist);
    GPoint dp1 = MainMap.FromLatLngToLocal(p1);
    GPoint dp2 = MainMap.FromLatLngToLocal(p2);
    GPoint dp3 = MainMap.FromLatLngToLocal(p3);
    GPoint dp4 = MainMap.FromLatLngToLocal(p4);

    RectangleF rec = new RectangleF(dp1.X, dp1.Y, dp2.X - dp1.X, dp3.Y - dp1.Y);
    SolidBrush ptlbrush = new SolidBrush(Color.Cyan);
    Pen ptlpen = new Pen(ptlbrush, 1);                        
    float direction1 = (-90 + angle - 45) % 360;
    float startAngle = direction1;
    float sweepAngle = 90;                                                                
    
    var brush = new SolidBrush(Color.FromArgb(50, 80, 0, 150));
    g.DrawPie(ptlpen, rec, startAngle, sweepAngle);
    if (angleFilledBox.Checked == true)
        g.FillPie(brush, Rectangle.Round(rec), startAngle, sweepAngle);

}
Huber answered 21/2, 2021 at 7:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.