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

来源:互联网 发布:python模块导入 编辑:程序博客网 时间:2024/06/09 20:35

           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不

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

原创粉丝点击