打造地图拼接利器(四)数据交互
2021-06-27 本文已影响0人
安静的林哥
这里的数据交互,主要指在地图上可以选择一个范围,这个范围可以调节,同时返回所选范围的经纬度值。
GMap.net提供一个绘制矩形的函数,但我们还需要加入一些控制点,用来随意调整区域的大小和位置。内置函数GMapPolygon可以生成一个矩形对象,然后添加到地图上。
新建一个类SelectArea,将地图控件作为构造函数的参数传入。
public SelectArea(GMapControl control)
{
this.control = control;
//获取两个层,分别用于放置区域和控制点,如果没有,测创建
InitOverlay(control);
//绑定事件
InitEvent(control);
}
同时,生成两个层,分别用来放置图形和控制点。这也是我们制作标绘的思路,即通过控制点,生成复杂图形。
/// <summary>
/// 初始化图层,拖动层和显示层,如果有则不创建
/// </summary>
/// <param name="control"></param>
private void InitOverlay(GMapControl control)
{
bool haspolygons = false, hasdrags = false;
foreach (GMapOverlay overlay in control.Overlays)
{
if (overlay.Id.Equals("polygons"))
{
haspolygons = true;
this.polygonOverlay = overlay;
continue;
}
if (overlay.Id.Equals("drags"))
{
hasdrags = true;
this.dragOverlay = overlay;
break;
}
}
if (!haspolygons)
{
polygonOverlay = new GMapOverlay("polygons");
control.Overlays.Insert(0, polygonOverlay);
}
if (!hasdrags)
{
dragOverlay = new GMapOverlay("drags");
control.Overlays.Add(dragOverlay);
}
}
在类中设置左上和右下两个关键点P1、P2,绑定鼠标按下、移动和抬起事件。当鼠标按下时,记录第一个点,当鼠标移动时,更新第二个点,当鼠标抬起时,停止更新,同步在polygons层里绘制矩形。
/// <summary>
/// 根据2个关键点坐标,获取矩形坐标
/// </summary>
/// <param name="p1"></param>
/// <param name="p2"></param>
/// <returns></returns>
List<PointLatLng> GetPolygonPoints(PointLatLng p1, PointLatLng p2)
{
return new List<PointLatLng>(){
new PointLatLng(p1.Lat,p1.Lng),
new PointLatLng(p1.Lat,p2.Lng),
new PointLatLng(p2.Lat,p2.Lng),
new PointLatLng(p2.Lat,p1.Lng)
};
}
鼠标抬起后,生成控制点。这里需要说明,其实控制点也是一个polygon矩形,只不过比较小,再加上描边效果,看起来像一个控制柄。控制点有3个,p1、p2和中点,分别为drag1、drag2和dragcenter,每个控制点根据中心坐标,算出边距为10的小矩形。
Polygon对象有一个.IsMouseOver属性,可以判断是否鼠标点击在上面,但实测不好使,所以写了一个检测函数,用来判断控制点是否选中:
/// <summary>
/// 判断点是否在区域范围内
/// </summary>
/// <param name="p"></param>
/// <param name="pm"></param>
/// <returns></returns>
bool isInside(GPoint p, PointLatLng pm,int radius)
{
bool isinside = false;
GPoint pa = control.FromLatLngToLocal(pm);
if (p.X > pa.X - radius && p.X < pa.X + radius && p.Y > p.Y - radius && p.Y < pa.Y + radius)
{
isinside = true;
}
return isinside;
}
当鼠标按下时,判断选择哪个控制点,并用state标记:
void control_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
control.DragButton = System.Windows.Forms.MouseButtons.Right;
isDrag = true;
if (polygon == null&&state==0)
{
p1=control.FromLocalToLatLng(e.X, e.Y);
p2=control.FromLocalToLatLng(e.X, e.Y);
List<PointLatLng> points = GetPolygonPoints(p1, p2);
polygon = new GMapPolygon(points, "polygon");
polygon.Stroke =new Pen( new SolidBrush(Color.Red),3);
polygonOverlay.Polygons.Add(polygon);
}
if (drag1 != null && isInside(new GPoint(e.X, e.Y), p1,5))
{
state = 1;
}
if (drag2 != null && isInside(new GPoint(e.X, e.Y), p2, 5))
{
state = 2;
}
if (dragcenter != null && isInside(new GPoint(e.X, e.Y), GetDragCenterPointsLatLng(p1, p2), 5))
{
state = 3;
}
}
添加一个代理事件,用于在矩形变化时将坐标返回主界面的左侧区域。
\\类外:
public delegate void showInfo(SelectInfo selectinfo);
\\类内:
public event showInfo MyShowInfo;
[\\mouseMove](file://mouseMove)事件中回馈
SelectInfo cinfo = new SelectInfo();
cinfo.StartPoint = p1;
cinfo.EndPoint = p2;
MyShowInfo(cinfo);
最终效果如下图:
控制点效果图