如何在 C# 中使用 GMAP.NET 在 MAP 上绘制圆圈

发布于 2025-01-06 07:24:25 字数 205 浏览 7 评论 0原文

我在 C# 中使用 GMAP.NET。我能够在表单上显示地图,现在我尝试通过单击某个点来绘制圆形鼠标,保持鼠标左键并将鼠标拖动到特定位置。一旦绘制了圆,我想得到它距中心点的半径(以英里为单位),我确信 GMAP 能够做到这一点。我正在使用 Opentstreet 地图。

我只是无法实现此功能,任何使用过 GMAP 控件的人请分享您的经验以及一些可行的代码。

谢谢

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

一页 2025-01-13 07:24:25

据我所知,可以实现这样的结果的唯一方法是创建一个包含 PointLatLng 点的列表并将它们绘制为多边形。这是一个例子:

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

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);
 }
束缚m 2025-01-13 07:24:25

如果你想使用与绘图类相关的典型GDI功能,你可以简单地继承GMapMarker类。这允许您绘制简单的形状,例如圆形,并创建自定义属性(例如,将计算形状的半径(以英里为单位)):

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

    }
 }

在地图上绘制点:(

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

        gMapControl1.Overlays.Add(points_);

因为我对此有一些疑问)我们继承自标记类,我们仍然可以利用工具提示文本功能:

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

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);
踏月而来 2025-01-13 07:24:25
   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);
    }
   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);
    }
暮年 2025-01-13 07:24:25

我遇到了同样的问题,在输入时我有经度、纬度和半径,这是我的解决方案。它就像一个魅力:)

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

打电话

CreateCircle(51.640980, -2.673544, 1143.899431);

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);
初心未许 2025-01-13 07:24:25
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`

所以公寓不会出现椭圆形

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

小嗲 2025-01-13 07:24:25

以下是如何在 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);
   }
}

就问题本身的第二部分而言,您将使用以下内置 MapControl 函数:

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

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
记忆で 2025-01-13 07:24:25
        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;
        }

和这个班级

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
    }
        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
    }
雄赳赳气昂昂 2025-01-13 07:24:25

我的代码绘制弧线并继承自 GMapMarker。圆弧从 A 点扫过 B 点,枢轴点为 C。当 A 点和 B 点重合时,将绘制一个圆。

    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

}

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

}
太阳哥哥 2025-01-13 07:24:25

我的方法是覆盖绘画事件然后定义一个矩形。一旦定义了矩形,您就可以绘制圆形、圆弧或饼图。

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

}

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

}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文