ArcGIS.Server.9.2.DotNet使用Virtual Earth地图图片数据(自带例子 九、二)

目的:
1.arcgis server9.2 ADF中把Virtual Earth地图图片数据作为数据源,这样可以直接使用MicroSoft的卫星图片

准备工作:
1.参考DeveloperKit\SamplesNET\Server\Web_Applications目录下的Common_CustomDataSourceCSharp.zip。
完成后的效果图:


开始:
1.把Virtual Earth地图图片数据作为地图数据源,和(九、一)例子一样也是需要通过自定义数据源实现了,具体的关于地图数据、地图控件、Data Source、Resource、Functionatily之间的关系地图以及地图从数据到显示的整个过程说明可以参考(九、一)例子,这里不做详细的说明。
2.新建名为CustomDataSource的ASP.NET Web应用程序,然后添加一个Default_TileMapData.aspx页面用来具体功能的展示。
3.在CustomDataSource的解决方案中在添加一个名为TiledMapDataSource的类库工程,用来实现自定义DataSource类型和MapResource的功能。同时在CustomDataSource的ASP.NET Web应用程序中添加对这个TiledMapDataSource的类库工程的引用。
4.同(九、一)例子一样自定义数据源的要在ADF中使用需要在ArcGisServer安装目录的DotNet文件内添加配置文件,关于配置文件的说明可以看(九、一)例子,添加名为ESRI.ArcGIS.ADF.Web.DataSources.TiledMap.config的配置文件,内容如下:

Code

5.从上面配置文件看,我们需要实现TiledMapDataSource.GISDataSource、TiledMapDataSource.MapResource这2个类,新建GISDataSource.cs和MapResource.cs两个文件。
6.TiledMapDataSource.GISDataSource类和(九、一)例子一样了这里不详细说明了,同时也可以参考Common_CustomDataSourceCSharp.zip的源代码,这样需要对在TiledMapDataSource.GISDataSource类中使用到的MapInformation.cs类需要进行说明,与上例不同这次是采用Virtual Earth瓦块图片数据,所以MapInformation.cs类的实现较上例有些不同,主要区别是当MapInformation类实例化时,读取配置了Virtual Earth地图数据的一些配置参数对TileCacheInfo属性进行数据设置,主要是在方法parseConfig()中。
Virtual Earth地图数据配置参数文件VirtualEarth_original.xml,具体节点说明可以对照parseConfig()方法,内容具体如下:

Code

MapInformation类具体的代码和说明如下:

  1namespace TiledMapDataSource
  2{
  3    public class MapInformation : IMapInformation
  4    {
  5        public MapInformation(string dataSourceDefinition, string resourceDefinition)
  6        {
  7            this.dataSourceConfig = dataSourceDefinition;
  8            resourceConfig = resourceDefinition;
  9            //读取对Virtual Earth地图数据的配置定义信心,包括名称、坐标系、图层、各个比例尺等信息
 10            parseConfig();
 11        }

 12
 13        private string dataSourceConfig = string.Empty;
 14        private string resourceConfig = string.Empty;
 15        private SpatialReference defaultSpatialReference = null;
 16        private TileCacheInfo tileCacheInfo = null;
 17        private Envelope defaultExtent, fullExtent;
 18
 19        //IMapInformation成员
 20        public string DataFrame
 21        {
 22            get return "(default)"; }
 23        }

 24        //IMapInformation成员
 25        public SpatialReference DefaultSpatialReference
 26        {
 27            get return defaultSpatialReference; }
 28        }

 29        //IMapInformation成员
 30        public Envelope DefaultExtent
 31        {
 32            get
 33            {
 34                return defaultExtent;
 35            }

 36        }

 37        //IMapInformation成员
 38        public Envelope FullExtent
 39        {
 40            get
 41            {
 42                return fullExtent;
 43            }

 44        }

 45        //IMapInformation成员
 46        public ESRI.ArcGIS.ADF.Web.DataSources.TileCacheInfo TileCacheInfo
 47        {
 48            get return tileCacheInfo; }
 49            set { tileCacheInfo = new TileCacheInfo(value); }
 50        }

 51
 52        private void parseConfig()
 53        {
 54            //读取xml文档
 55            XmlDocument doc = new XmlDocument();
 56            doc.Load(dataSourceConfig);
 57            XmlNode root = doc.DocumentElement;
 58            //读取TileCacheInfo节点
 59            XmlNodeList tileCacheInfoNodes = root.SelectNodes("TileCacheInfo");
 60            if (tileCacheInfoNodes == null || tileCacheInfoNodes.Count < 1)
 61            {
 62                throw new Exception("Could not find configuration for resource " + resourceConfig);
 63            }
   
 64
 65            XmlNode tileCacheNode = null;
 66            System.Collections.Generic.Dictionary<intstring> tileUrls = new Dictionary<intstring>();
 67            System.Collections.Generic.Dictionary<stringstring> layers = new Dictionary<stringstring>();
 68
 69            //如果Name节点为resourceConfig
 70            for (int t = 0; t < tileCacheInfoNodes.Count; ++t)
 71            {   
 72                if (tileCacheInfoNodes[t].Attributes["Name"].InnerText == resourceConfig)
 73                {
 74                    tileCacheNode = tileCacheInfoNodes[t];
 75                    break;
 76                }

 77            }

 78            //获取第一个节点
 79            if (tileCacheNode == null)
 80            {
 81                tileCacheNode = tileCacheInfoNodes[0];
 82            }

 83            //获取SpatialReference节点内容,坐标系统定义字符串
 84            string srtext = tileCacheNode.Attributes["SpatialReference"].InnerText;
 85            int srid;
 86            //设置defaultSpatialReference
 87            if (Int32.TryParse(srtext, out srid))
 88            {
 89                defaultSpatialReference = new SpatialReference(srid);
 90            }

 91            else
 92            {
 93                defaultSpatialReference = new SpatialReference(srtext);
 94            }

 95
 96            //获取图片解像度
 97            int dpi = Convert.ToInt32(tileCacheNode.Attributes["DPI"].InnerText);
 98            //瓦块图的高
 99            int height = Convert.ToInt32(tileCacheNode.Attributes["Height"].InnerText);
100            //瓦块图的宽
101            int width = Convert.ToInt32(tileCacheNode.Attributes["Width"].InnerText);
102            //原点坐标
103            string[] originCoords = tileCacheNode.Attributes["TileOrigin"].InnerText.Split(new char[] ',' });
104            //最小x坐标
105            double xmin = Convert.ToDouble(originCoords[0]);
106            //最小y坐标
107            double ymin = Convert.ToDouble(originCoords[1]);
108            //原点
109            Point origin = new Point(xmin, ymin);
110
111            //全图范围
112            XmlNode extentNode = tileCacheNode.SelectSingleNode("FullExtent");
113            xmin = Convert.ToDouble(extentNode.Attributes["XMin"].InnerText);
114            ymin = Convert.ToDouble(extentNode.Attributes["YMin"].InnerText);
115            double xmax = Convert.ToDouble(extentNode.Attributes["XMax"].InnerText);
116            double ymax = Convert.ToDouble(extentNode.Attributes["YMax"].InnerText);
117            fullExtent = new Envelope(xmin, ymin, xmax, ymax);
118            fullExtent.SpatialReference = defaultSpatialReference;
119
120            //默认显示范围
121            extentNode = tileCacheNode.SelectSingleNode("DefaultExtent");
122            xmin = Convert.ToDouble(extentNode.Attributes["XMin"].InnerText);
123            ymin = Convert.ToDouble(extentNode.Attributes["YMin"].InnerText);
124            xmax = Convert.ToDouble(extentNode.Attributes["XMax"].InnerText);
125            ymax = Convert.ToDouble(extentNode.Attributes["YMax"].InnerText);
126            defaultExtent = new Envelope(xmin, ymin, xmax, ymax);
127            defaultExtent.SpatialReference = defaultSpatialReference;
128
129            //获取图层id和名称
130            XmlNode layersNode = tileCacheNode.SelectSingleNode("Layers");
131            if (layersNode != null)
132            {
133                XmlNodeList layerNodes = layersNode.SelectNodes("Layer");
134                if (layerNodes != null)
135                {
136                    for (int l = 0; l < layerNodes.Count; ++l)
137                    {
138                        string layerId = layerNodes[l].Attributes["LayerID"].InnerText;
139                        string layerName = layerNodes[l].Attributes["Name"].InnerText;
140                        layers.Add(layerId, layerName);
141                    }

142                }

143            }

144 
145            //获取各个比例尺的信息
146            System.Collections.Generic.List<LodInfo> lodInfos = new List<LodInfo>();
147            System.Collections.Generic.Dictionary<intint> levels = new Dictionary<intint>();
148            XmlNode lodInfoNode = tileCacheNode.SelectSingleNode("LodInfos");
149            XmlNodeList lodInfoNodes = lodInfoNode.SelectNodes("LodInfo");
150            for (int l = 0; l < lodInfoNodes.Count; ++l)
151            {
152                int levelid = Convert.ToInt32(lodInfoNodes[l].Attributes["LevelID"].InnerText);
153                levels.Add(l, levelid);
154                //瓦片图行数量
155                int rows = Convert.ToInt32(lodInfoNodes[l].Attributes["Rows"].InnerText);
156                //瓦片图列数量
157                int columns = Convert.ToInt32(lodInfoNodes[l].Attributes["Columns"].InnerText);
158                //瓦片图路径
159                string tileUrl = lodInfoNodes[l].Attributes["TileUrl"].InnerText;
160                //瓦片图地理宽度
161                double tilewidth = Convert.ToDouble(lodInfoNodes[l].Attributes["TileExtentWidth"].InnerText);
162                //瓦片图地理高度
163                double tileheight = Convert.ToDouble(lodInfoNodes[l].Attributes["TileExtentHeight"].InnerText);
164                //比例尺
165                double scale = Convert.ToDouble(lodInfoNodes[l].Attributes["Scale"].InnerText);
166                //分辨率
167                double resolution = Convert.ToDouble(lodInfoNodes[l].Attributes["Resolution"].InnerText);
168                LodInfo lodInfo = new LodInfo(levelid, resolution, scale, columns, rows, tilewidth, tileheight);
169                lodInfos.Add(lodInfo);
170                tileUrls.Add(levelid, tileUrl);
171            }

172
173            //设置TileCacheInfo
174            tileCacheInfo = new TileCacheInfo(width, height,dpi, origin, lodInfos.ToArray());
175            tileCacheInfo.TileUrls = tileUrls;
176            tileCacheInfo.Layers = layers;
177            tileCacheInfo.Levels = levels;
178
179            //获取Virtual Earth瓦块图片路径处理类的Assembly和名称
180            XmlNode urlGenNode = tileCacheNode.SelectSingleNode("TileUrlGenerator");
181            if (urlGenNode != null)
182            {
183                tileCacheInfo.TileUrlGeneratorAssembly =urlGenNode.Attributes["Assembly"].InnerText;
184                tileCacheInfo.TileUrlGeneratorClass =urlGenNode.Attributes["Class"].InnerText;
185            }

186
187        }

188    }

189}

190
TileCacheInfo.cs类代码:
 1namespace TiledMapDataSource
 2{
 3    public class TileCacheInfo : ESRI.ArcGIS.ADF.Web.DataSources.TileCacheInfo
 4    {
 5        public TileCacheInfo(int width, int height, int dpi, Point origin, LodInfo[] lodInfos): base(width, height, dpi, origin, lodInfos)
 6        { }
 7        public TileCacheInfo(ESRI.ArcGIS.ADF.Web.DataSources.TileCacheInfo tci): base(tci.Width, tci.Height, tci.Dpi, tci.Origin, tci.LodInfos)
 8        { }
 9        internal System.Collections.Generic.Dictionary<intint> Levels = new Dictionary<intint>();
10        internal System.Collections.Generic.Dictionary<intstring> TileUrls = new Dictionary<intstring>();
11        internal System.Collections.Generic.Dictionary<stringstring> Layers = new Dictionary<stringstring>();
12        internal string TileUrlGeneratorAssembly;
13        internal string TileUrlGeneratorClass;
14    }

15}

16

7.MapResource类和(九、一)例子差不多了这里不详细说明了,具体的可以看Common_CustomDataSourceCSharp.zip的源代码,与上例不同的地方是这个Resource实现了TileFunctionality,因为本来的Virtual Earth地图数据源是切成小块的瓦块图,所以需要实现TileFunctionality,关于TileFunctionality的具体代码和说明如下:

  1namespace TiledMapDataSource
  2{
  3    class TileFunctionality : ITileFunctionality
  4    {
  5        ITileFunctionality 成员
 65
 66        IGISFunctionality 成员
133
134        private MapFunctionality GetMapFunctionality(string name)
135        {
136            MapFunctionality mapFunctionality = resource.Functionalities.Find(name) as MapFunctionality;
137            return mapFunctionality;
138        }

139
140        private object getInstanceOfType(string assemblyName, string type)
141        {
142            object o = null;
143            try
144            {
145                System.Reflection.Assembly assembly = System.Reflection.Assembly.Load(assemblyName);
146                o = assembly.CreateInstance(type);
147            }

148            catch (Exception e)
149            {
150                string mess = e.Message;
151            }

152            return o;
153        }

154    }

155}

156

8.在TileFunctionality类中有用到ITileUrlGenerator接口,新建ITileUrlGenerator.cs文件,代码如下:

1namespace TiledMapDataSource
2{
3    public interface ITileUrlGenerator
4    {
5        //获取瓦块图路径的的方法
6        string GetTileUrl(long column, long row, int level, string defaultUrl, Dictionary<stringbool> layerVisibility);
7    }

8}

9.在TileFunctionality类中有用到VirtualEarthTileUrlGenerator类,它实现了ITileUrlGenerator接口。VirtualEarthTileUrlGenerator方法是获取Virtual Earth的图片,所以有必要对VirtualEarth的图片算法进行了解,看如下的参考资料:
卫星图和微软普通地图瓦片算法是一样的,区别在于卫星图要是a或者h开头,而微普通地图则是r开头,服务器地址不同下面举例:
http://a1.ortho.tiles.virtualearth.net/tiles/a1322111.jpeg?g=1 这是不带label的微软卫星图
http://h1.ortho.tiles.virtualearth.net/tiles/h1322111.jpeg?g=1 这是带label(如显示省份、地市)的微软卫星图
http://r1.tiles.ditu.live.com/tiles/r1322111.png?g=1 这微软普通地图
看到http://后面,红色的a、h、r分别代表不带label卫星图、带label卫星图、微软普通地图。
10.有了上面的资料后就能知道如何取地图图片了,新建VirtualEarthTileUrlGenerator.cs文件,代码如下:

 1namespace TiledMapDataSource
 2{
 3    public class VirtualEarthTileUrlGenerator : ITileUrlGenerator
 4    {
 5        ITileUrlGenerator Members
13
14        //获取瓦块图路径,参数:瓦块列值,瓦块的行值,比例等级,可视图层
15        private string GetUrl(int column, int row, int level, Dictionary<stringbool> layerVisibility)
16        {
17            string mapType = null;
18            string mapExtension = null;
19            //如果同时包括Road图层和Aerial图层
20            if (layerVisibility["r"&& layerVisibility["a"])
21            {
22                mapType = "h";
23                mapExtension = ".jpeg";
24            }

25            //只包括Road图层
26            else if (layerVisibility["r"])
27            {
28                mapType = "r";
29                mapExtension = ".png";
30            }

31            //只包括Aerial图层
32            else if (layerVisibility["a"])
33            {
34                mapType = "a";
35                mapExtension = ".jpeg";
36            }

37            else
38            {
39                return null;
40            }

41
42            string quadKey = TileToQuadKey(column, row, level);
43
44            string url = String.Concat(new object[] "http://", mapType, quadKey[quadKey.Length - 1], ".ortho.tiles.virtualearth.net/tiles/", mapType, quadKey, mapExtension, "?g="1 });
45            return url;
46        }

47
48        //Virtual Earth图片名称的算法
49        private static string TileToQuadKey(int tx, int ty, int zl)
50        {
51            string quad = "";
52            for (int i = zl; i > 0; i--)
53            {
54                int mask = 1 << (i - 1);
55                int cell = 0;
56                if ((tx & mask) != 0)
57                {
58                    cell++;
59                }

60                if ((ty & mask) != 0)
61                {
62                    cell += 2;
63                }

64                quad += cell;
65            }

66            return quad;
67        }

68    }

69}

11.剩下的MapFunctionality.cs和MapTocFunctionality.cs和上例类似比较简单了不做详细解释,具体参考Common_CustomDataSourceCSharp.zip的源代码。

12.这样自定义数据源完成了,接下在就是测试这个数据源,在CustomDataSource的ASP.NET Web应用程序的Default_TileMapData.aspx页面中添加Map1、MapResourceManager1、Toc13个控件,然后做相应的设置,具体设置可以参考前面的文章。
13.接下来在MapResourceManager1中在Server Resource上面在新增加名为Virtual Earth,在弹出的Map Resource Definition Editor中Type:选择TiledMap就是上面添加到DotNet文件内的ESRI.ArcGIS.ADF.Web.DataSources.TiledMap.config中定义的名字,在Data Source:输入上面的那个xml的地址,如:D:\VirtualEarth_original.xml,然后确定就完成了设置。这里的Data Source为了方便是输入的方式了,最好的做法可以参考Common_CustomDataSourceCSharp.zip样例为它做一个xml文件选择界面,具体的参考CustomDataSource_CSharp\REXMLDataSource_CSharp\Design\DataSourceDefinitionEditorFormREXML.cs,是一个Winform的选择节目,只有在config文件配置一下,就可以在
Map Resource Definition Editor中调用自己定制的编辑器。
14.运行查看效果,这样成功的把Virtual Earth的卫星图片显示在我们的页面中了。

 

posted @ 2008-09-01 22:43  水的右边  阅读(4713)  评论(16编辑  收藏  举报