从天地图下载瓦片构建ArcGIS Server底图服务
我们可以通过调用天地图发布的API来将天地图作为自己的底图,但是这需要我们去学习如何天地图的API,并且要将天地图集成到自己的系统中则比较繁琐,并且在公司不能使用外网的情况下,调用天地图的API将变为不可行。今天我们通过下载天地图的瓦片地图,然后按照的瓦片组织规则将天地图的瓦片构建为自己服务器上的底图服务。
步骤如下:
1、从天地图下载瓦片
我们看到的天地图其实是由一个个瓦片拼接而成的,而这些瓦片存储在天地图的服务上,并且每一个瓦片都有自己的URI,天地图上由四种类型的瓦片,分别是:vec(矢量底图瓦片)、cva(矢量注记瓦片)、img(影像底图瓦片)、cia(影像注记瓦片),他们对应的URI分别是:
矢量底图:
矢量注记:
影像底图:
影像注记:
其中每个URI包含四个参数,分别是:
T=vec_c ; x = ? ; y = ? ; l = ?;
T代表底图类型,x代表瓦片的列号(起始位0),y代表瓦片的行号(起始位0),l代表底图的级别(起始位1,最大为20)。
天地图的切片规则是这样的,l=1时,整幅地图(全球地图)被切为两片,如图(l=1):
当l=2即以后,每个瓦片将被切位4片,如图(l=2):
2、通过坐标值计算在某一级别的行列号
通常,我们需要某一范围的地图,所以我们只需要下载一个范围内的地图,那如何通过一个范围的坐标系获得该范围的所有瓦片的行列好呢?
假设,X、Y为一个点的坐标值,而x、y为这个点在级别l时所处瓦片的行列号,通过下面一个公式来计算(X、Y)在级别l所处瓦片的行列号(x、y):
仅限在中国范围内
x = ((180 + X)/s*256)-1;
y = ((90-Y)/s*256)-1;
其中s代表在级别l时的分辨率,分辨率如下表:(分辨率(s)和级别(l)一一对应)
this._listResolution.Add(0.70312500015485435);l=1
this._listResolution.Add(0.35156250007742718);l=2
this._listResolution.Add(0.17578125003871359);l=3
this._listResolution.Add(0.0878906250193568); l=4
this._listResolution.Add(0.0439453125096784); l=5
this._listResolution.Add(0.0219726562548392); l=6
this._listResolution.Add(0.0109863281274196); l=7
this._listResolution.Add(0.0054931640637098); l=8
this._listResolution.Add(0.0027465820318549957); l=9
this._listResolution.Add(0.0013732910159274978);l=10
this._listResolution.Add(0.00068664549607834132); l=11
this._listResolution.Add(0.00034332275992416907); l=12
this._listResolution.Add(0.00017166136807812298); l=13
this._listResolution.Add(8.5830684039061379E-05); l=14
this._listResolution.Add(4.2915342019530649E-05); l=15
this._listResolution.Add(2.1457682893727977E-05); l=16
this._listResolution.Add(1.0728841446864E-05); l=17
this._listResolution.Add(5.3644207234319882E-06); l=18
this._listResolution.Add(2.6822103617159941E-06); l=19
this._listResolution.Add(1.341105180858E-06); l=20
公式讲解:
180 + X 代表从左至右的经度距离,s代表地图分辨率,就是每一个像素表示的距离(在这里单位为经纬度),而天地图的每一个切片为256*256像素的,所以每一个切片表示的距离为256*s,(180 + X)/s*256 则表示(X、Y)点所在切片的列号,可能是一个小数,所以则通过函数获得该数向上舍入(1.2则转化成2),由于行列号都是从0开始计数,故最后再减去1。如此便得到在 级别为 l 时,(X、Y)点的所在切片行列号为(x、y)。
我们只需要通过确定两个点的坐标就能确定一个范围,分别是点(Xmin,Ymin)和(Xmax,Ymax),则通过两个点获得行列的最大值和最小值,然后通过循环就能得到所有的瓦片,然后通过.NET中.NET命名空间中的类来下载每一个切片,并将每一个切片保存在本机上,代码如下:
= new ();
..Add("user-agent", "/5.0 ( NT 6.1; Win64; x64; rv:21.0) Gecko/ /21.0");
= .(, nCol, nRow, );
str2 = .((long) nCol, 0x10).();
str3 = "" + str2;
str3 = "C" + str3.(str2.);
= .(@"{0}\{1}.png", , str3);
.(, );
3、如何重新组织下载的切片
下载的切片是散乱的,必须通过有效的组织才能作为 的缓冲切片,则需要遵循 对瓦片的组织方式:
中的缓存是以文件夹结合文件名来组织和读取瓦片,如图:
我们可以看到,文件夹的第一级别为 L00、L01。。。。。,代表底图的级别;
文件夹的第二级别为、.。。。。。,代表一个级别中,所有的行,R后面的值就是上面计算出来的y值的范围,其中后面是通过16进制的编码;
文件夹的第三级为、。。。。。,代表一行中所有的列,C后面的值就是上面计算出来的x值的范围,也是16进制的编码;
例如:瓦片 它的行列号和级别分别为139、567、11,则它存储的位置为【L11】—【】—【】。
4、发布 服务
使用(Xmin,Ymin)和(Xmax,Ymax)两个点做一个矩形,然后将该矩形发布为地图服务,并将地图切片,这样在文件夹下则生成这个地图服务的缓存文件和配置文件,这时候只要把上面下载好的天地图瓦片文件夹复制到相应的文件夹下,然后修改配置文件:
只需要修改conf.xml和L00、L01等级别文件相互映射。将比例尺、分辨率和地图级别对应即可。
是如何读取瓦片并显示在相应的位置的那?
就是通过conf.xml中的地图分辨率配合图片的文件位置和编号计算出瓦片的位置,比如位置为 【L00//】的一个瓦片,然后通过L00从conf.xml中相应的,这个瓦片的位置为149行853列,瓦片为256*256像素,所以可以算出瓦片的经纬度,故显示在相应的位置。
上面这是我的猜想,然后通过修改L00中一个瓦片的名称,发现这个瓦片的位置也就显示在不同的地方了,故得出上面的猜想是正确的。
Conf.xml文件内同如下:
..5625
..78125
..-4
..725e-4
..583e-5
57044..2925e-5
63522..4063e-5
71761.71.7031e-5
8880..3644e-6
重启服务,完成配置过程,则将下载好的天地图瓦片发布为自己的地图服务: