C# Gmap.Net 以某点为圆心,指定半径绘制圆,并实现圆心闪烁

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_27278957/article/details/88786694

简述

关于Gmap,如果你不是很熟悉,可以通过以下几篇文章来了解,这里就不多介绍了。需注意一点,地图上的坐标是指(经度, 纬度)--> (y, x)-->(longitude, latitude),且中国地区的经纬度,经度大,纬度。

GMap.NET 使用教程【1】

GMap.NET 使用教程【2】

GMap.NET 使用教程【3】 

流程 

  1. 求圆点四周,距离圆点距离为指定半径的所有点位置(经纬度);
  2. 绘制到Gmap图层;
  3. 圆心(marker)闪烁。

一、求圆点四周,距离圆点距离为指定半径的所有点位置(经纬度)

 1、首先需要自定义经纬度类,便于后面使用。

  //自定义经纬度类
    public class MyLatLng
    {
        public double Rc = 6378137;     //赤道半径
        public double Rj = 6356725;     //极半径
        public double m_LoDeg, m_LoMin, m_LoSec;
        public double m_LaDeg, m_LaMin, m_LaSec;
        public double m_Longitude, m_Latitude;
        public double m_RadLo, m_RadLa;
        public double Ec;
        public double Ed;
        public MyLatLng(double longitude, double latitude)
        {
            m_LoDeg = (int)longitude;
            m_LoMin = (int)((longitude - m_LoDeg) * 60);
            m_LoSec = (longitude - m_LoDeg - m_LoMin / 60) * 3600;

            m_LaDeg = (int)latitude;
            m_LaMin = (int)((latitude - m_LaDeg) * 60);
            m_LaSec = (latitude - m_LaDeg - m_LaMin / 60) * 3600;

            m_Longitude = longitude;
            m_Latitude = latitude;
            m_RadLo = longitude * Math.PI / 180;
            m_RadLa = latitude * Math.PI / 180;
            Ec = Rj + (Rc - Rj) * (90 - m_Latitude) / 90;
            Ed = Ec * Math.Cos(m_RadLa);
        }
    }

2、准备“度与弧度互转”的接口。

度 转 弧度 

//度 转换成 弧度
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;
}

3、求圆点四周,距离圆点距离为指定半径的所有点位置(经纬度)

/**
* 求B点经纬度
* @param A 已知点的经纬度,
* @param distance   AB两地的距离  单位km
* @param angle  AB连线与正北方向的夹角(0~360)
* @return  B点的经纬度
*/
public static MyLatLng getMyLatLng(MyLatLng A, double distance, double angle)
{
	double dx = distance * 1000 * Math.Sin(DegreesToRadians(angle));
	double dy = distance * 1000 * Math.Cos(DegreesToRadians(angle));

	double bjd = (dx / A.Ed + A.m_RadLo) * 180/ Math.PI;
	double bwd = (dy / A.Ec + A.m_RadLa) * 180/ Math.PI;
	return new MyLatLng(bjd, bwd);
}

二、绘制到Gmap图层

这里,绘制到Gmap图层的方式有三种。

1、添加marker方式

//描述:以centerP为圆心,绘制半径为radius的圆
//gMapControl:Gmap控制器		overlay:图层
//centerP:圆心点	 radius:圆半径(单位: km)
public static void DrawEllipse(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, int radius)
{
	try
	{
		if (radius <= 0)
			return;
			
		List<PointLatLng> latLngs = new List<PointLatLng>();
		MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);

		// 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
		for (int i = 0; i < 360; i++)
		{
			//获取目标经纬度
			MyLatLng tempLatLng = getMyLatLng(centerLatLng, radius, i);
			//将自定义的经纬度类 转换成 标准经纬度类
			PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);

			//通过绘制标记点的方式绘制圆
			GMapMarker gMapMarker = new GMarkerGoogle(p, GMarkerGoogleType.red);
			overlay.Markers.Add(gMapMarker);
		}
	}
	catch (Exception ex)
	{
		Dialog.Error(ex);
	}
}

2、添加路线方式

//描述:以centerP为圆心,绘制半径为radius的圆
//gMapControl:Gmap控制器		overlay:图层
//centerP:圆心点	 radius:圆半径(单位: km)  name:路线id
public static void DrawEllipse(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, int radius, string name)
{
	try
	{
		if (radius <= 0)
			return;
			
		List<PointLatLng> latLngs = new List<PointLatLng>();
		MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);

		// 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
		for (int i = 0; i < 360; i++)
		{
			//获取目标经纬度
			MyLatLng tempLatLng = getMyLatLng(centerLatLng, radius, i);
			//将自定义的经纬度类 转换成 标准经纬度类
			PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
			latLngs.Add(p);
		}

		//安全性检查
		if (latLngs.Count < 20)
		{
			return;
		}

		//通过绘制路线的方式绘制圆
		GMapRoute route = new GMapRoute(latLngs, name);
		if (route == null)
		{
		    return;
		}
		route.Stroke = new Pen(Color.Red, 2.5f);
		overlay.Routes.Add(route);
	}
	catch (Exception ex)
	{
		Dialog.Error(ex);
	}
}

3、添加多边形方式(推荐使用,便于扩展功能)

//描述:以centerP为圆心,绘制半径为radius的圆
//gMapControl:Gmap控制器		overlay:图层
//centerP:圆心点	 radius:圆半径(单位: km)  name:多边形id
public static void DrawEllipse(GMapControl gMapControl, GMapOverlay overlay, PointLatLng centerP, int radius, string name)
{
	try
	{
		if (radius <= 0)
			return;
			
		List<PointLatLng> latLngs = new List<PointLatLng>();
		MyLatLng centerLatLng = new MyLatLng(centerP.Lng, centerP.Lat);

		// 0 - 360度 寻找半径为radius,圆心为centerP的圆上点的经纬度
		for (int i = 0; i < 360; i++)
		{
			//获取目标经纬度
			MyLatLng tempLatLng = getMyLatLng(centerLatLng, radius, i);
			//将自定义的经纬度类 转换成 标准经纬度类
			PointLatLng p = new PointLatLng(tempLatLng.m_Latitude, tempLatLng.m_Longitude);
			latLngs.Add(p);
		}

		//安全性检查
		if (latLngs.Count < 20)
		{
			return;
		}

		//通过绘制多边形的方式绘制圆
		GMapPolygon gpol = new GMapPolygon(latLngs, name);
		gpol.Stroke = new Pen(Color.Red, 1.0f);
		gpol.Fill = new SolidBrush(Color.FromArgb(20, Color.Red));
		gpol.IsHitTestVisible = true;
		overlay.Polygons.Add(gpol);
	}
	catch (Exception ex)
	{
		Dialog.Error(ex);
	}
}

三、 圆心(marker)闪烁

其实就是marker的显示与隐藏功能,加上定时器。

private System.Windows.Forms.Timer treeExTimer = null;    //古树异常点闪烁定时器
//古树异常点闪烁定时器 开始
private void StartTreeExTimer()
{
	//古树异常点闪烁定时器 初始化
	if (treeExTimer != null)
		StopTreeExTimer();
	treeExTimer = new System.Windows.Forms.Timer();
	treeExTimer.Interval = 1000;
	treeExTimer.Tick += new EventHandler(TreeExTimer_Tick);
	treeExTimer.Enabled = true;
	treeExTimer.Start();
}

//古树异常点 定时闪烁
private void TreeExTimer_Tick(object sender, EventArgs e)
{
	if (TreeExLayer.Markers.Count == 0)
	{
		Dialog.Information("stop");
		StopTreeExTimer();
		return;
	}
	
	foreach (GMapMarker m in TreeExLayer.Markers)
	{
		if (m is TreeExMarker)
		{
			TreeExMarker marker = m as TreeExMarker;
			//marker闪烁实现部分,并在marker上绘制红色圈
			if (marker.OutPen == null)
			{
				marker.OutPen = new Pen(Brushes.Red, 2);
				marker.IsVisible = true;
			}                        
			else
			{
				marker.OutPen.Dispose();
				marker.OutPen = null;
				marker.IsVisible = false;
			}
		}
	}
	this.gMapControl.Refresh();
}

//古树异常点闪烁定时器 结束
private void StopTreeExTimer()
{
	if (treeExTimer != null)
	{
		treeExTimer.Enabled = false;
		treeExTimer.Stop();
		treeExTimer.Dispose();
		treeExTimer = null;
	}            
}

四、计算地图上两点之间的距离--扩展功能

private const double EARTH_RADIUS = 6378.137;//地球半径
private static double rad(double d)
{
	return d * Math.PI / 180.0;
}

public static double GetDistance(double lat1, double lng1, double lat2, double lng2)
{
	double radLat1 = rad(lat1);
	double radLat2 = rad(lat2);
	double a = radLat1 - radLat2;
	double b = rad(lng1) - rad(lng2);

	double s = 2 * Math.Asin(Math.Sqrt(Math.Pow(Math.Sin(a / 2), 2) +
	 Math.Cos(radLat1) * Math.Cos(radLat2) * Math.Pow(Math.Sin(b / 2), 2)));
	s = s * EARTH_RADIUS;
	s = Math.Round(s * 10000) / 10000;
	return s;
}

 总结

以上功能均亲测可用!

参考链接:https://blog.csdn.net/s297485987/article/details/81270560

猜你喜欢

转载自blog.csdn.net/qq_27278957/article/details/88786694