地圖下載工具初步完成后,有網(wǎng)友提出需要加入經(jīng)緯網(wǎng)絡(luò)念赶,看了文檔础钠,沒有找到相關(guān)內(nèi)容。那就自己動手叉谜,豐衣足食吧旗吁。最終效果如下圖所示:
具體思路是,根據(jù)地圖界面顯示的經(jīng)緯網(wǎng)絡(luò)范圍停局,確定一個合理的參數(shù)很钓,結(jié)合地圖層級,將經(jīng)緯網(wǎng)絡(luò)分別生成并顯示出來董栽,同時在周圍顯示具體數(shù)據(jù)码倦,當(dāng)鼠標(biāo)拖動地圖、地圖放大縮小時锭碳,自動計算和更新經(jīng)緯網(wǎng)絡(luò)袁稽。比如,第3層擒抛,經(jīng)度范圍-180到180推汽,可以平均為8份制定經(jīng)線补疑,緯度范圍-90至90(實則為85°),可以平分為6份歹撒。
經(jīng)過測算莲组,不同層級內(nèi),經(jīng)緯度平分參數(shù)如下:
代碼為:
public static int[] lngsplit = {
2,
6,
8,
12,
24,
60,
120,
240,
360,
720,
1440,
2160,
4320,
9600,
21600,
43200,
64800,
129600,
259200,
648000,
1296000
};
public static int[] latsplit = {
2,
4,
6,
10,
15,
45,
90,
180,
270,
540,
1080,
2160,
3600,
7200,
21600,
43200,
64800,
129600,
324000,
648000,
1296000
};
具體實現(xiàn)步驟為暖夭,新建一個類LngLatGrid锹杈,構(gòu)造函數(shù)傳入?yún)?shù)GMapControl control,同時迈着,動態(tài)添加一個層嬉橙,用來放置經(jīng)緯線和刻度值文本。具體代碼如下
public LngLatGrid(GMapControl control)
{
this.control = control;
InitOverlay();
InitEvent();
}
/// <summary>
/// 初始化經(jīng)緯網(wǎng)層
/// </summary>
private void InitOverlay()
{
bool haslnglatgrid = false;
foreach (GMapOverlay overlay in control.Overlays)
{
if (overlay.Id.Equals("lnglatgrid"))
{
haslnglatgrid = true;
this.gridOverlay = overlay;
continue;
}
}
if (!haslnglatgrid)
{
gridOverlay = new GMapOverlay("lnglatgrid");
control.Overlays.Add(gridOverlay);
}
}
/// <summary>
/// 初始化事件
/// </summary>
private void InitEvent()
{
control.MouseDown += control_MouseDown;
control.MouseUp += control_MouseUp;
control.MouseMove += control_MouseMove;
control.OnMapZoomChanged += control_OnMapZoomChanged;
}
void control_OnMapZoomChanged()
{
UpdateLngLat();
}
void control_MouseMove(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (isDrag)
{
UpdateLngLat();
}
}
void control_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
isDrag = false; UpdateLngLat();
}
void control_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
isDrag = true;
}
internal void ClearLngLat()
{
gridOverlay.Clear();
}
經(jīng)緯網(wǎng)計算函數(shù)為:
這里要強調(diào)一下寥假,過細的拆分可能出現(xiàn)浮點數(shù)而變得不準(zhǔn)確市框,需要先將范圍擴大,所以我們可以把經(jīng)度×3600糕韧,相當(dāng)于把度換算成秒枫振,這樣平均計算時就不會有太大誤差。
public void UpdateLngLat()
{
if (GlobalConfig.isshowLnglatGird)
{
int zoom = (int)control.Zoom;
if (zoom > GlobalConfig.lngsplit.Length)
return;
gridOverlay.Clear();
Rectangle m = control.ClientRectangle;
PointLatLng p1 = control.FromLocalToLatLng(m.X, m.Y);
PointLatLng p2 = control.FromLocalToLatLng(m.Width, m.Height);
double latn = p1.Lat < 90 ? p1.Lat : 90;
double lats = p2.Lat > -90 ? p2.Lat : -90;
double lnge = p2.Lng < 180 ? p2.Lng : 180;
double lngw = p1.Lng > -180 ? p1.Lng : -180;
double lngsplit = 360d * 3600 / GlobalConfig.lngsplit[zoom - 1] ;
double latsplit = 180d * 3600 / GlobalConfig.latsplit[zoom - 1] ;
double mx = Convert.ToInt32(lngw * 3600 / lngsplit) * lngsplit;
double nx = Convert.ToInt32(lats * 3600 / latsplit) * latsplit;
for (double i = mx; i < lnge*3600; )
{
double cdeg = i / 3600;
GMapPolygon p = new GMapPolygon(new List<PointLatLng>()
{
new PointLatLng(lats,cdeg),
new PointLatLng(latn,cdeg)
}, "lng" + cdeg.ToString().PadLeft(3, '0'));
i += lngsplit;
p.Stroke = new Pen(new SolidBrush(Color.Black), 2);
gridOverlay.Polygons.Add(p);
GMapMarker markern = new LabelMarker(new PointLatLng(latn, cdeg), Tools.ToDegreeStr(cdeg,"lng"), Color.Black);
gridOverlay.Markers.Add(markern);
GPoint slatp = control.FromLatLngToLocal(new PointLatLng(lats, cdeg));
PointLatLng slat = control.FromLocalToLatLng((int)slatp.X, (int)(slatp.Y - 40));
GMapMarker markerw = new LabelMarker(slat, Tools.ToDegreeStr(cdeg, "lng"), Color.Black);
gridOverlay.Markers.Add(markerw);
}
for (double i = nx; i <= latn * 3600; )
{
double cdeg = i / 3600;
GMapPolygon p = new GMapPolygon(new List<PointLatLng>()
{
new PointLatLng(cdeg,lngw),
new PointLatLng(cdeg,lnge)
}, "lat" + cdeg.ToString().PadLeft(3, '0'));
i += latsplit;
p.Stroke = new Pen(new SolidBrush(Color.Red), 2);
gridOverlay.Polygons.Add(p);
GPoint elngp = control.FromLatLngToLocal(new PointLatLng(cdeg, lnge));
PointLatLng elng = control.FromLocalToLatLng((int)elngp.X - 140, (int)(elngp.Y));
GMapMarker markere = new LabelMarker(elng, Tools.ToDegreeStr(cdeg,"lat"), Color.Red);
gridOverlay.Markers.Add(markere);
GMapMarker markerw = new LabelMarker(new PointLatLng(cdeg, lngw), Tools.ToDegreeStr(cdeg, "lat"), Color.Red);
gridOverlay.Markers.Add(markerw);
}
control.Invalidate();
}
else
{
gridOverlay.Clear();
}
}
因為GMap.net中并未提供直接標(biāo)注文字的功能萤彩,所以我們要改造一個marker粪滤,用Graphics進行文本繪制,
using GMap.NET.WindowsForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Text;
namespace Mapmerger.Utils
{
class LabelMarker:GMapMarker
{
private string text;
public string Text
{
get { return text; }
set { text = value; }
}
private Color defaultColor;
public LabelMarker(GMap.NET.PointLatLng p, string text,Color color)
: base(p)
{
this.text = text;
this.defaultColor = color;
}
public override void OnRender(Graphics g)
{
RectangleF rect = new RectangleF(LocalPosition.X, LocalPosition.Y, Size.Width, Size.Height);
Font font = new Font("宋體", 18);
StringFormat format = StringFormat.GenericTypographic;
float dpi = g.DpiY;
using (GraphicsPath path = GetStringPath(text, dpi, rect, font, format))
{
g.SmoothingMode = SmoothingMode.AntiAlias;//設(shè)置字體質(zhì)量
g.DrawPath(Pens.White, path);//繪制輪廓(描邊)
g.FillPath(new SolidBrush(defaultColor), path);//填充輪廓(填充)
}
}
GraphicsPath GetStringPath(string s, float dpi, RectangleF rect, Font font, StringFormat format)
{
GraphicsPath path = new GraphicsPath();
float emSize = dpi * font.SizeInPoints / 72;
path.AddString(s, font.FontFamily, (int)font.Style, emSize, rect, format);
return path;
}
public override void Dispose()
{
base.Dispose();
}
}
}
相關(guān)功能測試效果較好雀扶,效率也很好杖小,因為動態(tài)更新且經(jīng)緯網(wǎng)和注記數(shù)量較少,運行速度很快愚墓。完工予权。