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

You may also like...