美文网首页GIS常用
打造地图拼接利器(三)图源配置

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

作者: 安静的林哥 | 来源:发表于2021-06-27 00:39 被阅读0次

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

    GMap.net内置了74个地图图源,清单如下:

    ArcGIS_DarbAE_Q2_2011_NAVTQ_Eng_V5_MapProvider ArcGIS_DarbAE_Q2_2011_NAVTQ_Eng_V5_Map;
      ArcGIS_Imagery_World_2D_MapProvider ArcGIS_Imagery_World_2D_Map;
      ArcGIS_ShadedRelief_World_2D_MapProvider ArcGIS_ShadedRelief_World_2D_Map;
      ArcGIS_StreetMap_World_2D_MapProvider ArcGIS_StreetMap_World_2D_Map;
      ArcGIS_Topo_US_2D_MapProvider ArcGIS_Topo_US_2D_Map;
      ArcGIS_World_Physical_MapProvider ArcGIS_World_Physical_Map;
      ArcGIS_World_Shaded_Relief_MapProvider ArcGIS_World_Shaded_Relief_Map;
      ArcGIS_World_Street_MapProvider ArcGIS_World_Street_Map;
      ArcGIS_World_Terrain_Base_MapProvider ArcGIS_World_Terrain_Base_Map;
      ArcGIS_World_Topo_MapProvider ArcGIS_World_Topo_Map;
      BingHybridMapProvider BingHybridMap;
      BingMapProvider BingMap;
      BingSatelliteMapProvider BingSatelliteMap;
      CloudMadeMapProvider CloudMadeMap;
      CzechGeographicMapProvider CzechGeographicMap;
      CzechHistoryMapProvider CzechHistoryMap;
      CzechHistoryMapProviderOld CzechHistoryOldMap;
      CzechHybridMapProvider CzechHybridMap;
      CzechHybridMapProviderOld CzechHybridOldMap;
      CzechMapProvider CzechMap;
      CzechMapProviderOld CzechOldMap;
      CzechSatelliteMapProvider CzechSatelliteMap;
      CzechSatelliteMapProviderOld CzechSatelliteOldMap;
      CzechTuristMapProvider CzechTuristMap;
      CzechTuristMapProviderOld CzechTuristOldMap;
      CzechTuristWinterMapProvider CzechTuristWinterMap;
      EmptyProvider EmptyProvider;
      GoogleChinaHybridMapProvider GoogleChinaHybridMap;
      GoogleChinaMapProvider GoogleChinaMap;
      GoogleChinaSatelliteMapProvider GoogleChinaSatelliteMap;
      GoogleChinaTerrainMapProvider GoogleChinaTerrainMap;
      GoogleHybridMapProvider GoogleHybridMap;
      GoogleKoreaHybridMapProvider GoogleKoreaHybridMap;
      GoogleKoreaMapProvider GoogleKoreaMap;
      GoogleKoreaSatelliteMapProvider GoogleKoreaSatelliteMap;
      GoogleMapProvider GoogleMap;
      GoogleSatelliteMapProvider GoogleSatelliteMap;
      GoogleTerrainMapProvider GoogleTerrainMap;
      LatviaMapProvider LatviaMap;
      Lithuania3dMapProvider Lithuania3dMap;
      LithuaniaHybridMapProvider LithuaniaHybridMap;
      LithuaniaHybridOldMapProvider LithuaniaHybridOldMap;
      LithuaniaMapProvider LithuaniaMap;
      LithuaniaOrtoFotoMapProvider LithuaniaOrtoFotoMap;
      LithuaniaOrtoFotoOldMapProvider LithuaniaOrtoFotoOldMap;
      LithuaniaReliefMapProvider LithuaniaReliefMap;
      LithuaniaTOP50 LithuaniaTOP50Map;
      MapBenderWMSProvider MapBenderWMSdemoMap;
      NearHybridMapProvider NearHybridMap;
      NearMapProvider NearMap;
      NearSatelliteMapProvider NearSatelliteMap;
      OpenCycleLandscapeMapProvider OpenCycleLandscapeMap;
      OpenCycleMapProvider OpenCycleMap;
      OpenCycleTransportMapProvider OpenCycleTransportMap;
      OpenSeaMapHybridProvider OpenSeaMapHybrid;
      OpenStreet4UMapProvider OpenStreet4UMap;
      OpenStreetMapProvider OpenStreetMap;
      OpenStreetMapQuestProvider OpenStreetMapQuest;
      OpenStreetMapQuestHybridProvider OpenStreetMapQuestHybrid;
      OpenStreetMapQuestSatteliteProvider OpenStreetMapQuestSattelite;
      OviHybridMapProvider OviHybridMap;
     OviMapProvider OviMap;
      OviSatelliteMapProvider OviSatelliteMap;
      OviTerrainMapProvider OviTerrainMap;
      SpainMapProvider SpainMap;
      SwedenMapProvider SwedenMap;
      TurkeyMapProvider TurkeyMap;
      WikiMapiaMapProvider WikiMapiaMap;
      YahooHybridMapProvider YahooHybridMap;
      YahooMapProvider YahooMap;
      YahooSatelliteMapProvider YahooSatelliteMap;
      YandexHybridMapProvider YandexHybridMap;
      YandexMapProvider YandexMap;
      YandexSatelliteMapProvider YandexSatelliteMap;
    

    但在实际使用中,大部分都因一些未知因素而无法访问,特别是国外的地图,大部分对我国边境标绘错误,需谨慎使用。而且这些地图中,鲜有国内地图商的地址。

    为便于使用国内地图,我们需要写一些访问国内地图数据的代码,还好,GMap.net开源,我们可以照猫画虎,写一个通用的TMSProvider。

    在解决方案资源管理器中建一个文件夹,名为Utils。

    要是用自定义Provider,首先建一个基类TmsProviderBase,让他继承自GMapProvider,并重写2个方法。

    using GMap.NET;
    using GMap.NET.MapProviders;
    using GMap.NET.Projections;
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace Mapmeger
    {
        public abstract class TmsProviderBase : GMapProvider
        {
            public TmsProviderBase()
            {
                MaxZoom = null;
                RefererUrl = "";
            }
    
            public override PureProjection Projection
            {
                get { return MercatorProjection.Instance; }
            }
    
            GMapProvider[] overlays;
            public override GMapProvider[] Overlays
            {
                get
                {
                    if (overlays == null)
                    {
                        overlays = new GMapProvider[] { this };
                    }
                    return overlays;
                }
            }
        }
    }
    

    然后新建一个类TmsProvider,继承自我们刚新建的类TmsProviderBase,重新其核心方法

    public override PureImage GetTileImage(GPoint pos, int zoom){}

    当我们使用自定义的地图源时,就会调用这个函数,传来瓦片坐标GPoint和层级,然后通过网络请求,返回瓦片图片对象。

    GMap.net为我们提供了一个函数GetTileImageUsingHttp(string url),用以通过一个网络瓦片地址返回一个瓦片图片。

    如何获得这个地址呢,我们以获取天地图瓦片地址为例。打开谷歌浏览器,输入https://www.tianditu.gov.cn/,按F12进入浏览器调试模式,选择Network选项卡,然后调整地图大小,可以看到图片请求地址:

    3.1.png

    拷贝其中一个,可以看到:

    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个服务器,TILECOL=11&TILEROW=5&TILEMATRIX=4代表x=11,y=5,z=4,最后还有一个密钥tk,如果没有这个tk,就无法访问到数据。密钥可以通过注册天地图开发者账号申请,但普通开发者每天只能访问10000次数据,公司和政府机构会比较多,分别为300w和500w。

    在实际使用过程中,内置GetTileImageUsingHttp(string 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;
                }
            }
    

    同时,为了提高程序复用性,我们通过一个地址就可以自动生成一个心得Provider,需要写一个地址解析函数,自动替换{x},{y},{z}和服务器地址,比如把https://a[1-4].tile.openstreetmap.org/{z}/{x}/{y}.png根据请求自动替换为https://a1.tile.openstreetmap.org/3/1/1.png

    
    

    还有一个很重要的问题,就是图片合并的问题,有些卫星图是不带路网和地名的,需要将两个图形合并后返回。所以我们为TmsProvider提供一个参数,用以将1种图或2种图合并后返回给地图程序。

      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;
            }
    

    图片返回函数如下:

     PureImage GetImgFromUrl(GPoint pos, int zoom, string url)
            {
                //return GetTileImageUsingHttp(MakeTileImageUrl(pos, zoom, 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 = 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;
            }
    

    在前端,我们通过一个配置文件config.txt,将能使用的图源地址进行配置:

    //配置说明:竖线前为地图名称,后为TMS地址,方括号内为服务器序号,{x}\{y}\{z}分别代表瓦片坐标。很多地图都需要key授权,天地图的key可以自行申请,每天都会受到使用次数限制
    openstreet交通|https://a.tile.openstreetmap.org/{z}/{x}/{y}.png
    高德影像|https://webst0[1-4].is.autonavi.com/appmaptile?style=6&x={x}&y={y}&z={z}
    高德矢量|http://wprd0[1-4].is.autonavi.com/appmaptile?lang=zh_cn&size=1&style=7&x={x}&y={y}&z={z}
    高德注记|https://wprd0[1-4].is.autonavi.com/appmaptile?x={x}&y={y}&z={z}&lang=zh_cn&size=1&scl=1&style=8
    天地图交通|https://t[1-4].tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=c03258c0232becff8dfbd108c02a3265
    天地图卫星|https://t[1-4].tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=c03258c0232becff8dfbd108c02a3265
    天地图地形|https://t[1-4].tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=c03258c0232becff8dfbd108c02a3265
    天地图注记|https://t[1-4].tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILECOL={x}&TILEROW={y}&TILEMATRIX={z}&tk=c03258c0232becff8dfbd108c02a3265
    

    在主程序加载时,将图层分别绑定到地图和覆盖图上。

     private void InitMapurls()
            {
                string configfile = Application.StartupPath + "\\config.txt";
                if (File.Exists(configfile))
                {
                    string[] configlines = File.ReadAllLines(configfile);
                    for (int i = 0; i < configlines.Length; i++)
                    {
                        if (!configlines[i].StartsWith("//"))
                        {
                            curmapurls.Add(configlines[i].Split('|')[1]);
                            break;
                        }
                    }
                    DataTable dt = new DataTable();
                    dt.Columns.Add("text");
                    dt.Columns.Add("value");
                    DataTable dt1 = dt.Clone();
                    for (int i = 0; i < configlines.Length; i++)
                    {
                        if (!configlines[i].StartsWith("//"))
                        {
                            mapurls.Add(configlines[i]);
                            DataRow row = dt.NewRow();
                            row[0] = configlines[i].Split('|')[0];
                            row[1] = configlines[i].Split('|')[1];
                            dt.Rows.Add(row);
                            dt1.Rows.Add(row.ItemArray);
                        }
                    }
                    CBLayer1.DataSource = dt;
                    CBLayer1.DisplayMember = "text";
                    CBLayer1.ValueMember = "value";
                    CBLayer2.DataSource = dt1;
                    CBLayer2.DisplayMember = "text";
                    CBLayer2.ValueMember = "value";
                }
                else
                {
                    curmapurls.Add("https://a.tile.openstreetmap.org/{z}/{x}/{y}.png");
                }
    
            }
    

    当图源下拉框变化时,切换地图:

        void changeMap()
            {
                if (isfirtload)
                    return;
                curmapurls.Clear();
                curmapurls.Add(((DataRowView)CBLayer1.SelectedItem)[1].ToString());
                if (CBShow.CheckState==CheckState.Checked)
                {
                    curmapurls.Add(((DataRowView)CBLayer2.SelectedItem)[1].ToString());
                }
                gmapc.MapProvider = new TmsProvider(curmapurls);
            }
    

    同时,将gmapc.MapProvider =new TmsProvider(curmapurls);设置为自定义图源。其中curmapurls为一个泛型,用来记录右上角选择的地图的地址。

    3.2.png

    相关文章

      网友评论

        本文标题:打造地图拼接利器(三)图源配置

        本文链接:https://www.haomeiwen.com/subject/tdhtultx.html