三 打造地图拼接利器图源配置( 二 )


然后新建一个类,继承自我们刚新建的类,重新其核心方法
( pos, int zoom){}
【三打造地图拼接利器图源配置】当我们使用自定义的地图源时,就会调用这个函数,传来瓦片坐标和层级,然后通过网络请求,返回瓦片图片对象 。
为我们提供了一个函数p( url),用以通过一个网络瓦片地址返回一个瓦片图片 。

三  打造地图拼接利器图源配置

文章插图
如何获得这个地址呢,我们以获取天地图瓦片地址为例 。打开谷歌浏览器,输入,按F12进入浏览器调试模式,选择选项卡,然后调整地图大小,可以看到图片请求地址:
拷贝其中一个,可以看到:
https://t3.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL=11&TILEROW=5&TILEMATRIX=4&tk=9a02b3cdd29cd346de4df04229797710
其中,t3代表第3个服务器,=11&=5&=4代表x=11,y=5,z=4,最后还有一个密钥tk,如果没有这个tk,就无法访问到数据 。密钥可以通过注册天地图开发者账号申请,但普通开发者每天只能访问10000次数据,公司和政府机构会比较多,分别为300w和500w 。
在实际使用过程中,内置p( url)函数并不能获取到所有网站的数据,因为地图服务端认为客户端不是浏览器,所以我们要重新一个请求程序,在http请求头中加入“我是浏览器”的声明,才可以获取到数据 。
我们新建一个Tools类,再新建一个下载图片的函数:
public static byte[] downloadTile(string url){try{WebClient myClient = new WebClient();myClient.Headers.Add( "User-Agent","Mozilla/5.0(Windows NT 6.1;Win64; x64; rv:50.0) Gecko/20100101 Firefox/50.0");//这里就是告诉服务器,我是浏览器myClient.Encoding = Encoding.UTF8;Uri uri = new Uri(url);byte[] bts = myClient.DownloadData(uri);return bts;}catch (Exception err){return null;}}
同时,为了提高程序复用性,我们通过一个地址就可以自动生成一个心得,需要写一个地址解析函数,自动替换{x},{y},{z}和服务器地址,比如把[1-4]./{z}/{x}/{y}.png根据请求自动替换为:
public static string getUrl(string urlformat,int x,int y ,int z){int leftSignPos = -1, rightSignPos = -1;leftSignPos = urlformat.IndexOf('[');rightSignPos = urlformat.IndexOf(']');if (leftSignPos > 0 && rightSignPos > leftSignPos){string serverstr = urlformat.Substring(leftSignPos + 1, rightSignPos - leftSignPos - 1);int startnum = int.Parse(serverstr.Split('-')[0]);int endnum = int.Parse(serverstr.Split('-')[1]);long num = (x + y) % (endnum - startnum) + startnum;string nurl = urlformat.Substring(0, leftSignPos) + num + urlformat.Substring(rightSignPos + 1);urlformat = nurl;}urlformat = urlformat.Replace("{x}", x.ToString()).Replace("{y}", y.ToString()).Replace("{z}", z.ToString());return urlformat;}
还有一个很重要的问题,就是图片合并的问题,有些卫星图是不带路网和地名的,需要将两个图形合并后返回 。所以我们为提供一个参数,用以将1种图或2种图合并后返回给地图程序 。
三  打造地图拼接利器图源配置

文章插图
public override PureImage GetTileImage(GPoint pos, int zoom){try{if (urls.Count == 2){PureImage image =GetMultiImgFromUrl(pos, zoom, urls[0], urls[1]);return image;}else{PureImage image = GetImgFromUrl(pos, zoom, urls[0]);return image;}}catch (Exception ex){return null;}}
图片返回函数如下:
PureImage GetImgFromUrl(GPoint pos, int zoom, string url){string durl = MakeTileImageUrl(pos, zoom, url);byte[] bts = Tools.downloadTile(durl);MemoryStream ms = new MemoryStream();ms.Write(bts, 0, bts.Length);Image img = Bitmap.FromStream(ms);GMapImage gimg = new GMapImage();gimg.Data = http://www.kingceram.com/post/ms;gimg.Img = img;ms.Dispose();return gimg;}PureImage GetMultiImgFromUrl(GPoint pos, int zoom, string url1, string url2){GMapImage img = new GMapImage();string durl1 = MakeTileImageUrl(pos, zoom, url1);byte[] bts1 = Tools.downloadTile(durl1);string durl2 = MakeTileImageUrl(pos, zoom, url2);byte[] bts2 = Tools.downloadTile(durl2);MemoryStream ms1 = new MemoryStream();ms1.Write(bts1, 0, bts1.Length);Image img1 = Bitmap.FromStream(ms1);MemoryStream ms2 = new MemoryStream();ms2.Write(bts2, 0, bts2.Length);Image img2 = Bitmap.FromStream(ms2);Image bit = new Bitmap(256,256);Graphics g = Graphics.FromImage(bit);g.DrawImage(img1, 0, 0, img1.Width, img1.Height);g.DrawImage(img2, 0, 0, img2.Width, img2.Height);MemoryStream ms = new MemoryStream();bit.Save(ms, System.Drawing.Imaging.ImageFormat.Png);img.Img = bit;img.Data = ms;g.Dispose();ms.Close();ms1.Dispose();ms2.Dispose();return img;