第二章 构架属于自己的WMTS服务,数据下载整合篇1

 第一步构建下载数据源的描述文件

如此XML结构

<?xml version="1.0" encoding="utf-8"?>
<onlinemapsources>
 
 <onlineMapSource>
  <name>GaoDeDiTuImage</name>
  <url><![CDATA[http://webst0{$s}.is.autonavi.com/appmaptile?style=6&x={$x}&y={$y}&z={$z}]]></url>
  <servers>1,2,3,4</servers>
 </onlineMapSource>
 
</onlinemapsources>

其中NAME节点描述下载地图数据源名称

url为需要下载数据源切片的访问方式的URL

servers为在线地图的服务器个数。

下面我们以天地图为例

首先构建DATASROUS对象 所有数据源的基类

 /// <summary>
    /// 所有数据缓存下载转换的基类
    /// </summary>
    public abstract class DataSourceBase
    {
        ~DataSourceBase()
        {
            if (_connLocalCacheFile != null)
                _connLocalCacheFile.Close();
            _connLocalCacheFile = null;
        }
        /// <summary>
        /// 预定义或者在线地图
        /// </summary>
        public string Type { get; set; }
        /// <summary>
        /// 数据服务地址
        /// </summary>
        public string Path { get; set; }
        /// <summary>
        /// 服务的元数据信息
        /// </summary>
        public TilingScheme TilingScheme { get; set; }
        /// <summary>
        /// 表述该地图源头为在线地图
        /// 很多方法数据的下载取决于这个属性
        /// </summary>
        public bool IsOnlineMap { get; set; }

        /// <summary>
        /// 初始化 对象生成下载和转换方案
        /// </summary>
        protected virtual void Initialize(string path)
        {
            
            this.Path = path;
            TilingScheme ts;
            try
            {
                ReadTilingScheme(out ts);
            }
            catch (Exception e)
            {
                throw new Exception("读取瓦片的元数据失败!\r\n" + e.Message+"\r\n"+e.StackTrace);
            }
            TilingScheme = ts;
            IsOnlineMap = IsOnlineMaps(Type);
        }

        /// <summary>
        /// TODO: 读取对应数据源的元数据信息
        /// </summary>
        /// <param name="tilingScheme"></param>
        /// <param name="lodsJson"></param>
        protected abstract void ReadTilingScheme(out TilingScheme tilingScheme);

        /// <summary>
        /// 生成JSON字符串
        /// </summary>
        /// <param name="tilingScheme"></param>
        /// <returns></returns>
        protected TilingScheme TilingSchemePostProcess(TilingScheme tilingScheme)
        {
            #region ArcGIS REST Service Info
            string pjson = @"{
  ""currentVersion"" : 10.01,
  ""serviceDescription"" : ""This service is populated from PortableBasemapServer by diligentpig. For more information goto http://newnaw.com"",
  ""mapName"" : ""Layers"",
  ""description"" : ""none"",
  ""copyrightText"" : ""IMapGeoServer by diligentpig, REST API by Esri"",
  ""layers"" : [
    {
      ""id"" : 0,
      ""name"" : ""YourServiceNameHere"",
      ""parentLayerId"" : -1,
      ""defaultVisibility"" : true,
      ""subLayerIds"" : null,
      ""minScale"" : 0,
      ""maxScale"" : 0
    }
  ],
  ""tables"" : [
   
  ],
  ""spatialReference"" : {
    ""wkid"" : " + tilingScheme.WKID + @"
  },
  ""singleFusedMapCache"" : true,
  ""tileInfo"" : {
    ""rows"" : " + tilingScheme.TileRows + @",
    ""cols"" : " + tilingScheme.TileCols + @",
    ""dpi"" : " + tilingScheme.DPI + @",
    ""format"" : """ + tilingScheme.CacheTileFormat + @""",
    ""compressionQuality"" : " + tilingScheme.CompressionQuality + @",
    ""origin"" : {
      ""x"" : " + tilingScheme.TileOrigin.X + @",
      ""y"" : " + tilingScheme.TileOrigin.Y + @"
    },
    ""spatialReference"" : {
      ""wkid"" : " + tilingScheme.WKID + @"
    },
    ""lods"" : [" + tilingScheme.LODsJson + @"
    ]
  },
  ""initialExtent"" : {
    ""xmin"" : " + tilingScheme.InitialExtent.XMin + @",
    ""ymin"" : " + tilingScheme.InitialExtent.YMin + @",
    ""xmax"" : " + tilingScheme.InitialExtent.XMax + @",
    ""ymax"" : " + tilingScheme.InitialExtent.YMax + @",
    ""spatialReference"" : {
      ""wkid"" : " + tilingScheme.WKID + @"
    }
  },
  ""fullExtent"" : {
    ""xmin"" : " + tilingScheme.FullExtent.XMin + @",
    ""ymin"" : " + tilingScheme.FullExtent.YMin + @",
    ""xmax"" : " + tilingScheme.FullExtent.XMax + @",
    ""ymax"" : " + tilingScheme.FullExtent.YMax + @",
    ""spatialReference"" : {
      ""wkid"" : " + tilingScheme.WKID + @"
    }
  },
  ""units"" : ""esriMeters"",
  ""supportedImageFormatTypes"" : ""PNG24,PNG,JPG,DIB,TIFF,EMF,PS,PDF,GIF,SVG,SVGZ,AI,BMP"",
  ""documentInfo"" : {
    ""Title"" : ""none"",
    ""Author"" : ""none"",
    ""Comments"" : ""none"",
    ""Subject"" : ""none"",
    ""Category"" : ""none"",
    ""Keywords"" : ""none"",
    ""Credits"" : ""diligentpig""
  },
  ""capabilities"" : ""Map,Query,Data""
}
";
            #endregion
            tilingScheme.RestResponseArcGISPJson = pjson;
            tilingScheme.RestResponseArcGISJson = pjson.Replace("\r\n", "").Replace("\n", "");
            return tilingScheme;
        }

        /// <summary>
        /// TODO: 获取瓦片的的二进制文件
        /// </summary>
        /// <param name="level"></param>
        /// <param name="row"></param>
        /// <param name="col"></param>
        /// <returns></returns>
        public abstract byte[] GetTileBytes(int level, int row, int col);
        /// <summary>
        /// 当瓦片开始加载的时候执行
        /// </summary>
        public EventHandler<TileLoadEventArgs> TileLoaded;

        #region 读取瓦片的的元数据
        protected void ReadSqliteTilingScheme(out TilingScheme tilingScheme, SQLiteConnection sqlConn)
        {
            tilingScheme = new TilingScheme();
            StringBuilder sb;
            #region 读取MBtile中的元数据信息
            tilingScheme.Path = "N/A";
            bool isMACFile = false;
            using (SQLiteCommand cmd = new SQLiteCommand(sqlConn))
            {
                cmd.CommandText = "SELECT COUNT(*) FROM sqlite_master WHERE type='table' AND name='info'";
                long i = (long)cmd.ExecuteScalar();
                if (i == 0)
                    isMACFile = false;
                else
                    isMACFile = true;
              
                if (!isMACFile)
                {
                   
                    cmd.CommandText = string.Format("SELECT value FROM metadata WHERE name='format'");
                    object o = cmd.ExecuteScalar();
                    if (o != null)
                    {
                        string f = o.ToString();
                        tilingScheme.CacheTileFormat = f.ToUpper().Contains("PNG") ? ImageFormat.PNG : ImageFormat.JPG;
                    }
                    else
                    {
                        tilingScheme.CacheTileFormat = ImageFormat.JPG;
                    }
                }
            }
            tilingScheme.CompressionQuality = 75;
            tilingScheme.DPI = 96;
           
            tilingScheme.LODs = new LODInfo[20];
            const double cornerCoordinate = 20037508.342787;
            double resolution = cornerCoordinate * 2 / 256;
            double scale = 591657527.591555;
            for (int i = 0; i < tilingScheme.LODs.Length; i++)
            {
                tilingScheme.LODs[i] = new LODInfo()
                {
                    Resolution = resolution,
                    LevelID = i,
                    Scale = scale
                };
                resolution /= 2;
                scale /= 2;
            }
           
            sb = new StringBuilder("\r\n");
           
            foreach (LODInfo lod in tilingScheme.LODs)
            {
                sb.Append(@"      {""level"":" + lod.LevelID + "," + @"""resolution"":" + lod.Resolution + "," + @"""scale"":" + lod.Scale + @"}," + "\r\n");
            }
            tilingScheme.LODsJson = sb.ToString().Remove(sb.ToString().Length - 3);
            try
            {
                using (SQLiteCommand sqlCmd = new SQLiteCommand(sqlConn))
                {
                    sqlCmd.CommandText = string.Format("SELECT value FROM metadata WHERE name='bounds'");
                    object o = sqlCmd.ExecuteScalar();
                    if (o != null)
                    {
                        string[] bounds = o.ToString().Split(new char[] { ',' });
                        Point leftBottom = new Point(double.Parse(bounds[0]), double.Parse(bounds[1]));
                        Point rightTop = new Point(double.Parse(bounds[2]), double.Parse(bounds[3]));
                        leftBottom = Utility.GeographicToWebMercator(leftBottom);
                        rightTop = Utility.GeographicToWebMercator(rightTop);
                        tilingScheme.InitialExtent = new Envelope(leftBottom.X, leftBottom.Y, rightTop.X, rightTop.Y);
                        tilingScheme.FullExtent = tilingScheme.InitialExtent;
                    }
                    else
                    {
                        throw new Exception();
                    }
                }
            }
            catch (Exception)
            {
                tilingScheme.InitialExtent = new Envelope(-cornerCoordinate, -cornerCoordinate, cornerCoordinate, cornerCoordinate);
                tilingScheme.FullExtent = tilingScheme.InitialExtent;
            }
            tilingScheme.PacketSize = 0;
            tilingScheme.StorageFormat = StorageFormat.esriMapCacheStorageModeExploded;
            tilingScheme.TileCols = tilingScheme.TileRows = 256;
            tilingScheme.TileOrigin = new Point(-cornerCoordinate, cornerCoordinate);
            tilingScheme.WKID = 3857;
            tilingScheme.WKT = @"PROJCS[""WGS_1984_Web_Mercator_Auxiliary_Sphere"",GEOGCS[""GCS_WGS_1984"",DATUM[""D_WGS_1984"",SPHEROID[""WGS_1984"",6378137.0,298.257223563]],PRIMEM[""Greenwich"",0.0],UNIT[""Degree"",0.0174532925199433]],PROJECTION[""Mercator_Auxiliary_Sphere""],PARAMETER[""False_Easting"",0.0],PARAMETER[""False_Northing"",0.0],PARAMETER[""Central_Meridian"",0.0],PARAMETER[""Standard_Parallel_1"",0.0],PARAMETER[""Auxiliary_Sphere_Type"",0.0],UNIT[""Meter"",1.0],AUTHORITY[""ESRI"",""3857""]]";
            #endregion
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="path">切片方案的路径而不是数据源头的路径</param>
        /// <param name="tilingScheme"></param>
        protected void ReadArcGISTilingSchemeFile(string path, out TilingScheme tilingScheme)
        {
            tilingScheme = new TilingScheme();
            StringBuilder sb;
            #region 读取arcgis缓存的描述文件
            if (!System.IO.File.Exists(path))//当数据产生缓存时候path是一个目录
            {
                path += "\\conf.xml";
            }
            tilingScheme.Path = path;//构建完整的目录地址
          //读取配置描述文件
            XElement confXml = XElement.Load(System.IO.Path.GetDirectoryName(path) + @"\\conf.xml");
            tilingScheme.WKT = confXml.Element("TileCacheInfo").Element("SpatialReference").Element("WKT").Value;
            if (confXml.Element("TileCacheInfo").Element("SpatialReference").Element("WKID") != null)
                tilingScheme.WKID = int.Parse(confXml.Element("TileCacheInfo").Element("SpatialReference").Element("WKID").Value);
            else
                tilingScheme.WKID = -1;
            tilingScheme.TileOrigin = new Point(
                double.Parse(confXml.Element("TileCacheInfo").Element("TileOrigin").Element("X").Value),
                double.Parse(confXml.Element("TileCacheInfo").Element("TileOrigin").Element("Y").Value));
            tilingScheme.DPI = int.Parse(confXml.Element("TileCacheInfo").Element("DPI").Value);
           
            int lodsCount = confXml.Element("TileCacheInfo").Element("LODInfos").Elements().Count();
            tilingScheme.LODs = new LODInfo[lodsCount];
            for (int i = 0; i < lodsCount; i++)
            {
                tilingScheme.LODs[i] = new LODInfo()
                {
                    LevelID = i,
                    Scale = double.Parse(confXml.Element("TileCacheInfo").Element("LODInfos").Elements().ElementAt(i).Element("Scale").Value),
                    Resolution = double.Parse(confXml.Element("TileCacheInfo").Element("LODInfos").Elements().ElementAt(i).Element("Resolution").Value)
                };
            }
            sb = new StringBuilder("\r\n");
            
            foreach (LODInfo lod in tilingScheme.LODs)
            {
                sb.Append(@"      {""level"":" + lod.LevelID + "," + @"""resolution"":" + lod.Resolution + "," + @"""scale"":" + lod.Scale + @"}," + "\r\n");
            }
            tilingScheme.LODsJson = sb.ToString().Remove(sb.ToString().Length - 3);//remove last "," and "\r\n"
            tilingScheme.TileCols = int.Parse(confXml.Element("TileCacheInfo").Element("TileCols").Value);
            tilingScheme.TileRows = int.Parse(confXml.Element("TileCacheInfo").Element("TileRows").Value);
            tilingScheme.CacheTileFormat = (ImageFormat)Enum.Parse(typeof(ImageFormat), confXml.Element("TileImageInfo").Element("CacheTileFormat").Value.ToUpper());
            tilingScheme.CompressionQuality = int.Parse(confXml.Element("TileImageInfo").Element("CompressionQuality").Value);
            tilingScheme.StorageFormat = (StorageFormat)Enum.Parse(typeof(StorageFormat), confXml.Element("CacheStorageInfo").Element("StorageFormat").Value);
            tilingScheme.PacketSize = int.Parse(confXml.Element("CacheStorageInfo").Element("PacketSize").Value);
            //read conf.cdi
            XElement confCdi = XElement.Load(System.IO.Path.GetDirectoryName(path) + @"\\conf.cdi");
            try
            {
                tilingScheme.FullExtent = new Envelope(
                double.Parse(confCdi.Element("XMin").Value),
                double.Parse(confCdi.Element("YMin").Value),
                double.Parse(confCdi.Element("XMax").Value),
                double.Parse(confCdi.Element("YMax").Value));
            }
            catch (Exception e)
            {
                throw new Exception("the content of conf.cdi file is not valid!" + e.Message);
            }
            tilingScheme.InitialExtent = tilingScheme.FullExtent;
            #endregion
        }

        /// <summary>
        /// 创建TilingScheme解析ArcGISTiledMapService信息
        /// </summary>
        /// <param name="ht">哈希表包含所有ArcGISTiledMapService信息解析JSON util类.</param>
        /// <param name="tilingScheme"></param>
        protected void ReadArcGISTiledMapServiceTilingScheme(Hashtable ht, out TilingScheme tilingScheme)
        {
            tilingScheme = new TilingScheme();
            StringBuilder sb;
            #region 读取缓存的元数据
            tilingScheme.Path = "N/A";
            tilingScheme.WKT = (ht["spatialReference"] as Hashtable)["wkt"] == null ? "Absent" : (string)(ht["spatialReference"] as Hashtable)["wkt"];
            tilingScheme.WKID = int.Parse((ht["spatialReference"] as Hashtable)["wkid"].ToString());
            tilingScheme.TileOrigin = new Point(
                (double)((ht["tileInfo"] as Hashtable)["origin"] as Hashtable)["x"],
                (double)((ht["tileInfo"] as Hashtable)["origin"] as Hashtable)["y"]);
            tilingScheme.DPI = int.Parse((ht["tileInfo"] as Hashtable)["dpi"].ToString());
            //LODInfos
            int lodsCount = ((ht["tileInfo"] as Hashtable)["lods"] as ArrayList).Count;
            tilingScheme.LODs = new LODInfo[lodsCount];
            for (int i = 0; i < lodsCount; i++)
            {
                tilingScheme.LODs[i] = new LODInfo()
                {
                    LevelID = i,
                    Scale = (double)(((ht["tileInfo"] as Hashtable)["lods"] as ArrayList)[i] as Hashtable)["scale"],
                    Resolution = (double)(((ht["tileInfo"] as Hashtable)["lods"] as ArrayList)[i] as Hashtable)["resolution"]
                };
            }
            sb = new StringBuilder("\r\n");
           
            foreach (LODInfo lod in tilingScheme.LODs)
            {
                sb.Append(@"      {""level"":" + lod.LevelID + "," + @"""resolution"":" + lod.Resolution + "," + @"""scale"":" + lod.Scale + @"}," + "\r\n");
            }
            tilingScheme.LODsJson = sb.ToString(

<think>好的,用户想了解如何在ArcGIS中导出WMTS服务数据。首先,我需要回忆一下ArcGIS的相关功能和限制。记得在ArcMap中,直接导出WMTS数据可能不太行,但ArcGIS Pro可能有不同的方法。根据引用3,用户提到在Pro中可以通过布局视图导出,而ArcMap不行。这可能涉及到将地图导出为图片或特定格式,比如TIFF或PDF。 接下来,需要分步骤说明操作流程。首先在Pro中添加WMTS服务,然后可能需要在布局视图中调整范围,再使用导出地图功能。另外,用户可能需要设置导出范围,比如数据驱动页面或者自定义范围。还要注意WMTS服务可能有缓存或切片限制,导出大范围数据可能需要分块处理或者使用其他工具,比如ArcPy自动化导出。 另外,引用2提到REST服务的导出瓦片功能,但WMTS是否支持呢?可能需要检查服务是否允许导出,或者是否有权限问题。如果服务不支持直接导出,可能需要用QGIS或其他工具,如引用4中的QGIS步骤,但用户问的是ArcGIS,所以可能需要专注于Pro的方法。 还要考虑用户的实际需求,比如是否需要高分辨率或特定区域的数据。导出时的DPI设置和格式选择也很重要。最后,提醒用户注意版权和使用权限,确保合法使用数据。总结步骤,可能需要验证在Pro中的具体操作,确保步骤正确,并引用相关的参考资料。</think>### 如何在 ArcGIS 中导出 WMTS 服务数据? #### 方法一:通过 ArcGIS Pro 导出影像 1. **添加 WMTS 服务** - 在 ArcGIS Pro 中,通过“插入”菜单添加 WMTS 服务连接,输入服务 URL(例如:`http://.../WMTSCapabilities.xml`)[^4]。 - 加载服务到地图视图。 2. **调整布局视图** - 切换到“布局视图”,设置需要导出的地图范围。根据引用[3],直接导出地图可能受限,但布局视图支持自定义范围导出。 3. **导出地图为栅格数据** - 在“布局”选项卡中选择“导出”功能,设置输出格式(如 TIFF、PNG)和分辨率(DPI)。 - 通过“范围”选项指定导出区域(当前可见范围、数据驱动页面或自定义范围)。 #### 方法二:使用 ArcPy 脚本批量导出 若需导出大范围数据,可通过 Python 脚本自动化切片导出: ```python import arcpy aprx = arcpy.mp.ArcGISProject("CURRENT") lyt = aprx.listLayouts("布局名称")[0] lyt.exportToTIFF(r"导出路径/output.tif", resolution=300) ``` #### 注意事项 1. **权限与缓存限制** WMTS 服务可能因缓存策略限制导出范围,需确认服务是否开放下载权限[^2]。 2. **替代方案** 若 ArcGIS 导出受限,可尝试 QGIS 加载 WMTS 服务后直接导出(参考引用[4])。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值