這里的數(shù)據(jù)交互恩脂,主要指在地圖上可以選擇一個范圍帽氓,這個范圍可以調(diào)節(jié),同時返回所選范圍的經(jīng)緯度值俩块。
GMap.net提供一個繪制矩形的函數(shù)黎休,但我們還需要加入一些控制點,用來隨意調(diào)整區(qū)域的大小和位置玉凯。內(nèi)置函數(shù)GMapPolygon可以生成一個矩形對象势腮,然后添加到地圖上。
新建一個類SelectArea漫仆,將地圖控件作為構造函數(shù)的參數(shù)傳入捎拯。
public SelectArea(GMapControl control)
{
this.control = control;
//獲取兩個層,分別用于放置區(qū)域和控制點盲厌,如果沒有署照,測創(chuàng)建
InitOverlay(control);
//綁定事件
InitEvent(control);
}
同時,生成兩個層吗浩,分別用來放置圖形和控制點建芙。這也是我們制作標繪的思路,即通過控制點拓萌,生成復雜圖形岁钓。
/// <summary>
/// 初始化圖層,拖動層和顯示層微王,如果有則不創(chuàng)建
/// </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>
/// 根據(jù)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媚朦,每個控制點根據(jù)中心坐標氧敢,算出邊距為10的小矩形。
Polygon對象有一個.IsMouseOver屬性询张,可以判斷是否鼠標點擊在上面孙乖,但實測不好使,所以寫了一個檢測函數(shù)份氧,用來判斷控制點是否選中:
/// <summary>
/// 判斷點是否在區(qū)域范圍內(nèi)
/// </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;
}
}
添加一個代理事件蜗帜,用于在矩形變化時將坐標返回主界面的左側區(qū)域恋拷。
\\類外:
public delegate void showInfo(SelectInfo selectinfo);
\\類內(nèi):
public event showInfo MyShowInfo;
[\\mouseMove](file://mouseMove)事件中回饋
SelectInfo cinfo = new SelectInfo();
cinfo.StartPoint = p1;
cinfo.EndPoint = p2;
MyShowInfo(cinfo);
最終效果如下圖:
控制點效果圖