DotSpatial如何加载GeoServer、谷歌 、百度、腾讯的WMS地图
转载请注明来源:http://blog.csdn.net/caoshiying
首先说明一下,这篇文章讲解的是WMS地图,不是WMTS地图,讲的不是瓦片索引计算方法与坐标转换。朋友们在动手之前需要申请好腾讯的开发密钥以及百度的开发密钥,在局域网中搭建好GeoServer服务器。百度的开发密钥不需要高级认证。我的GeoServer服务浏览效果如下:
开篇以加载GeoServer的地图为例说明加载WMS的方法。考虑到WMS地图的本质是从网络上得到一张当前视野的图片,GeoServer、谷歌、百度、腾讯的WMS地图存在相同点,只是URL等细节不同。因上抽像出一个StaticImageLayer类型,代码如下:
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
abstract class StaticImageLayer : Layer, IMapLayer
{
public abstract string UrlFormat { get; }
private Bitmap syncBuffer;
public int ZoomLevel { get; set; }
public Size WindowSize { get; set; }
public StaticImageLayer()
{
WindowSize = new Size();
ZoomLevel = 0;
}
public void DrawRegions(MapArgs args, List<Extent> regions)
{
foreach (var region in regions)
{
if (region.Width <= 0 || region.Height <= 0)
continue;
if (WindowSize.Width <= 0 || WindowSize.Height <= 0 || ZoomLevel <= 0)
continue;
var bmp = GetBitmap(region);
if (bmp == null)
continue;
args.Device.DrawImage(bmp, 0, 0);
}
}
protected virtual Image GetBitmap(Extent e)
{
string geoserverUrl = GetURL(e);
Console.WriteLine(geoserverUrl);
var wc = new WebClient();
var bytes = wc.DownloadData(geoserverUrl);
if (bytes.Length < 400)
{
var text = Encoding.GetEncoding("UTF-8").GetString(bytes);
Console.WriteLine(text);
return null;
}
var str = new MemoryStream(bytes);
syncBuffer = new Bitmap(str);
str.Close();
str.Dispose();
return syncBuffer;
}
protected virtual string GetURL(Extent e)
{
return string.Format(UrlFormat, e.Center.X, e.Center.Y, WindowSize.Width, WindowSize.Height, ZoomLevel);
}
}
}
本类设置为象类型,不允许实例化。变化核心在于URL和图像获取算法,因此把这两个方法设为虚方法。不同的地图,比例尺、分辨率、坐标系是不同的,因此需要新建一个地图函数类型以支持不同的地图行为,代码如下:
using DotSpatial.Controls;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
class StaticImageFunction : MapFunction
{
StaticImageLayer baiduLayer;
Point firstPoint;
Point lastPoint;
public StaticImageFunction(IMap mapCtrl, StaticImageLayer layer)
: base(mapCtrl)
{
this.baiduLayer = layer;
}
protected override void OnMouseWheel(GeoMouseArgs e)
{
if (e.Delta > 0)
{
baiduLayer.ZoomLevel++;
}
else
{
baiduLayer.ZoomLevel--;
}
if (baiduLayer.ZoomLevel < 3)
baiduLayer.ZoomLevel = 3;
if (baiduLayer.ZoomLevel > 19)
baiduLayer.ZoomLevel = 19;
base.OnMouseWheel(e);
}
protected override void OnMouseDown(GeoMouseArgs e)
{
e.Handled = true;
firstPoint = e.Location;
base.OnMouseDown(e);
}
protected override void OnMouseUp(GeoMouseArgs e)
{
e.Handled = true;
lastPoint = e.Location;
base.OnMouseUp(e);
}
protected override void OnMouseMove(GeoMouseArgs e)
{
base.OnMouseMove(e);
}
}
}
这个StaticImageFunction其实只实现了百度地图的缩放行为。朋友们有不同的需求请参照此方法自行实现。
GeoServer图层的实现代码如下:
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
class GeoserverStaticImageLayer : StaticImageLayer
{
string geoserverUrlFormat = "http://192.168.1.4:8080/geoserver/wms?bbox={0},{1},{2},{3}&styles=&Format=image/png&request=GetMap&layers=bj54:china&width={4}&height={5}&srs=EPSG:2432";
public GeoserverStaticImageLayer()
{
LegendText = "Geoserver WMS地图";
}
protected override string GetURL(Extent e)
{
return string.Format(geoserverUrlFormat, e.MinX, e.MinY, e.MaxX, e.MaxY, WindowSize.Width, WindowSize.Height);
}
public override string UrlFormat
{
get { return geoserverUrlFormat; }
}
}
}
百度WMS图层的实现代码如下:
using DotSpatial.Controls;
using DotSpatial.Data;
using DotSpatial.Symbology;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
class BaiduStaticImageLayer : StaticImageLayer
{
string urlFormat = "http://api.map.baidu.com/staticimage/v2?ak=<span style="color:#ff0000;"><您申请的AK密钥></span>¢er={0},{1}&width={2}&height={3}&zoom={4}";
public BaiduStaticImageLayer():
base()
{
LegendText = "百度WMS地图";
}
public override string UrlFormat
{
get { return urlFormat; }
}
}
}
谷歌WMS地图不需要开发者申请密钥,实现代码如下:
using DotSpatial.Data;
using DotSpatial.Projections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
class GoogleStaticImageLayer : StaticImageLayer
{
public string urlFormat = "http://maps.google.cn/maps/api/staticmap?center={0},{1}&zoom={2}&size={3}x{4}&format=png&maptype=roadmap&sensor=false";
ProjectionInfo googleProj;
ProjectionInfo wgs84Proj;
public GoogleStaticImageLayer()
{
LegendText = "谷歌WMS地图";
googleProj = ProjectionInfo.FromProj4String("+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs");
wgs84Proj = ProjectionInfo.FromEpsgCode(4326);
}
protected override string GetURL(Extent e)
{
var xys = new double[] { e.Center.X, e.Center.Y };
var z = new double[1] { 0 };
DotSpatial.Projections.Reproject.ReprojectPoints(xys, z, wgs84Proj, googleProj, 0, 1);
return string.Format(urlFormat, xys[0], xys[1], ZoomLevel, WindowSize.Width, WindowSize.Height);
}
public override string UrlFormat
{
get { return urlFormat; }
}
}
}
腾讯WMS地图效果如下:
using DotSpatial.Controls;
using DotSpatial.Symbology;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace wms
{
class TencentStaticImageLayer : StaticImageLayer
{
string urlFormat = "http://apis.map.qq.com/ws/staticmap/v2/?center={0},{1}&size={2}*{3}&zoom={4}&maptype=roadmap&key=<请替换成您申请的密钥>";
public TencentStaticImageLayer()
{
LegendText = "腾讯WMS地图";
}
public override string UrlFormat
{
get { return urlFormat; }
}
protected override string GetURL(DotSpatial.Data.Extent e)
{
return string.Format(UrlFormat, e.Center.Y, e.Center.X, WindowSize.Width, WindowSize.Height, ZoomLevel);
}
}
}
这些图层加入DotSpatial地图控件的代码如下:
mapCtrl = new Map()
{
Width = Width,
Height = Height,
Left = 0,
Top = 0,
FunctionMode = FunctionMode.Pan,
Dock = DockStyle.Fill
};
imageLayer = new GeoserverStaticImageLayer()
{
Projection = mapCtrl.Projection,
WindowSize = this.Size,
ZoomLevel = 11
};
imageFunction = new StaticImageFunction(mapCtrl, imageLayer);
mapCtrl.Layers.Add(imageLayer);
mapCtrl.MapFunctions.Add(imageFunction);
Controls.Add(mapCtrl);
mapCtrl.ActivateMapFunction(imageFunction);
mapCtrl.ViewExtents = new Extent(114.29189, 30.39661, 114.52518, 30.51317);
最终一个桌面WinForm程序运行效果如下:
转载自:https://blog.csdn.net/caoshiying/article/details/51984796