自定义图层加载Arcgis Server松散切片

           ArcGIS Server提供了丰富的GIS功能,但是对于一个相对简单的项目来说,可能只是使用到了Arcgis Server提供的

地图服务MapServer,这种情况下使用Arcgis Server感觉有些资源浪费,而且Arcgis Server的价格不便宜。这种情况下,

我们可以考虑通过自定义图层的方式来加载Arcgis Server的切片。下面就介绍基于Silverlight Api如何去加载松散切片:

           在ArcgisCache缓存目录下可以找到地图瓦片。如下图,有两个文件conf.xml和conf.cdi,这两个文件里存储了地图

瓦片的基本参数信息。conf.cdi中存储了地图的初始外包范围,conf.xml中存储了坐标系、瓦片和瓦片每个级别的基本参

数。不难发现ArcGISTiledMapServiceLayer图层也就是在内部通过对这两个文件的解析,然后实现加载瓦片的,所以自

定义图层的关键就这解析这两个文件。

 

         *第一步:继承TiledMapServiceLayer,重写GetTileUrl方法。打开切片目录,可以发现瓦片的等级是以L开头的,比

较特殊的是行和列,分别是以R和C开头的8位16进制值表示的(不够8位补零),所以在拼路径的时候需要对十进制进行转

换。

	public override string GetTileUrl(int level, int row, int col)
        {
            return string.Format("{0}{1}/L0{2}/R{3}/C{4}.png", this.TiledUrl, _TILEDS, level, AppendChar(row), AppendChar(col));
        } 
	//16进制转换
   	private string AppendChar(int num)
	{
            string str16 = Convert.ToString(num, 16);
            StringBuilder str = new StringBuilder();
            for (int i = str16.Length; i < 8; i++)
                str.Append("0");
            str.Append(str16);
            return str.ToString();
        }

             

            *第二步:读取conf.cdi和conf.xml文件内的参数。读取的内容主要是三部分,地图外包(Extent)、坐标系(SpatialReference)、

瓦片(TileInfo)和瓦片每级(Lod)的信息。在使用WebClient读取conf.cdi文件的时候,由于不识别这个文件的后缀cdi,可以将其

改成常见的文本格式,例如:txt、ini等。

 //初始化图层外包
        private void InitFullExtent()
        {
            WebClient client = new WebClient();
            client.OpenReadCompleted += (s, e) =>
            {
                try
                {
                    XDocument doc = XDocument.Load(e.Result);
                    XElement env = doc.Element("EnvelopeN");
                    this.FullExtent = new Envelope
                    (
                        Convert.ToDouble(env.Element("XMin").Value),
                        Convert.ToDouble(env.Element("YMin").Value),
                        Convert.ToDouble(env.Element("XMax").Value),
                        Convert.ToDouble(env.Element("YMax").Value)
                    );
                    _CdiIsLoaded = true;
                }
                catch { }
                finally { NotifyLoad(); }
            };
            client.OpenReadAsync(new Uri(string.Format("{0}{1}", this.TiledUrl, _CON_CDI), UriKind.RelativeOrAbsolute));
        }
        //初始化瓦片信息
        private void InitTiledInfo()
        {
            WebClient client = new WebClient();
            client.OpenReadCompleted += (s, e) =>
            {
                try
                {
                    XDocument doc = XDocument.Load(e.Result);
                    XElement tileInfo = doc.Element("CacheInfo").Element("TileCacheInfo");
                    IEnumerable<XElement> lodsInfo = tileInfo.Element("LODInfos").Elements("LODInfo");
                    //初始化坐标系
                    this.SpatialReference = new SpatialReference(Convert.ToInt32(tileInfo.Element("SpatialReference").Element("WKID").Value));
                    //初始化瓦片信息
                    this.TileInfo = new TileInfo()
                    {
                        Height = Convert.ToInt32(tileInfo.Element("TileCols").Value),
                        Width = Convert.ToInt32(tileInfo.Element("TileRows").Value),
                        Origin = new MapPoint() 
                        { 
                            X = Convert.ToDouble(tileInfo.Element("TileOrigin").Element("X").Value),
                            Y = Convert.ToDouble(tileInfo.Element("TileOrigin").Element("Y").Value),
                            SpatialReference = new ESRI.ArcGIS.Client.Geometry.SpatialReference(this.SpatialReference.WKID) 
                        },
                        Lods = new Lod[lodsInfo.Count()]
                    };
                    //初始化瓦片级别信息
                    foreach (XElement lod in lodsInfo)
                    {
                        int index = Convert.ToInt32(lod.Element("LevelID").Value);
                        this.TileInfo.Lods[index] = new Lod()
                        {
                            Resolution = Convert.ToDouble(lod.Element("Resolution").Value),
                        };
                    }
                    _XmlIsLoaded = true;
                }
                catch { }
                finally { NotifyLoad(); }
            };
            client.OpenReadAsync(new Uri(string.Format("{0}{1}", this.TiledUrl, _CON_XML), UriKind.RelativeOrAbsolute));
        }

        注意:必须在conf.cdi和conf.xml文件内的配置信息读取完毕之后,才能Add

到Map中。

       此处,我是将瓦片拷贝到Silverlight的宿主网站的目录下,在Silverlight端使用WebClient读取。对于紧凑的切片,

在GetTileUrl中每一次请求时需要对bundlx和bundle格式的文件进行解析,那么切片就必须放在xap包内部,考虑到xap不

易过大,所以就没有使用这种方式实现。

转载自:https://blog.csdn.net/zxian610/article/details/12648309

You may also like...