Common Custom data source
Common_CustomDataSource_CSharp\TiledMapDataSource_CSharp\MapInformation.cs
// Copyright 2010 ESRI
// 
// All rights reserved under the copyright laws of the United States
// and applicable international laws, treaties, and conventions.
// 
// You may freely redistribute and use this sample code, with or
// without modification, provided you include the original copyright
// notice and use restrictions.
// 
// See the use restrictions.
// 



using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using ESRI.ArcGIS.ADF.Web.Display.Graphics;
using ESRI.ArcGIS.ADF.Web.Geometry;
using ESRI.ArcGIS.ADF.Web.SpatialReference;
using ESRI.ArcGIS.ADF.Web.DataSources;

namespace TiledMapDataSource_CSharp
{
    public class MapInformation : IMapInformation
    {
        public MapInformation(string dataSourceDefinition, string resourceDefinition)
        {
            this.dataSourceConfig = dataSourceDefinition;
            resourceConfig = resourceDefinition;
            parseConfig();
        }

        private string dataSourceConfig = string.Empty;
        private string resourceConfig = string.Empty;
        private SpatialReference defaultSpatialReference = null;
        private TileCacheInfo tileCacheInfo = null;
        private Envelope defaultExtent, fullExtent;

        public string DataFrame
        {
            get { return "(default)"; }
        }

        public SpatialReference DefaultSpatialReference
        {
            get { return defaultSpatialReference; }
        }

        public Envelope DefaultExtent
        {
            get
            {
                return defaultExtent;
            }
        }

        public Envelope FullExtent
        {
            get 
            {
                return fullExtent;
            }
        }

        public ESRI.ArcGIS.ADF.Web.DataSources.TileCacheInfo TileCacheInfo
        {
            get { return tileCacheInfo; }
            set { tileCacheInfo = new TileCacheInfo(value); }
        }

        private void parseConfig()
        {
            #region Get resource config nodes from document
            XmlDocument doc = new XmlDocument();
            doc.Load(dataSourceConfig);
            XmlNode root = doc.DocumentElement; //TileCacheInfos           
           
            XmlNode tileCacheNode = root.SelectSingleNode("TileCacheInfo");

            string cacheUrl = tileCacheNode.SelectSingleNode("URL").InnerText;

            if (tileCacheNode == null)
                throw new Exception("Could not find configuration for resource " + resourceConfig);
                       
            System.Collections.Generic.Dictionary<int, string> tileUrls = new Dictionary<int, string>();
            System.Collections.Generic.Dictionary<string, string> layers = new Dictionary<string, string>();
            #endregion

            #region Tile Cache Info
            XmlNode srNode = tileCacheNode.SelectSingleNode("SpatialReference");
            string srtext = srNode.SelectSingleNode("WKID").InnerText;
            int srid;
            if (Int32.TryParse(srtext, out srid))
            {
                defaultSpatialReference = new SpatialReference(srid);
            }
            else
            {
                defaultSpatialReference = new SpatialReference(srtext);
            }
                
            int dpi = Convert.ToInt32(tileCacheNode.SelectSingleNode("DPI").InnerText);
            int width = Convert.ToInt32(tileCacheNode.SelectSingleNode("TileCols").InnerText);
            int height = Convert.ToInt32(tileCacheNode.SelectSingleNode("TileRows").InnerText);
            XmlNode originNode = tileCacheNode.SelectSingleNode("TileOrigin");
            double xmin = Convert.ToDouble(originNode.SelectSingleNode("X").InnerText);
            double ymin = Convert.ToDouble(originNode.SelectSingleNode("Y").InnerText);
            Point origin = new Point(xmin, ymin);

            XmlNode extentNode = tileCacheNode.SelectSingleNode("FullExtent");
            xmin = Convert.ToDouble(extentNode.Attributes["XMin"].InnerText);
            ymin = Convert.ToDouble(extentNode.Attributes["YMin"].InnerText);
            double xmax = Convert.ToDouble(extentNode.Attributes["XMax"].InnerText);
            double ymax = Convert.ToDouble(extentNode.Attributes["YMax"].InnerText);
            fullExtent = new Envelope(xmin, ymin, xmax, ymax);
            fullExtent.SpatialReference = defaultSpatialReference;

            extentNode = tileCacheNode.SelectSingleNode("DefaultExtent");
            xmin = Convert.ToDouble(extentNode.Attributes["XMin"].InnerText);
            ymin = Convert.ToDouble(extentNode.Attributes["YMin"].InnerText);
            xmax = Convert.ToDouble(extentNode.Attributes["XMax"].InnerText);
            ymax = Convert.ToDouble(extentNode.Attributes["YMax"].InnerText);
            defaultExtent = new Envelope(xmin, ymin, xmax, ymax);
            defaultExtent.SpatialReference = defaultSpatialReference;
            #endregion

            #region Layers
            XmlNode layersNode = tileCacheNode.SelectSingleNode("Layers");
            if (layersNode != null)
            {
                XmlNodeList layerNodes = layersNode.SelectNodes("Layer");
                if (layerNodes != null)
                {
                    for (int l = 0; l < layerNodes.Count; ++l)
                    {
                        string layerId = layerNodes[l].Attributes["LayerID"].InnerText;
                        string layerName = layerNodes[l].Attributes["Name"].InnerText;
                        layers.Add(layerId, layerName);
                    }
                }
            }
            #endregion

            #region LOD Info
            System.Collections.Generic.List<LodInfo> lodInfos = new List<LodInfo>();
            System.Collections.Generic.Dictionary<int, int> levels = new Dictionary<int, int>();
            XmlNode lodInfoNode = tileCacheNode.SelectSingleNode("LODInfos");
            XmlNodeList lodInfoNodes = lodInfoNode.SelectNodes("LODInfo");
            for (int l = 0; l < lodInfoNodes.Count; ++l)
            {
                int levelid = Convert.ToInt32(lodInfoNodes[l].SelectSingleNode("LevelID").InnerText);
                levels.Add(l, levelid);
                double scale = Convert.ToDouble(lodInfoNodes[l].SelectSingleNode("Scale").InnerText);
                double resolution = Convert.ToDouble(lodInfoNodes[l].SelectSingleNode("Resolution").InnerText);

                double tileExtentWidth = width * resolution;
                double tileExtentHeight = height * resolution;

                double xOffset = fullExtent.XMin - origin.X;
                if (xOffset < 0)
                    xOffset = 0; //allows for full extent to extend to the left of the tile origin

                int minColumn = (int)Math.Floor((xOffset) / tileExtentWidth); //2 //-2

                int maxColumn = (int)Math.Ceiling((fullExtent.XMax - origin.X) / tileExtentWidth) - 1;//4 //4
                int columns = maxColumn - minColumn + 1; //3 //7


                double yOffset = origin.Y - fullExtent.YMax;
                if (yOffset < 0)
                    yOffset = 0; //allows for full extent to extend to the left of the tile origin

                int minRow = (int)Math.Floor((yOffset) / tileExtentHeight);
                int maxRow = (int)Math.Ceiling((origin.Y - fullExtent.YMin) / tileExtentHeight) - 1;
                int rows = maxRow - minRow + 1;

                LodInfo lodInfo = new LodInfo(levelid, resolution, scale, columns, rows, tileExtentWidth, tileExtentHeight);
                lodInfos.Add(lodInfo);
            }
            #endregion

            tileCacheInfo = new TileCacheInfo(width, height,
                dpi, origin, lodInfos.ToArray());
            tileCacheInfo.Layers = layers;
            tileCacheInfo.Levels = levels;
            tileCacheInfo.Url = cacheUrl;

            XmlNode tileImageNode = tileCacheNode.SelectSingleNode("TileImageInfo");
            string imgFormat = tileImageNode.SelectSingleNode("CacheTileFormat").InnerText;
            tileCacheInfo.CacheTileFormat = imgFormat;
        }
    }
}