[转]ArcGIS移动客户端离线地图的几种解决方案
原文地址:http://blog.chinaunix.net/uid-10914615-id-3023158.html
移动GIS中,通常将数据分为两大类:basemap layer和operational layer。前者是指漫游或导航时起参考作用的图层,这些图层内容通常不会变化,只起到视觉辅助作用,称为底图图层;后者是指存储GIS数据的图层,比如可通过这些图层来提供属性/空间查询操作,或者对其内容进行编辑,然后与服务器端进行同步,称为业务图层。
目前ArcGIS移动产品有5种,基于Windows Mobile平台的ArcPad和ArcGIS Mobile,这两个产品已经很成熟了,都有各自的离线缓存格式,其中ArcGIS Mobile从10版本开始,可以直接读取ArcGIS Server缓存地图服务的切片文件做为basemap layer,支持exploded和compact两种格式。
相对于以上两个老牌移动产品,三个刚出道的小弟ArcGIS for iOS,ArcGIS for Android和ArcGIS for Windows Phone就走了不同路线:依赖于ArcGIS Server的REST服务。因此几乎所有操作,包括显示地图,都需要用到ArcGIS Server发布的各种服务。这三个产品的离线功能将来肯定是会有的,但具体的时间表还无法确定。
针对ArcGIS for iOS/Android/Windows Phone,本文提出3种可行的离线底图(basemap layer)的解决方案,供各位参考。以ArcGIS for Windows Phone为例。
1、ArcGIS Server地图服务的Exploded格式缓存文件
ArcGIS API for Windows Phone中,提供了ArcGISTiledMapServiceLayer用来加载ArcGIS Server发布的缓存地图服务,它的原理是Map控件计算好需要加载的切片的row,col,level参数,利用ArcGISTiledMapServiceLayer里的GetTileUrl方法提供如何获得指定参数的切片文件,最后拼接成完整的地图。
因此我们可以通过继承ArcGISTiledMapServiceLayer的父类,TiledMapServiceLayer或TiledLayer,来实现自己的自定义图层,比如用它来加载Google Maps,天地图等各种地图。加载这些在线地图都是通过重写GetTileUrl()方法来实现的。
对于已经存放在硬盘上的缓存文件,该如何加载呢?这几个图层还有一个方法,GetTileSource。这个方法有一个onComplete action,可以传入ImageSource类型的参数,它比GetTileUrl来的更直接。其实GetTileSource方法中调用了GetTileUrl方法的结果(一个获得tile的url字符串),利用这个字符串向服务器端发送请求,请求回来的结果就是切片图片的二进制流,再将这个二进制流形成ImageSource,通过onComplete方法返回。
所以我们可以抛开GetTileUrl,直接重写GetTileSource方法,来根据row,col,level参数,读取地图服务的缓存文件。首先将Exploded格式的地图服务缓存文件拷贝到手机中:
![]()
包含conf.cdi(ArcGIS Server 10版本中才有,记录了缓存的全图范围)和conf.xml文件的好处是,我们可以在代码中读取这两个文件来动态生成我们的Tiling Scheme,以完成图层初始化的工作。从配置文件中读取参数后,就可以重写GetTileSource方法了。部分代码如下:
2: {
3: string f = string.Empty;
4: if (_cacheTileFormat.ToLower().Contains("png"))
5: f = ".png";
6: else if (_cacheTileFormat.ToLower().Contains("jpeg") || _cacheTileFormat.ToLower().Contains("jpg"))
7: f = ".jpg";
8: else
9: throw new Exception("切片格式不明:" + _cacheTileFormat);
10: #region Exploded读取
11: if (_storageFormat == StorageFormat.esriMapCacheStorageModeExploded)
12: {
13: string baseUrl = _path;// "/WP_LocalCacheReader;component/Assets/usa_exploded/"
14: baseUrl += @"/_alllayers";
15: string l = "L";
16: l = level.ToString().PadLeft(2, '0');
17: string r = "R";
18: r = String.Format("{0:X}", row).PadLeft(8, '0');
19: string c = "C";
20: c = String.Format("{0:X}", col).PadLeft(8, '0');
21: string str = baseUrl
22: + @"/L" + l
23: + @"/R" + r
24: + @"/C" + c + f;
25: BitmapImage img = new BitmapImage(new Uri(str,UriKind.RelativeOrAbsolute))
26: {
27: CreateOptions = BitmapCreateOptions.DelayCreation
28: };
29: img.ImageFailed += (s, a) =>
30: {
31: string uri = _path + "/missing" + _tileRows.ToString() + f;
32: BitmapImage image = new BitmapImage(new Uri(uri, UriKind.RelativeOrAbsolute))
33: {
34: CreateOptions = BitmapCreateOptions.DelayCreation
35: };
36: onComplete(image);
37: return;
38: };
39: onComplete(img);
40: }
41: #endregion
42: }
当指定的切片文件不存在(也许还未创建)时,可以加载事先准备好的missing图片来替换。
2、ArcGIS Server地图服务的Compact格式缓存文件
这是ArcGIS Server 10推出的新的缓存格式,缓存图片都保存在.bundle文件中,一个bundle目前可存储128*128张切片。切片文件更少,主要目的是为了迁移方便。文档中并未给出读取这种格式文件的方法,不过牛魔王已经凭空推断出了这种格式的内容,这里就借鉴了他的方法。还是先将缓存文件拷贝到手机中:![]()
利用conf.cdi和conf.xml获得tiling scheme,之后重写GetTileSource方法。具体思路牛魔王文中已经给出,感兴趣的同学还是看原文,学习牛牛的思路比较好。
下面是读取两种缓存文件的效果:![]()
![]()
![]()
3、第三方离线地图文件
除了ArcGIS Server的缓存切片之外,我们还可以读取第三方的离线地图文件来做为我们的底图。比如以前面介绍过的Mobile Atlas Creator为例,我现在已经有了很多自己下载好的离线地图,如果能在ArcGIS移动客户端使用起步两全其美?其实在目前的离线导航软件中,很多都用sqlite数据库做为地图存储格式,因为它应用广泛,轻巧,紧凑,Android,iOS,Symbian等系统对它都有原生的支持。Mobile Atlas Creator中,RMaps和OruxMaps都用Sqlite保存离线地图。这里以应用较为广泛的RMaps格式为例,进行试验。
创建好的RMaps地图文件如下:![]()
我们利用FireFox里的Sqlite Manager插件先来查看一下数据库的内容:![]()
可以看出,我们所需的内容都保存在tiles这张表中,而x,y,z三个参数与我们所需的row,col,level很像。经过试验(保存一个全球范围的地图),很快验证出level=17-z。
参数有了,要如何读取切片呢?对于Sqlite,虽然目前Windows Phone还没有提供原生的支持,不过codeplex上已经有不少项目都提供了解决办法。我选择Sqlite Client for Windows Phone来读取RMaps的地图文件。下面是RMaps离线地图(Bing Maps)和ArcGIS Online上StreetMap叠加的效果:![]()
需要说明的是,不论是RMaps还是OruxMaps,都没有在数据库中保存tiling scheme的相关参数,所以我们不能为图层提供诸如FullExtent之类的参数。但这丝毫不影响我们的使用,我们可以为Map控件显示指定Extent,这样就可以直接显示我们的离线地图了。除了自己的地图数据之外,基本上所有数据源都使用一种空间参考,102100或者3857,你懂的。
这样即使我们没有ArcGIS Server软件,也能制作自己的底图了。这里有网友们已经下载好的各个城市的RMaps格式文件。
相对于RMaps之类的离线地图软件,ArcGIS的移动产品的优势除了不仅能够任意叠加地图数据,还有GraphicsLayer和服务器端强大的功能支持,在配合Windows Phone本身的SDK功能,你也可以做出一个功能全面的导航软件来。
关于离线地图文件的打包。1、在Silverlight程序中,Build Action的选择决定了文件最后的保存位置,比如你选择Resource,则会嵌入到工程的dll中,如果选择Content,则会保存在dll之外,xap文件之内。以上三种解决方案里,我们可以选择任意的Build Action,这样地图都会通过xap部署到手机里;如果有需要,我们还可以将文件拷贝到程序的IsolatedStorage中去。2、对于Exploded格式的缓存,WP的编程建议中提到,媒体文件Build Action设为Content效率会更高。3、对于Exploded格式的缓存,如果为了拷贝方便,我们也可以将其打包为.zip文件,部署到手机中,在程序加载的时候再将其解压缩来读取。
本文以ArcGIS for Windows Phone为例,讨论了3种离线底图的解决方案,文中所涉及的所有功能,ArcGIS for iOS和ArcGIS for Android同样适用。
[转]ArcGIS移动客户端离线地图的几种解决方案的更多相关文章
- 【BIGEMAP一键离线地图服务】
地址:http://www.bigemap.com/offlinemaps/ 首页 离线地图 代码示例 项目案例 开发文档 关于我们 [BIGEMAP一键离线服务] 1.快速搭建离线地图服务2 ...
- Arcgis For Android之离线地图实现的几种方式
为什么要用,我想离线地图的好处是不言而喻的,所以很多人做系统的时候都会考虑用离线地图.在此,我给大家介绍几种Arcgis For Android下加载离线地图的方式. 在Arcgis For Andr ...
- Arcgis Android API开发之离线地图
最近一直在倒腾Arcgis Android API等相关的东西,想把自己的做的图放到地图上去,也就是离线地图,穷人一般是没有钱的,一个月好几十的流量是开不起的,所以就左捉摸,右思考,看着API里面有离 ...
- ArcGIS for Android示例解析之离线地图-----LocalTiledLayer
转自:http://blog.csdn.net/wozaifeiyang0/article/details/7327423 LocalTiledLayer 看到这个标题是否是很激动,如题,该示例就是添 ...
- (四)WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.前言 在前面我花了两个篇幅来讲解行列号的获取,也解释了为什么要获取行 ...
- WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图(转载)
WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图 1.前言 在前面我花了两个篇幅来讲解行列号的获取,也解释了为什么要获取行列号.在这一章,我将把常见的几种请求瓦片时的URL样式罗列出来,并 ...
- 利用ArcGIS-Server瓦片制作离线地图包(*.tpk)_详细流程
1.写在前面 本人是综合了好几个资料才最终制作成功,在这个过程中发现网上好多博客写的步骤不是很详细,因此就把自己的详细制作步骤全部分享出来,可以供需要的小伙伴参考. (1)本文档不讨论tpk文件的详细 ...
- 从底层谈WebGIS 原理设计与实现(四):WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图
从底层谈WebGIS 原理设计与实现(四):WebGIS中通过行列号来换算出多种瓦片的URL 之离线地图 作者:naaoveGI… 文章来源:naaoveGIS 点击数:1759 更 ...
- Web GIS 离线地图
Web GIS 离线地图 1,基于瓦片的离线地图下载 博客园 阿凡卢 提供了离线地图的下载工具,下载地址:http://pan.baidu.com/s/1hqvQr7e 具体使用见 参考资料2 阿凡卢 ...
随机推荐
- WIN7_64位系统安装oracle以及PLSQL方法(不用装32位oracle客户端)
一.oracle10g安装,比较简单 1.去Oracle网站下载Vista版的Oracle:Oracle Database 10g Release 2 (10.2.0.4) for Microsoft ...
- Amazon Redshift and Massively Parellel Processing
Today, Yelp held a tech talk in Columbia University about the data warehouse adopted by Yelp. Yelp u ...
- OpenCV视屏跟踪
#include <stdio.h> #include <iostream> #include "opencv2/imgproc/imgproc.hpp" ...
- UML图总结
UML叙述 UML文档仅仅是设计与开发人员采用UML语言进行系统分析与设计的结果,并没有给出如何进行开发和采用何种开发流程,同样也不指导如何进行面向对象设计. UML文档描述了面向对象分析与设计的结果 ...
- Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6939890 在Android系统中,针对移动设 ...
- Cocos2d-X中实现菜单特效
Cocos2d-X中能够讲菜单和动作结合起来使用实现菜单特效 程序实例1:使用菜单和动作的组合实现菜单特效<一> #include "MenuItem.h" CCSce ...
- 基于 koajs 的前后端分离实践
一.什么是前后端分离? 前后端分离的概念和优势在这里不再赘述,有兴趣的同学可以看各个前辈们一系列总结和讨论: 系列文章:前后端分离的思考与实践(1-6) slider: 淘宝前后端分离实践 知乎提问: ...
- sqlplus常用操作命令2
常用编辑命令:A[ppend] text 将text附加到当前行之后C[hange] /old /new 将当前行中的old替换为newCLear] buff[er] 清除缓冲区中的所有行DEL 删除 ...
- [python语法巩固][leetcode326][Power of Three]
题目大意: 让你判断一个int是否为3的幂; 最简单的思路 C++ class Solution { public: bool isPowerOfThree(int n) { for(long lon ...
- .Net类型与JSON的映射关系
首先谢谢大家的支持和关注.本章主要介绍.Net类型与JSON是如何映射的.我们知道JSON中类型基本上有三种:值类型,数组和对象.而.Net中的类型比较多.到底它们是如何映射的呢? 总体来讲,Json ...