1.arcgis server9.2 ADF中把Google Maps卫星图片作为数据源。
准备工作:
1.本例子是在上一篇的基础上实现的,请参考ArcGIS.Server.9.2.DotNet使用Virtual Earth地图图片数据(自带例子 九、二)
完成后的效果图:
开始:
1. 在上一篇中实现了用微软的Virtual Earth地图图片数据作为地图数据源进行ADF的开发,今天再用Google Maps卫星图片作为数据源。实现的原理和过程和上一篇一样了不详细说明了,具体参考ArcGIS.Server.9.2.DotNet使用Virtual Earth地图图片数据(自带例子 九、二) 。
2.要取Google Maps卫星图片,首先需要对Google Maps卫星图片的路径算法进行研究了,关于Google Maps卫星图片的资料如下:
Google的每一个卫片是256*256的jpg格式的图片,总共有0-20比例等级,采用WGS84坐标系。
全幅地图组成情况,0级:1张256*256图片;1级:4张256*256图片;2级:16张256*256图片;3级:64张256*256图片.....
每一片卫片的名称是由一种类似“Q树”的算法计算的,如http://kh.google.com/kh?v=3&t=trstt,v=3代表,卫星图的投影算法采用Mercator projection算法,v=2代表另外一种算法(已不再支持),变量t=trstt,这个就是这张图片的名称编码了,将一幅图片的左上、右上、左下、右下用q,r,t,s分别表示。然后依次递归下去,最上层的是t。
3.通过上面的描述,我们可以先编写Google Maps地图数据配置参数文件GoogleMap.xml,这个文件与上例的VirtualEarth_original.xml有些区别了,主要是VirtualEarth和Google Maps的参数略有不同了,关于GoogleMap.xml某些参数是根据上面的描述计算得出的,具体内容如下:
1<TileCacheInfos>
2 <TileCacheInfo Name='Google Map'
3 SpatialReference='PROJCS["Sphere_VE_WGS84",GEOGCS["GCS_Sphere_VE_WGS84",
4DATUM["D_Sphere_VE_WGS84",
5SPHEROID["Sphere_VE_WGS84",6378137.0,0.0]],
6PRIMEM["Greenwich",0.0],
7UNIT["Degree",0.0174532925199433]],
8PROJECTION["Mercator"],
9PARAMETER["False_Easting",0.0],
10PARAMETER["False_Northing",0.0],
11PARAMETER["Central_Meridian",0.0],
12PARAMETER["Standard_Parallel_1",0.0],
13UNIT["Meter",1.0]]'
14 DPI='96'
15 Width='256' Height='256' TileOrigin='-20037508.3427892,20037508.3427892'>
16 <FullExtent XMin='-20037508.3427892' YMin='-20037508.3427892' XMax='20037508.3427892' YMax='20037508.3427892'/>
17 <DefaultExtent XMin='-20037508.3427892' YMin='-20037508.3427892' XMax='20037508.3427892' YMax='20037508.3427892'/>
18 <Layers>
19 </Layers>
20 <TileUrlGenerator type='class' Assembly='TiledMapDataSource' Class='TiledMapDataSource.GoogleMapTileUrlGenerator' />
21 <LodInfos>
22 <LodInfo LevelID='1' Resolution='78271.5170' Scale='295829355.45' Rows='2' Columns='2' TileExtentWidth='20037508.3427892' TileExtentHeight='20037508.3427893' TileUrl='' />
23 <LodInfo LevelID='2' Resolution='39135.7585' Scale='147914677.73' Rows='4' Columns='4' TileExtentWidth='10018754.1713946' TileExtentHeight='10018754.1713947' TileUrl='' />
24 <LodInfo LevelID='3' Resolution='19567.8792' Scale='73957338.86' Rows='8' Columns='8' TileExtentWidth='5009377.08569731' TileExtentHeight='5009377.08569736' TileUrl='' />
25 <LodInfo LevelID='4' Resolution='9783.9396' Scale='36978669.43' Rows='16' Columns='16' TileExtentWidth='2504688.54284865' TileExtentHeight='2504688.54284866' TileUrl='' />
26 <LodInfo LevelID='5' Resolution='4891.9698' Scale='18489334.72' Rows='32' Columns='32' TileExtentWidth='1252344.27142432' TileExtentHeight='1252344.27142439' TileUrl='' />
27 <LodInfo LevelID='6' Resolution='2445.9849' Scale='9244667.36' Rows='64' Columns='64' TileExtentWidth='626172.135712165' TileExtentHeight='626172.135712203' TileUrl='' />
28 <LodInfo LevelID='7' Resolution='1222.9925' Scale='4622333.68' Rows='128' Columns='128' TileExtentWidth='313086.067856081' TileExtentHeight='313086.067856163' TileUrl='' />
29 <LodInfo LevelID='8' Resolution='611.4962' Scale='2311166.84' Rows='256' Columns='256' TileExtentWidth='156543.03392804' TileExtentHeight='156543.033928085' TileUrl='' />
30 <LodInfo LevelID='9' Resolution='305.7481' Scale='1155583.42' Rows='512' Columns='512' TileExtentWidth='78271.5169640221' TileExtentHeight='78271.5169640593' TileUrl='' />
31 <LodInfo LevelID='10' Resolution='152.8741' Scale='577791.71' Rows='1024' Columns='1024' TileExtentWidth='39135.7584820092' TileExtentHeight='39135.7584820762' TileUrl='' />
32 <LodInfo LevelID='11' Resolution='76.4370' Scale='288895.85' Rows='2048' Columns='2048' TileExtentWidth='19567.8792410046' TileExtentHeight='19567.8792410083' TileUrl='' />
33 <LodInfo LevelID='12' Resolution='38.2185' Scale='144447.93' Rows='4096' Columns='4096' TileExtentWidth='9783.93962049857' TileExtentHeight='9783.93962051347' TileUrl='' />
34 <LodInfo LevelID='13' Resolution='19.1093' Scale='72223.96' Rows='8192' Columns='8192' TileExtentWidth='4891.96981025115' TileExtentHeight='4891.96981034055' TileUrl='' />
35 <LodInfo LevelID='14' Resolution='9.5546' Scale='36111.98' Rows='16384' Columns='16384' TileExtentWidth='2445.98490512371' TileExtentHeight='2445.98490521312' TileUrl='' />
36 <LodInfo LevelID='15' Resolution='4.7773' Scale='18055.99' Rows='32768' Columns='32768' TileExtentWidth='1222.99245255813' TileExtentHeight='1222.99245259538' TileUrl='' />
37 <LodInfo LevelID='16' Resolution='2.3887' Scale='9027.0' Rows='65536' Columns='65536' TileExtentWidth='611.496226280928' TileExtentHeight='611.496226321906' TileUrl='' />
38 <LodInfo LevelID='17' Resolution='1.1943' Scale='4513.0' Rows='131072' Columns='131072' TileExtentWidth='305.748113140464' TileExtentHeight='305.748113185167' TileUrl='' />
39 <LodInfo LevelID='18' Resolution='0.5971' Scale='2254.4' Rows='262144' Columns='262144' TileExtentWidth='152.702993744053' TileExtentHeight='152.702993744053' TileUrl= '' />
40 <LodInfo LevelID='19' Resolution='0.29858' Scale='1127.2' Rows='524288' Columns='524288' TileExtentWidth='76.3514968720267' TileExtentHeight='76.3514968720267' TileUrl= '' />
41
42 </LodInfos>
43 </TileCacheInfo>
44</TileCacheInfos>
4.接下来还需要实现一个GoogleMapTileUrlGenerator类作为GoogleMap的图片地址生成类,同上例的VirtualEarthTileUrlGenerator类一样需要实现ITileUrlGenerator接口,具体代码如下:
2 <TileCacheInfo Name='Google Map'
3 SpatialReference='PROJCS["Sphere_VE_WGS84",GEOGCS["GCS_Sphere_VE_WGS84",
4DATUM["D_Sphere_VE_WGS84",
5SPHEROID["Sphere_VE_WGS84",6378137.0,0.0]],
6PRIMEM["Greenwich",0.0],
7UNIT["Degree",0.0174532925199433]],
8PROJECTION["Mercator"],
9PARAMETER["False_Easting",0.0],
10PARAMETER["False_Northing",0.0],
11PARAMETER["Central_Meridian",0.0],
12PARAMETER["Standard_Parallel_1",0.0],
13UNIT["Meter",1.0]]'
14 DPI='96'
15 Width='256' Height='256' TileOrigin='-20037508.3427892,20037508.3427892'>
16 <FullExtent XMin='-20037508.3427892' YMin='-20037508.3427892' XMax='20037508.3427892' YMax='20037508.3427892'/>
17 <DefaultExtent XMin='-20037508.3427892' YMin='-20037508.3427892' XMax='20037508.3427892' YMax='20037508.3427892'/>
18 <Layers>
19 </Layers>
20 <TileUrlGenerator type='class' Assembly='TiledMapDataSource' Class='TiledMapDataSource.GoogleMapTileUrlGenerator' />
21 <LodInfos>
22 <LodInfo LevelID='1' Resolution='78271.5170' Scale='295829355.45' Rows='2' Columns='2' TileExtentWidth='20037508.3427892' TileExtentHeight='20037508.3427893' TileUrl='' />
23 <LodInfo LevelID='2' Resolution='39135.7585' Scale='147914677.73' Rows='4' Columns='4' TileExtentWidth='10018754.1713946' TileExtentHeight='10018754.1713947' TileUrl='' />
24 <LodInfo LevelID='3' Resolution='19567.8792' Scale='73957338.86' Rows='8' Columns='8' TileExtentWidth='5009377.08569731' TileExtentHeight='5009377.08569736' TileUrl='' />
25 <LodInfo LevelID='4' Resolution='9783.9396' Scale='36978669.43' Rows='16' Columns='16' TileExtentWidth='2504688.54284865' TileExtentHeight='2504688.54284866' TileUrl='' />
26 <LodInfo LevelID='5' Resolution='4891.9698' Scale='18489334.72' Rows='32' Columns='32' TileExtentWidth='1252344.27142432' TileExtentHeight='1252344.27142439' TileUrl='' />
27 <LodInfo LevelID='6' Resolution='2445.9849' Scale='9244667.36' Rows='64' Columns='64' TileExtentWidth='626172.135712165' TileExtentHeight='626172.135712203' TileUrl='' />
28 <LodInfo LevelID='7' Resolution='1222.9925' Scale='4622333.68' Rows='128' Columns='128' TileExtentWidth='313086.067856081' TileExtentHeight='313086.067856163' TileUrl='' />
29 <LodInfo LevelID='8' Resolution='611.4962' Scale='2311166.84' Rows='256' Columns='256' TileExtentWidth='156543.03392804' TileExtentHeight='156543.033928085' TileUrl='' />
30 <LodInfo LevelID='9' Resolution='305.7481' Scale='1155583.42' Rows='512' Columns='512' TileExtentWidth='78271.5169640221' TileExtentHeight='78271.5169640593' TileUrl='' />
31 <LodInfo LevelID='10' Resolution='152.8741' Scale='577791.71' Rows='1024' Columns='1024' TileExtentWidth='39135.7584820092' TileExtentHeight='39135.7584820762' TileUrl='' />
32 <LodInfo LevelID='11' Resolution='76.4370' Scale='288895.85' Rows='2048' Columns='2048' TileExtentWidth='19567.8792410046' TileExtentHeight='19567.8792410083' TileUrl='' />
33 <LodInfo LevelID='12' Resolution='38.2185' Scale='144447.93' Rows='4096' Columns='4096' TileExtentWidth='9783.93962049857' TileExtentHeight='9783.93962051347' TileUrl='' />
34 <LodInfo LevelID='13' Resolution='19.1093' Scale='72223.96' Rows='8192' Columns='8192' TileExtentWidth='4891.96981025115' TileExtentHeight='4891.96981034055' TileUrl='' />
35 <LodInfo LevelID='14' Resolution='9.5546' Scale='36111.98' Rows='16384' Columns='16384' TileExtentWidth='2445.98490512371' TileExtentHeight='2445.98490521312' TileUrl='' />
36 <LodInfo LevelID='15' Resolution='4.7773' Scale='18055.99' Rows='32768' Columns='32768' TileExtentWidth='1222.99245255813' TileExtentHeight='1222.99245259538' TileUrl='' />
37 <LodInfo LevelID='16' Resolution='2.3887' Scale='9027.0' Rows='65536' Columns='65536' TileExtentWidth='611.496226280928' TileExtentHeight='611.496226321906' TileUrl='' />
38 <LodInfo LevelID='17' Resolution='1.1943' Scale='4513.0' Rows='131072' Columns='131072' TileExtentWidth='305.748113140464' TileExtentHeight='305.748113185167' TileUrl='' />
39 <LodInfo LevelID='18' Resolution='0.5971' Scale='2254.4' Rows='262144' Columns='262144' TileExtentWidth='152.702993744053' TileExtentHeight='152.702993744053' TileUrl= '' />
40 <LodInfo LevelID='19' Resolution='0.29858' Scale='1127.2' Rows='524288' Columns='524288' TileExtentWidth='76.3514968720267' TileExtentHeight='76.3514968720267' TileUrl= '' />
41
42 </LodInfos>
43 </TileCacheInfo>
44</TileCacheInfos>
1namespace TiledMapDataSource
2{
3 class GoogleMapTileUrlGenerator : ITileUrlGenerator
4 {
5 ITileUrlGenerator 成员
13
14 //获取瓦块图路径,参数:瓦块列值,瓦块的行值,比例等级,可视图层
15 private string GetUrl(int column, int row, int level, Dictionary<string, bool> layerVisibility)
16 {
17 string quadKey = TileToQuadKey(column, row, level);
18
19 string url = "http://kh.google.com/kh?v=3&t=t" + quadKey;
20 return url;
21 }
22
23 private static string TileToQuadKey(int tx, int ty, int zl)
24 {
25 string quad = "";
26 for (int i = zl; i > 0; i--)
27 {
28 int mask = 1 << (i - 1);
29 int cell = 0;
30 if ((tx & mask) != 0)
31 {
32 cell++;
33 }
34 if ((ty & mask) != 0)
35 {
36 cell += 2;
37 }
38 quad += cell;
39 }
40 quad = quad.Replace("0", "q");
41 quad = quad.Replace("1", "r");
42 quad = quad.Replace("2", "t");
43 quad = quad.Replace("3", "s");
44 return quad;
45 }
46 }
47}
5.上面的GoogleMapTileUrlGenerator类中的TileToQuadKey方法就是来实现图片名称编码的计算,这个方法是采用了VirtualEarthTileUrlGenerator中的方法,具体不同的部分就是最后做了一下简单的字符替换,可以这样做的原因是Virtual Earth和Google Maps的图片名称编码是一样的,如同一个位置的图片路径,Virtual Earth:http://h0.ortho.tiles.virtualearth.net/tiles/a1302.jpeg?g=1 ;Google Maps:http://kh.google.com/kh?v=3&t=trsqt ,只是代表的字符不同而已,0=q;1=r;2=t;3=s。2{
3 class GoogleMapTileUrlGenerator : ITileUrlGenerator
4 {
5 ITileUrlGenerator 成员
13
14 //获取瓦块图路径,参数:瓦块列值,瓦块的行值,比例等级,可视图层
15 private string GetUrl(int column, int row, int level, Dictionary<string, bool> layerVisibility)
16 {
17 string quadKey = TileToQuadKey(column, row, level);
18
19 string url = "http://kh.google.com/kh?v=3&t=t" + quadKey;
20 return url;
21 }
22
23 private static string TileToQuadKey(int tx, int ty, int zl)
24 {
25 string quad = "";
26 for (int i = zl; i > 0; i--)
27 {
28 int mask = 1 << (i - 1);
29 int cell = 0;
30 if ((tx & mask) != 0)
31 {
32 cell++;
33 }
34 if ((ty & mask) != 0)
35 {
36 cell += 2;
37 }
38 quad += cell;
39 }
40 quad = quad.Replace("0", "q");
41 quad = quad.Replace("1", "r");
42 quad = quad.Replace("2", "t");
43 quad = quad.Replace("3", "s");
44 return quad;
45 }
46 }
47}
6.接着在Default_TileMapData.aspx中的MapResourceManager1控件的DataSourceDefinition的路径改成GoogleMap.xml的路径,就可以运行查看效果了。
7. 完成后才发现Google Maps好像不允许这样方式取地图图片了经常会几率很高的取不到地图图片,而Virtual Earth没有这个问题了,看来还是google小气了一把了。
google maps取图时经常需要输入验证码,这样做的目的防止程序取了!!!