2011年12月19日星期一

ArcGIS移动客户端中可以自动离线的底图图层

  我们都知道,在使用ArcGIS移动客户端(已更名为ArcGIS Runtime SDK for iOS/Windows Phone/Android)API进行开发时,一般对于底图数据,需要用ArcGISTiledMapServiceLayer这个类来加载,指向一个在线的缓存地图服务。而对于移动GIS应用,通常我们又有非常强烈的离线需求。目前来说,ArcGIS移动客户端底图离线有两种实现办法:自定义图层加载离线数据或等待新版本api来加载10.1的TilePackage底图离线包(iOS API已经实现)。
  这次我们来讨论另一种可以让底图离线的办法。在手机上使用过离线地图程序的朋友都知道,它们一般都会提供自动离线的功能,即当我们连接到互联网,浏览在线地图时,程序会自动将浏览过的数据缓存到本地,以便下次没有网络环境时可离线使用。新版本的Goolge Maps移动版,Android上的RMaps,OruxMaps等程序都有类似的功能。
  那么如何为ArcGIS的移动程序实现类似的功能呢?因为这个图层既要能够加载在线的地图服务,又要能够自动离线,所以我们选择创建一个派生自ArcGISTiledMapServiceLayer的类。当有网络连接时,我们浏览地图的过程中,将切片自动存储到本地,没有网络连接时就可以浏览这些切片了。而且可以给用户提供若干选项,比如是否允许自动下载缓存切片,是否允许自动更新已有的缓存切片等。
  请注意本文讨论内容与之前讨论的自定义图层加载离线数据不同,前者具有自动下载缓存切片的功能,下载后没有网络连接的情况下会自动变成离线图层加载离线数据,有网络连接的情况下可当做正常的在线图层使用;后者只能当做离线图层使用,不能自动下载缓存切片。
  这里我以Windows Phone为例,写好了一个扩展类:OfflineableTiledMapServiceLayer(下载地址见最后)。下面对它进行一些说明。
功能:
  OfflineableTiledMapServiceLayer是一个继承自ArcGISTiledMapServiceLayer的自定义类,在线浏览地图的过程中,会自动将缓存切片保存在Sqlite数据库文件中(存储在应用程序的IsolatedStorage空间内),无需人工干预;这样在没有网络连接的情况下,就自动加载先前保存过的切片,作为离线图层使用(程序代码无需做任何修改)。

如何使用:
  与ArcGISTiledMapServiceLayer用法一致,只需额外设置一些参数即可。
<esri:Map x:Name="map1">
    <my:OfflineableTiledMapServiceLayer Url="http://services.arcgisonline.com/ArcGIS/rest/services/Ocean_Basemap/MapServer" EnableOffline="True"  SaveOfflineTiles="True" SaveTilesMode="SaveOnly"
DeleteSavedOfflineTiles="False" LoadOfflineTileFirst="True" />
</esri:Map>

工作流程:
  除了ArcGISTiledMapServiceLayer已有的功能外,OfflineableTiledMapServiceLayer可在浏览地图的过程中,自动将缓存切片保存到Sqlite数据库中。当下次加载该服务时(以URL地址识别),就可从离线的数据库中加载切片数据(没有网络连接的情况下)。
  OfflineableTiledMapServiceLayer目前有以下5个属性可设置:

  • EnableOffline: 默认为True。当设置为True时,OfflineableTiledMapServiceLayer具有自动离线的能力;当设置成False时,OfflineableTiledMapServiceLayer完全和ArcGISTiledMapServiceLayer一样。
  • SaveOfflineTiles: 默认为True。当设置为True时,OfflineableTiledMapServiceLayer会将浏览过的缓存切片保存到本地的Sqlite数据库中(存储在应用程序的IsolatedStorage空间);当设置为False时,OfflineableTiledMapServiceLayer不会保存任何缓存切片。只有当LoadOfflineTileFirst==false时才会生效。
  • LoadOfflineTileFirst: 默认为False。当设置为True时,OfflineableTiledMapServiceLayer会优先从本地Sqlite数据库中加载缓存切片(即使有Internet连接),如果处于离线状态,则会直接从本地Sqlite数据库中加载缓存切片(如果之前没有保存过任何切片,则会抛出异常);当设置为False时,则会优先从在线服务中加载缓存切片,如果处于离线状态,则只能从本地Sqlite中加载数据。
  • SaveTilesMode: 默认为'SaveOnly'。当设置为'SaveOnly'时,OfflineableTiledMapServiceLayer只会存储新的缓存切片(Sqlite数据库中没有的);当设置为'SaveOrUpdate'时,OfflineableTiledMapServiceLayer会存储新的缓存切片,并且更新已有的缓存切片。当在线的缓存地图服务内容更新时,此选项比较有用。只有当LoadOfflineTileFirst==false && SaveOfflineTiles==true时有效。
  • DeleteSavedOfflineTiles: 默认为False。当设置成True时,会首先删除Sqlite数据库中已有的本图层数据,之后重新初始化本图层。只有当EnableOffline==True时有效。


Sqlite文件结构:
  Sqlite在移动设备上具有广泛的应用基础,iOS和Android对其均提供原生支持。OfflineableTiledMapServiceLayer使用Sqlite Client for Windows Phone来读写Sqlite数据库。可以使用Windows Phone 7 Isolated Storage Explorer或者Isolated Storage Explorer Tool将Sqlite文件从Windows Phone的IsolatedStorage中导出,以供其它移动程序使用,比如ArcGIS Runtime SDK for iOS/Android。
  OfflineableTiledMapServiceLayer创建的Sqlite数据库名称为"OfflineTiles.db",它的内容由一张或多张表组成。

  • 'MapServices'表:此表是OfflineableTiledMapServiceLayer必须使用的。具有四个字段:'url'(text), 'spatialreference'(text), 'fullextent'(text), 'tileinfo'(text)。存储在Sqlite中不同的OfflineableTiledMapServiceLayer由其Url属性区分(假设不同的Url代表不同的缓存地图服务)。另外三个字段分别以JSON格式存储了缓存服务对应的信息,这些信息是在离线状态下初始化图层所需要的。创建该表的SQL语句: CREATE TABLE "MapServices" ("url" TEXT PRIMARY KEY  NOT NULL  UNIQUE , "spatialreference" TEXT NOT NULL , "fullextent" TEXT NOT NULL , "tileinfo" TEXT NOT NULL )
  • 其它表:如果Sqlite中存储过任何OfflineableTiledMapServiceLayer缓存图片,则除了上述MapServices表外还会有其它表。其余每张表以该缓存地图服务的Url字符串命名。这些表包含有4个字段:'level'(integer), 'row'(integer), 'column'(integer), 'tile'(blob)。一目了然。创建该表的SQL语句:CREATE TABLE "HereIsYourServiceURL" ("level" INTEGER NOT NULL , "row" INTEGER NOT NULL , "column" INTEGER NOT NULL , "tile" BLOB NOT NULL ), 创建索引的SQL语句: CREATE UNIQUE INDEX 'idx_ HereIsYourServiceURL ' ON ' HereIsYourServiceURL ' ('level' ASC, 'row' ASC, 'column' ASC)


OfflineableTiledMapServiceLayer的下载地址(包括源码,示例程序,示例Sqlite离线文件):http://www.arcgis.com/home/item.html?id=d2b40d7f553947a2b575556b057f5dcf

2011年11月2日星期三

解读ArcGIS Runtime SDKs

  本文试图解读新的ArcGIS Runtime SDKs及其本质,与ArcGIS移动SDK,for iOS/Windows Phone/Android,之间的关系,以及这三种移动SDK后续发展的一些猜想。
  ArcGIS Runtime SDKs是随ArcGIS 10.1 beta一起发布的一套横跨桌面和移动端的,跨平台,轻量级的GIS开发SDK的总称。
image

  从上图中我们可以看出,ArcGIS Runtime SDKs家族包括了以下内容:

  • ArcGIS Runtime SDK for Android
  • ArcGIS Runtime SDK for iOS
  • ArcGIS Runtime SDK for Windows Phone
  • ArcGIS Runtime SDK for Windows Mobile
  • ArcGIS Runtime SDK for Java
  • ArcGIS Runtime SDK for Qt
  • ArcGIS Rutnime SDK for WPF

  之所以说ArcGIS Runtime SDKs横跨桌面和移动端,是因为它既包含了iOS/Windows Phone/Android等移动平台的开发SDK,也包含了可以开发传统桌面程序(C/S程序)的WPF、Java、QT等SDK;而后三种SDK则可开发出Windows和Linux平台下的具有丰富交互效果和良好体验的应用程序。其实ArcGIS Runtime还包括了一些现成的应用程序,比如iOS/Windows Phone/Android各自市场上都能下载到的“ArcGIS”程序,ArcGIS Mobile中的“ArcGIS”程序等。
  说起轻量级,首先要看看ArcGIS 10.1产品架构的一些变化。

image

  ArcGIS 10.1中,产品的划分更加明确和简单。主要分为四个部分,桌面GIS(传统的ArcMap,ArcGlobe等),ServerGIS(全新架构的ArcGIS Server),轻量级GIS(ArcGIS Explorer,Runtime SDKs及其对应的应用程序)和ArcGIS Online。前三部分都是围绕ArcGIS Online这个云GIS平台的,在不同程度上都与ArcGIS Online有交互,或可将数据直接部署上去,或作为它的客户端(云+端)。而轻量级GIS就是为了能够在任何地点,任何平台,任何设备上访问云平台提供的GIS能力。
  ArcGIS Runtime SDKs正是在这种背景下诞生的。其实它也分为狭义和广义上的两种解释。狭义的ArcGIS Runtime SDK是指桌面上的WPF,Java和Qt,它们的消息早在半年前就已经流出。它们的出现,是为了逐步替代强大而相对臃肿的ArcGIS Engine这个产品。做过Engine开发的朋友都知道,即使是最简单的显示地图的需求,理论上都必须在客户机上安装ArcGIS Engine Runtime这个运行时(注意不是ArcGIS Runtime),安装包通常400m左右。而利用新的ArcGIS Runtime SDK for WPF/Java/Qt开发出的程序,完全是绿色程序,不需要在客户机上安装任何部件(.Net Framework和JRE不计)即可运行,因为所有的依赖库直接和程序拷贝在一起即可。如果你喜欢ArcGIS Runtime SDK开发的程序的部署过程——拷贝到u盘里/插入目标计算机/运行,那么你一定也喜欢它的卸载过程——关闭程序/拔掉u盘。
  广义上的ArcGIS Runtime SDKs是上述列表中,诸多SDKs的统称。除了包含狭义的ArcGIS Runtime SDK,可以看到加入了移动端部分:ArcGIS Runtime SDK for iOS/Windows Phone/Android/Windows Mobile,而它们其实是新瓶装旧酒,分别对应以前的ArcGIS SDK for iOS/Windows Phone/Android和ArcGIS Mobile,只是换了产品名称而已。为什么会换名称?为什么还有ArcGIS Mobile这个“另类”的东西?这得从ArcGIS Runtime SDK的功能说起。
  做过ArcGIS Web API(ArcGIS API for Javascript/Flex/Silverlight)开发的朋友,应该可以很快理解狭义Runtime这个产品的所有功能。目前ArcGIS Runtime的功能与ArcGIS Web API,ArcGIS移动API(iOS/Windows Phone/Android)基本相同,都是基于ArcGIS REST API的。比如地图服务(动态/缓存)的加载,GraphicsLayer/FeatureLayer,基于FeatureService的数据编辑,Identify/Find/Query操作,GeometryService,Geoprocessing Service的调用等。它们的开发思路和代码编写几乎是一样的,比如ArcGIS API for Silverlight和目前的ArcGIS Runtime SDK for WPF,如出一辙(后者的前身就是ArcGIS API for WPF)。但狭义上的ArcGIS Runtime SDK与ArcGIS Web API不同之处在于,前者可以加载本地数据,包括Map Package/Tile Package/Locator Package/Geoprocessing Package。Map Package是包括.mxd文档和所有引用数据在内的压缩包,其余类似。最早的Package是9.3.1产品中的LayerPackage,它不仅包含了.lyr图层配置信息,还打包了图层所引用的实际数据。早期的ArcGIS Online平台允许用户上传LayerPackage以便分享,现在看来,直到此时Runtime产品的出现才将Package的概念发扬光大,并且为以后的所谓云GIS提供了更多的数据共享途径。对本地数据的读取是否破坏了基于ArcGIS REST API的框架呢?其实没有。ArcGIS API for WPF/Java/QT中,都内置了一个c++写的Web Server,读取本地数据后,会自动发布成这个Web Server上的REST服务来供Runtime SDK使用,所以一切功能,还是由REST API提供的。收起题外话,ArcGIS Runtime SDK的框架,是针对轻量级GIS产品(不包括ArcGIS Web API)的,它拥有统一的编程模型,可以用一致的开发思路,做出C/S,及移动端应用(Web API开发出B/S应用),为开发人员提供了极大的便利。这也是为什么将它们统称为ArcGIS Runtime SDKs的原因。
  在来说说ArcGIS Runtime for Windows Mobile(原来的ArcGIS Mobile)这个产品。之所以将它也归为ArcGIS Runtime SDK,是不无道理的。使用过ArcGIS Mobile的朋友一定知道,它的一个核心理念就是将数据划分为Basemap Layer和Operational Layer。前者是指起可视化参考作用的数据,一般是栅格底图或地图服务切片;后者是包含矢量信息在内的业务数据。ArcGIS Runtime中所涉及到Package,恰好与之对应。Tile Package对应Basemap Layer,Map Package对应Operational Layer。可以说,ArcGIS Mobile的设计理念,在整个ArcGIS Runtime产品家族中,得到了很好的延续。其实ArcGIS Mobile是个十分优秀的产品……
  到此,新的三个移动SDK(iOS/Windows Phone/Android)也归为ArcGIS Runtime SDKs的原因也就明了了,主要原因是都基于REST API的框架。另外基本可以肯定,它们都会使用相同的数据模型,即各种Package。由此不难推断,以后iOS/Windows Phone/Android平台上移动SDK的离线功能,也会依赖于Tile Package和Map Package。上周刚刚发布的ArcGIS API for iOS 2.1(以后要叫ArcGIS Runtime SDK for iOS)版本中,已经印证了这种猜测——加入了对Tile Package的支持,实现了原生的底图数据离线功能。其它两个移动平台的离线功能,敬请期待。
  由iPad这个产品引发的变革已经展开,移动设备数量正在爆炸性的增长,桌面设备和移动设备之间的概念会越来越模糊。Windows 8的发布预示着微软已经做出了改变,它即可以运行在桌面电脑上,也可以运行在平板设备中。有人说Windows 8的意义对于微软不亚于当年的Windows 95,我同意这个观点。Esri也做出了积极的改变,新的产品体系,新的产品命名,新的ArcGIS Runtime。

2011年10月25日星期二

在ArcGIS Web API应用程序中使用灰度地图

  上个月底,ArcGIS Online发布了一款全新风格的底图服务Light Gray Basemap。该底图服务尽可能少地使用了色彩,标注和要素内容,目的是突出地图的主题内容,把重点展示给最终用户。美化的底图固然好看,但有时我们不能为了使用地图而去使用地图,忽略了我们真正想要表达的意思,很多时候,都会回归到以简为美的原点。使用这种底图服务,我们可以很轻松的将注意力集中在业务数据上。
AGOL_LE_2_basemap_types

  可以看到,只有在右上角的Light Gray Canvas底图上,四个要素点才清晰可见。
  其实Google Maps API中就一直能够设置显示风格,以适应我们的需求。虽然ArcGIS Online已经推出了灰度底图服务,但对于自己的底图服务(尤其是国内数据用户)来说,如何能够风格化显示呢?以ArcGIS API for Silverlight为例来说明。
  缓存地图服务所对应的ArcGISTiledMapServiceLayer类中,暴露出了TileLoaded事件(继承自TiledLayer)。这个事件会在每一个切片加载完成时触发,并且事件参数中可以获得ImageSource属性,它就是切片本身,随后地图控件会对这些切片进行拼接,从而形成完整的地图。我们的工作,就是在这个事件中,对切片上的每个像素做色彩处理,从而达到风格化地图服务的效果。在Silverlight中,我们可以利用WritableBitmap来完成这项工作,代码如下,具体原理可自己参详:

   1: private void ArcGISTiledMapServiceLayer_TileLoaded(object sender, TiledLayer.TileLoadEventArgs e)
   2:         {
   3:             WriteableBitmap wb = new WriteableBitmap(e.ImageSource as BitmapSource);
   4:             for (int y = 0; y < wb.PixelHeight; y++)
   5:             {
   6:                 for (int x = 0; x < wb.PixelWidth; x++)
   7:                 {
   8:                     int pixel = wb.Pixels[y * wb.PixelWidth + x];
   9:                     byte[] dd = BitConverter.GetBytes(pixel);
  10:                     double R = dd[2];
  11:                     double G = dd[1];
  12:                     double B = dd[0];
  13:                     byte gray = (byte)(0.333 * R + 0.333 * G + 0.333 * B);
  14:                     dd[0] = dd[1] = dd[2] = gray;
  15:  
  16:                     wb.Pixels[y * wb.PixelWidth + x] = BitConverter.ToInt32(dd, 0);
  17:                 }
  18:             }
  19:             e.ImageSource = wb;
  20:         }

  下图是加载ArcGIS Online上StreetMap时的效果:
image  细心的朋友可能会发现,这个Silverlight程序并没有运行在浏览器中。这的确是一个OOB的程序,因为TileLoaded事件要求Silverlight程序必须获得提升权限才行。但是WPF和Windows Phone程序可以直接使用上述代码。
  那么在Silverlight应用中还能否显示风格化的地图服务呢?答案是肯定的。Map控件有一个Effect属性(继承自UIElement),系统提供了 BlurEffect,DropShadowEffect两个现成的效果。我们可以通过HLSL(High Level Shading Language)语言来自定义一些效果,比如灰度,通过PixelShader类应用到UIElement上,从而达到显示灰度地图的目的(此时Map控件中的所有图层都将变为灰色)。有兴趣的朋友可以动手实践一下,Windows Presentation Foundation Pixel Shader Effects Library这个项目中可以找到很多现成的效果。
  再来看看ArcGIS API for Javascript/Flex,两个API甚至都没有类似的TileLoaded事件可用。即使有,在Javascript中处理图片的颜色也是一项有难度的工作。不过不用担心,Portable Basemap Server从1.0.6版本开始,提供了风格化地图服务的功能,有灰度图和反色图两个选项,无需任何代码,即可在所有的ArcGIS REST客户端程序中,使用风格化的地图了:)
Untitled-1

2011年8月26日星期五

几个喜欢的歌手@豆瓣小站

上豆瓣不多,今天才看到豆瓣小站里有很多音乐的试听。发几个喜欢的歌手,排名不分先后~

2011年8月16日星期二

地图微博

  类似foursquare或街旁的网络应用模式主要是签到,但签到后的每条信息相对独立,没有互相的联系;LBS味道重,但该类应用发展已遇到瓶颈。
  类似twitter或微博的网络应用主要是发布信息,虽然也可在发布信息的同时标记地理位置,但这些地理位置相对孤立,只能和某条微博联系(查看地理位置必须点击该条微博)。海量信息之间可通过评论、转发、好友发生联系,但无法在真实空间范围上发生联系,缺乏lbs因素。
  设想中的地图微博是一种能够将两种应用结合起来的应用。即在发布的时候,发布者可以同时标记发布信息时的地理位置(可选或自动),这样每条信息就有了自己的地理位置。对于拥有地理位置的微博信息,可直接展示在地图上。
  这样地图微博应用的界面就主要是一张地图,地图上显示了在该可见范围内发布的所有微博信息。新信息发布时,可主动推送到客户端,弹出气泡显示。用户可设置地图上总共可显示的信息条数。当超过该条数后,最旧一条信息消失,最新一条信息气泡弹出。信息此起彼伏,蔚为壮观。。。
  可在空间和时间两个维度上对信息进行过滤。

  • 空间过滤:即地图范围过滤。地图上只显示当前可见地理范围内发布的微博信息,就达到了空间过滤的目的。对于小比例尺(大范围)的地图,微博数目过多,可采用聚类的方式显示。
  • 时间过滤:加上时间滑块的工具条,可显示指定时间范围内(且在地图可见范围内)的所有微博信息。拖动时间滑块,可动态显示/隐藏微博信息。如果只想看到自己的微博,则可看到随时间的变化,自己发布微博位置和内容的变化;如果想看其他用户(比如自己关注的人/所有人)的信息,随着时间滑块的拖动,地图上动态显示该时间范围内所有其他人的信息。

  将地图与微博应用结合的好处:

  1. 加入更多真实的地理社交(geosocial?)因素。如果查看所有人的信息,则可实时看到自己周围的陌生人说的话/自己周围正在发生什么信息,比现在微博首页(所谓的timeline)更加真实,更加有用。如果感兴趣的话,可以和自己周围的人直接发起社交活动。因为通过地图找到自己周围感兴趣的人比从一堆文字信息里找到自己周围感兴趣的人要容易的多;
  2. 非常容易发掘热点事件。某一时间段内,如果某个特定地理范围内的微博信息突然激增,则很容易判断出该地发生了社会热点事件。比如甬温线动车事件后,发布与该事件有关的信息都可标注地理位置到温州,其他网友也可为了围观目的,手动标记位置到温州(类似现场签到)。这样改地点的信息数目就会激增,可制作出相应的heatmap,来供大家参考;
  3. 地图微博能够将twitter和foursquare之类的两者应用结合起来,使信息交流通过空间性而变得更加真实和有趣。

  通过地图微博,可以把timeline中无序杂乱的信息组织在地图这个有序真实的二维世界中。新浪微博目前还没有意识到发布信息的同时,搜集地理位置的重要性。没有地理位置,地理社交应用就无法上马。google+在上线之初就意识到了这个问题(自己猜测),因为在发布每条信息的时候,都可以选择提交地理位置(信息发布框旁边有个按钮)。而新浪微博目前电脑端的应用无法提交地理位置,只有手机客户端才可以。
  补充几个应用场景:

  • 我住在东直门,要卖一辆自行车,基于地理位置发布了一条信息;某人也住东直门附近,刚好要买一辆二手车,多边形选择东直门,选择一个月之内,搜索“自行车”,便能直接找到我。发、收、搜索信息均及时免费有效。可远离58同城、赶集网;
  • 人们每天都在进行着消费行为/每天foursquare签到300w次/消费完成后有功夫的人才会去大众点评进行点评。相比于这些,年轻人更愿意在买完东西后,就地发一条微博来对商家进行评价,评价信息会自动随着时间和位置进行积累。我在东直门,想要找好吃的东西,多边形选择东直门,搜索“好吃”,即可看到大家对所有商家的真实评价。可远离大众点评网;
  • 我在东直门上班,想找恋爱对象,基于地理位置发布信息,很容易被人找到。而且也可以很轻易找到同在居然大厦上班的单身女青年,如果愿意,也可以找到隔壁中青旅的人。联系起来很方便,探索的过程本身也很有趣。可远离世纪佳缘、百合网;
  • 10年后,你可以来到东直门附近,将时间范围拉回十年前,看看当时人们在这里都在做着什么,过着什么样的生活。。。
  • 应该还会有更多意想不到的应用,颠覆目前的社交模式。

  地理社交,为各式各样的周边信息提供一个平台,让你周围的信息流动起来。

2011年7月19日星期二

vimeo转载:the mountain

from: http://www.vimeo.com/22439234
that's the reason why we should love our earth.

2011年7月11日星期一

Portable Basemap Server:多数据源多客户端的底图服务器

2014.3.8更新v3.1
~在线切片转换为MBTiles时,增加RecreateEmptyCache模式。当你想继续上次未完成的任务或打算合并多个级别/范围的切片时,RecreateEmptyCache模式会非常适合;
~在CustomOnlineMaps.xml中自定义数据源时,增加Multi-Layer模式,比如可将标注和影像两个数据源融合为一个服务。具体用法请参考自带示例;
~修复已知Bug;
2013.5.10更新v3.0
~添加以Windows服务方式运行功能,即使不登陆系统,也可通过REST Admin API对PBS进行管理;
~发布的缓存服务增加对OGC WMTS规范的支持。详见这里
~数据源增加对OGC WMS服务的支持。详见这里
~数据源增加对高德本地缓存文件的支持。详见这里
~预览界面中可显示切片来源(动态生成/文件缓存/内存缓存,以不同底色区分);
~添加日志功能;
~修复已知bug;
2012.12.10更新v2.0.7:
~为影像数据源增加本地缓存(.cache文件)功能。详见这里
~在线地图转换/下载到MBTiles格式时,增加按Shapefile文件范围下载功能。详见这里
~为转换后的MBTiles文件增加了"压缩"选项,某些情况下可大幅减小MBTiles文件体积。详见这里
2012.11.14更新v2.0.6:
~Portable Basemap Server已在CodePlex上开源,LGPL协议;
~添加ArcGIS Cache/在线地图数据源到MBTiles格式(.mbtiles)的转换/下载工具。详见这里
~为在线地图数据源添加本地缓存功能。详见这里
~改进ArcGIS Tile Package(.tpk)格式文件的读取速度;
~修复已知bug;
2012.4.24更新v2.0.5:

~为数据源类型为ArcGISDynamicMapService的PBS服务增加附加参数设置,比如layers,layerDefs等,达到控制图层可见性,按属性过滤图层内容等目的。详见这里
~REST Admin API为ArcGISDynamicMapService数据源增加changeParams操作,以动态修改附加参数。详见这里。详见这里
~数据源增加对ArcGISTiledMapService的支持;
~增加自定义在线地图功能。可通过修改CustomOnlineMaps.xml文件内容,自行增删在线地图数据源(数据源须采用Google Maps/Bing Maps/ArcGIS Online地图的缓存策略);
~增加自动保存/载入上次配置的功能;
~为系统托盘图标增加右键菜单;
~修复已知bug;
2012.1.9更新v2.0.4:
~REST Admin API增加enable/disable/clearByService三个操作,分别用于开启/关闭内存缓存功能,清除指定服务的内存缓存数据。详见这里
~界面改进:增加中文语言界面;支持最小化到系统托盘;地图预览加入显示切片网格功能;
~修复一些已知Bug;
2011.11.21更新v2.0.3:
~
增加REST Admin API。任何程序可通过发送HTTP(POST)请求,对PBS的服务进行管理。新增操作:添加服务(addService),删除服务(deleteService)。详见这里
~底图风格化选项增加泛黄(tint)与浮雕(embossed)两种效果。详见这里
2011.11.08更新v2.0.2: ~数据源增加对ArcGIS Tile Package格式的支持。Tile Package是ArcGIS 10.1推出的便于分发,可将地图服务缓存文件(compact或exploded)打包成单一文件的文件格式。详见这里
~增加对单一服务的清除内存缓存功能;
2011.11.04更新v2.0.1: ~增加对单个服务是否启用内存缓存的控制;
~增加输出动态生成切片数量和内存缓存切片数量的信息;
~界面微调;
~修复bug:32位系统上无法启用内存缓存功能;
~修复bug:移动PBS文件夹后,启用内存缓存功能时可能报错;
~修复bug:对服务启用反色(Invert)视觉效果后,PBS内存占用过大;
~修复bug:在没有网络连接的情况下,双击预览没有初始范围的数据源时(第三方离线缓存或影像数据源),程序报错;
2011.10.31更新v2.0: ~增加内存缓存功能。可将已生成过的切片数据自动缓存在机器内存中,之后可从内存中直接返回该切片,而不是动态生成。启用内存缓存功能后,可显著提高PBS性能,尤其对于动态缓存地图服务功能(影像数据或动态地图服务作为数据源),在几乎不占用cpu资源的情况下,支持的并发数可提高数十倍。该功能利用Memcached完成,它是一个免费的高性能分布式缓存系统(http://memcached.org/)。详细介绍
2011.10.25更新v1.0.6: ~增加底图风格化选项。目前除了原本的底图之外,为所有服务提供两个视觉风格选项:灰度图(Gray)和反色图(Invert),用于特殊目的。比如使用灰度图可突出显示业务内容,详见这里详细介绍
2011.10.12更新v1.0.5:
~增加ArcGIS Server Endpoint(http://localhost/arcgis/rest/services?f=json)信息,以便需要此信息的程序来使用PBS发布的服务。比如可在Silverlight Viewer中,直接加载PBS转发的天地图服务;
2011.8.8更新v1.0.4:
~增加配置文件功能:可将已发布的服务保存为配置文件,下回启动程序时可载入配置文件以启动相应服务;
~增加选择本地IP地址功能:方便生成供其他机器使用的正确服务地址;
~修复bug:在有些机器上双击服务进行预览时,程序会崩溃。原因是预览窗口中的服务属性使用了xaml binding,但出现了没有捕捉到的异常(有vs2010开发环境的机器不会抛出此异常)。感谢ningjun198624的反馈
~修复bug:在没有vs2010开发环境的机器上发布RasterDataset数据源报错。原因是程序中使用的gdal由vs2010编译,需要用到几个额外的动态链接库。新版本中已将所需的文件随压缩包分发。
2011.7.31更新v1.0.3:
~影像数据源增加对.sid格式的支持:MrSID是LizardTech公司持有的高压缩比影像存储格式,根据GDAL的解释,最初被FBI用于指纹存储。了解遥感的mm同事告诉我,MrSID格式压缩率通常比ecw格式要高,并且使用更广泛;
~数据源增加对ArcGIS影像服务的支持:在10.1版本之前,ArcGIS Server发布的Image Service是不能够做切片的。通过PBS,可将ArcGIS Server的影像服务转换成动态缓存地图服务,既提高了显示速度和效果,又省去了切图时间和硬盘空间;
~添加平均出图时间统计:服务信息中增加“Seconds Per Tile”统计信息,即该服务平均成功输出一张切片所用的时间。
2011.7.24更新v1.0.2: ~影像数据源增加对.ecw格式的支持:ecw是ERDAS公司持有的高压缩比影像格式,压缩率可达1:2~1:100。比如1m大小的ecw文件可包含3波段3000*3000(行/列)大小的影像数据;
~影像数据源增加对.vrt格式的支持:类似于ArcGIS中的Raster Catalog。比如你有不同空间范围内的若干小的影像文件,可通过构建后缀名为vrt的xml文件,直接将它们通过动态镶嵌,发布为一个完整的动态缓存地图服务;
~修复bug:ArcGISDynamicMapService数据源输入错误服务地址时程序会崩溃;
~代码重构。
2011.7.17更新v1.0.1:

~数据源加入对影像数据的支持:对于大数据量的影像文件,无需切图,即可提供缓存地图服务。数据源选择RasterDataset,可发布文件形式的影像数据。利用GDAL读取栅格图像,支持格式见这里;不支持动态投影(TilingScheme文件中的空间参考必须与影像数据的空间参考一致);
~修复bug:未发布服务时点击“Copy to Clipboard”按钮出错;
~修复bug:预览窗口中左上角的缩放级别信息在有的坐标系下不准确。
==================================更新分割线====================================
使用现在流行的Web地图API的第一件事情,就是往地图控件中添加一个底图(Basemap)图层,做为我们整个GIS应用的可视化基础。而这个底图图层通常有两个特点,一是经过了缓存,即服务器端提供已经预先缓存好或动态提供固定大小(比如256*256)地图切片,加快客户端的访问速度;二是该图层由一个REST风格的网络服务暴露出来。对于它的访问,客户端一般会发起若干个包含有三个关键参数的请求,比如http://hostaddress/servicename/LEVEL/ROW/COLUMN,将请求的结果(若干切片)拼接成我们所看到的地图。
目前来讲,要使用这些底图服务的前提是,我们必须使用特定的客户端才能加载特定的底图服务,比如利用Google Maps API加载Google的底图;如果要加载自己地理数据,还需要有专门的GIS软件,比如ArcGIS Server来发布Map Service。
为了解决这一问题,使得开发人员能够更加方便地加载各种底图服务,从而将更多的精力投入到做出更有用的系统中去,我做了这个称作Portable Basemap Server(简称PBS)的小程序供大家免费使用。它的目的是通过一个可以拷贝到U盘里的,免安装的WPF程序,来加载各种数据源作为底图图层,直接为更多的客户端API提供一致风格的REST底图服务,从而使开发人员免去为每个应用程序自定义图层的麻烦。

Untitled-1
关于PBS的功能
使用起来很简单,大致分四个步骤。1、选择数据源类型,2、设置数据源路径,3、设置将要发布的服务端口号和服务名,4、启动服务。程序界面如下:
image
一、选择数据源类型:
image

  • MobileAtlasCreator:MAC是一个开源的Java程序,可将在线地图切片保存到本地,比如Sqlite数据库中,供移动设备离线使用。介绍看这里。很多朋友都喜欢使用Google地图作为底图,以前的方法是,用第三方程序(MAC还是比较厚道的,不加水印没有任何功能限制)去下载切片,保存到本地,然后按照ArcGIS缓存的组织规则重新组织这些切片,再将其发布成缓存地图服务。最后一步比较麻烦。利用PBS,就可以直接读取MAC保存的Sqlite数据库,将其中的切片直接发布成可供多种客户端API使用的底图服务;
  • MBTile:类似于MAC,但它有更严格的规范,比如在特定位置存储全图范围(MAC没有),具体规范查看这里。MBTile切片存储遵循的是TMS规范,虽然这中规范已被WMTS逐步取代,但PBS依然支持这种数据源,可直接读取该数据源作为多种客户端的底图服务。可在这里下载一个海地的地形图进行试验;
  • ArcGISCache:这个不用多说了,ArcGIS Server生成的地图缓存,指定包含Conf.xml和Conf.cdi文件的文件夹作为数据源即可,PBS会自动读取Tiling Scheme;Exploded和Compact两种存储格式均可识别。如果是ArcGIS 10之前的切片,需要自己手动创建Conf.cdi文件(仿照现有的文件即可,里面存储的是全图范围);
  • ArcGISTilePackage:Tile Package是ArcGIS 10.1推出的便于分发,可将地图服务缓存文件(compact或exploded)打包成单一文件的文件格式,文件后缀名为.tpk。以前为了分发地图数据,需要将样式配置信息(针对所有图层的地图文档.mxd,针对单个图层的图层样式.lyer)和实际地理数据(.mdb/.gdb/.shp等)一起拷贝。自9.3.1的开始,为了便于地图数据的分发,ArcGIS推出了Layer Package格式(.lpk),它包括了图层样式(.lyr)以及引用到的实际地理数据。这样其他用户拿到一个文件,就可完全还原数据本身和显示样式。ArcGIS10开始推出Map Package(.mpk)格式,10.1开始推出Tile Package(.tpk),Locator Package(.apk)和Geoprocessing Package(.gpk)格式;
  • RasterImage:1.0.1版本开始支持。文件形式的影像数据。在项目过程中,可能需要加入高分辨率的影像文件做为底图服务,但对这些影像文件切图、保存需要耗费极大的时间、空间。利用PBS可将影像文件直接发布为动态缓存地图服务,无需切图即可达到缓存地图服务的效果。对栅格数据的读取是利用GDAL完成的,支持的影像格式见这里。发布的影像数据必须具有正确的空间参考信息;需要选择ArcGIS Server生成的TilingScheme(Conf.xml和Conf.cdi文件)以确定缓存服务的级别;不支持动态投影;
    1.0.2版本开始支持.ecw和.vrt影像格式。
    ecw是ERDAS公司持有的高压缩比影像格式,压缩率可达1:2~1:100。比如1m大小的ecw文件可包含3波段3000*3000(行/列)大小的影像数据;1.0.3版本开始支持.sid影像格式。
    .vrt格式类似于ArcGIS中的Raster Catalog,具有对多张影像动态镶嵌的功能。比如你有很多空间连续的小的影像文件,它们加起来可能有上百G。通过构建后缀名为vrt的xml文件,直接将它们通过动态镶嵌,发布为一个完整的动态缓存地图服务。vrt文件可利用gdalbuildvrt.exe工具来自动创建,发布时PBS中数据源直接选择.vrt文件即可。vrt格式介绍一文,供参考。
    1.0.3版本开始支持.sid影像格式。
    MrSID是LizardTech公司持有的高压缩比影像存储格式,根据GDAL的解释,最初被FBI用于指纹存储。我对遥感知识知之甚少,做遥感的mm同事告诉我,MrSID格式压缩率通常比ecw格式要高,并且使用更广泛;
    v2.0.7版本开始,为影像数据源提供本地缓存功能,任何客户端浏览过的切片,都会存储在指定目录的本地缓存文件中;本地缓存文件存在的情况下,会首先从该文件中输出切片,而不是动态输出。对于多并发情况下的影像数据源,可大幅减少cpu的使用率(与内存缓存配合可达成二级缓存的效果)。此功能可通过配置文件中的AllowFileCacheOfRasterImage参数设置,默认为True;image
  • ArcGISDynamicMapService:此数据源是指利用ArcGIS Server发布的,没有创建过缓存的动态地图服务。动态地图服务如何作为缓存地图服务的数据源呢?这就是所谓的动态缓存服务,没有预先创建过缓存,但能够提供缓存服务效果,并且支持动态投影的服务,也可查看超图的在线帮助。通过PBS,也能够提供动态缓存服务了,并且不需要在客户端再去自定义图层,因为PBS已经为你做好,直接使用即可。还可以输入多个动态服务地址,通过多个服务实例来达到加速动态缓存服务的目的,原理说明可查看这篇文章。输入服务地址后,还需要选择Tiling Scheme。可以选择Google/Bing/ArcGISOnline采用的Tiling Scheme,也可指定ArcGIS Server创建的Tiling Scheme(Conf.xml和Conf.cdi文件),如果数据源的坐标系与指定的Tiling Scheme坐标系不一致,可以自动进行动态投影;2.0.5版本开始,在创建服务后,可为此数据源设置附加参数,比如layers,layerDefs等,达到控制图层可见性,按属性过滤图层内容等目的,具体语法请参考ArcGIS Server REST API
    image
  • ArcGISTiledMapService:v2.0.5版本开始支持。此数据源为ArcGIS Server发布的缓存地图服务。使用此数据源的目的是使已经经过缓存的地图服务能够利用PBS的附加功能,比如提供具有视觉风格的底图服务;
  • ArcGISImageService:ArcGIS Server发布的影像服务(ImageService)。10.1版本之前的ArcGIS,不支持ImageService的切图。类似于上面的动态地图服务数据源,PBS可将动态的ImageService转成动态缓存地图服务,既大大改善了ImageService的显示效果和速度,又省去了切图所需的时间和硬盘空间。支持输入多个影像服务地址,通过多个服务实例来达到加速动态缓存地图服务的目的。选择此数据源,默认填入Esri发布的全球Landsat数据影像服务地址,可通过观察原动态影像服务,对比PBS转换后的动态缓存地图服务的效果;
  • OGCWMSService:v3.0版本开始支持OGC WMS服务做为数据源。原理同上述ArcGISDynamicMapService类似,可将动态的WMS服务直接转换为具有缓存能力的服务,改进显示效果。注意:不同于ArcGIS的动态地图服务,支持几乎所有坐标系的动态投影,选择此数据源时,缓存策略文件的空间参考必须在WMS服务能力文档描述中所支持的坐标系统列表内,否则无法启动服务;
  • AutoNaviCache:v3.0版本开始支持高德离线地图缓存。资料有限,目前能支持的格式结构如下:
    image_thumb[1]
  • 各种在线地图:v2.0.5版本开始可通过CustomOnlineMaps.xml文件自定义在线地图数据源。这个也不用多说了。目前支持OpenStreetMap,Google Maps街道图,Google Maps影像图,Bing Maps街道图,Bing Maps影像图,天地图(文字注记和地图是两个服务,可叠加)这几种在线地图作为数据源,天地图Tiling Scheme是WGS 1984坐标系的,其他几种均是WGS 1984 Web Mercator坐标系的。需要说明一点,如果你打算使用PBS为公网用户提供服务,选用在线数据源时可能会有延迟,因为PBS首先会下载切片到本机(内存中),然后公网用户在下载这些结果,局域网应用可忽略此问题(2.0版本开始提供内存缓存功能,可解决此问题);如果确实慢,可考虑使用MAC数据源(Bing Maps服务最好输入一个合法的API KEY,以用达到最快的下载速度)。v2.0.6版本开始,为在线地图数据源提供本地缓存功能,任何客户端浏览过或在格式转换过程中下载过的切片,都会存储在指定目录的本地缓存文件中;本地缓存文件存在的情况下,会首先从该文件中输出切片,而不是重新下载。此功能可通过配置文件中的AllowLocalCacheOfOnlineMaps参数设置,默认为True。还要郑重声明一点,这些数据源只能做试验使用,不能直接用于商业目的,没有技术手段限制,但大家要自觉。如需商用,还请联系最终服务提供商
二、设置数据源:
为选择的数据源类型设置相应的数据源位置即可。MAC和MBTile直接选去本地的Sqlite文件;ArcGISCache选择包含有Conf.xml和Conf.cdi的文件夹;ArcGISDynamicMapService直接输入一个或多个REST服务的地址;所有在线地图不需要设置数据源位置,PBS已为你做好。
三、设置端口号和服务名
PBS是通过.NET Framework的WCF框架完成的。在启动服务之前需要选择将服务发布到本机的哪个端口上。一个端口上可以发布多个服务,也可将服务发布在多个端口上。但同一端口上不能有同名的服务。
DisableClientCache:默认情况下,PBS输出的图片可以被缓存在客户端,下次访问时会直接使用客户端的缓存而不需要重新绘制切片。勾选此选项后,PBS输出的图片响应会指明不允许客户端进行缓存,从而方便客户端每次都请求道最新的数据。
Display”NoData”Tile:勾选此项后,在Tiling Scheme范围内,如果某些范围或某些比例尺没有创建缓存,则会显示一个NoData的图片;如果打算用此服务与其它服务叠加(保持此服务背景透明),请不要勾选。
四、启动服务
设置好上面参数后,点击“Start New Service”,即可启动该服务。启动好的服务会出现在下方的服务列表中:
image
五、服务管理
程序下方的服务列表内会列出所有正在运行的底图服务,会显示服务名,所在端口号,数据源类型,服务启动后输出的切片数量,平均成功输出一张切片所需时间,以及最后一次被请求的客户端ip地址做为服务情况的大致预览。可在服务列表中双击某个服务,会弹出一个对话框,调用ArcGIS API for WPF查看该服务,并显示该服务的详细信息。如果该服务缺少全图范围参数,比如MAC数据源,则会新弹出的WPF对话框会额外添加一个ArcGIS Online底图,以便方便浏览到该服务的范围。
image 如果加载某个切片失败,比如下载在线数据源时网络连接出现问题,会显示失败的图片:
image
若要删除某个服务,请在服务列表中选中,然后点击“DeleteService”即可。
此外,还可将已发布的全部服务保存成配置文件(v1.0.4版本以上),下回程序启动时可载入配置文件以启动相应的服务。配置文件保存在程序根目录下的Config.db文件中(sqlite文件格式)。
image
2.0.3版本开始,PBS增加REST Admin API。任何程序可通过发送HTTP(POST)请求,对PBS的服务进行管理。PBS的REST Admin API使用HTTP基本认证,即HTTP请求头(request header)中必须含有“Authorization”项,该项内容为Base64编码字符串,格式为“用户名:密码”。请求认证信息中的用户(包含正确的密码),必须为PBS运行机器上Administrators组中的成员,所发送的请求才会被正确处理,否则将返回包含详细错误描述的响应信息。
为了保证PBS能够正确响应请求的操作,请求中的端口必须提前打开。2.0.3版本开始,PBS默认使用7080端口,该端口会在PBS启动时自动开启。可修改配置文件中的DefaultPort值来更改PBS使用的默认端口号。
每项管理操作都需要相应的参数,参数提交格式为标准JSON对象,对象中每一个键值对即为一个参数(键应为string类型,值应为string/int/bool/null类型)。参数应存放于HTTP请求体(request body)内。
~添加服务(addService):v2.0.3,该操作的地址为“http://serverip:port/PBS/rest/admin/addService”,参数列表如下:
  • name:(必须)需要添加的服务名称;
  • port:(必须)需要添加的服务端口号;
  • dataSourceType:(必须)需要添加的服务数据源类型,例如“ArcGISTilePackage”。可选值:MobileAtlasCreator|MBTile|ArcGISCache|ArcGISTilePackage|RasterImage|ArcGISDynamicMapService|ArcGISImageService|OpenStreetMap|BingMapsRoad|BingMapsImagery|GoogleMapsRoad|GoogleMapsImagery|TianDiTuAnnotation|TianDiTuMap。区分大小写;
  • dataSourcePath:(必须)需要添加的服务数据源路径。文件数据源类型可用本地路径或UNC路径,比如“D:\\arcgisserver\\arcgiscache\\CharlotteRaster.tpk”或“\\192.168.0.100\\arcgisserver\\arcgiscache\\CharlotteRaster.tpk”;ArcGIS动态地图服务或影像服务填服务地址;其余在线服务不需要此参数,填“”即可。注:RasterImage数据源路径中不能有中文字符;
  • allowMemoryCache:(可选)需要添加的服务是否允许支持内存缓存,默认为true。可选值:true|false;
  • disableClientCache:(可选)需要添加的服务是否禁止客户端缓存,默认为false。可选值:true|false;
  • displayNodataTile:(可选)需要添加的服务是否显示“Nodata”的切片,默认为false。如需要和其它服务叠加,此项需为false。可选值:true|false;
  • visualStyle:(可选)需要添加的服务的视觉效果,默认为None。可选值:None|Gray|Invert|Tint|Embossed。区分大小写;
  • tilingSchemePath:(可选)需要添加的服务使用的tiling scheme(缓存策略)文件路径。默认为null;
比如,在fiddler中发送如下请求:
image
或用C#发送如下请求:
   1: byte[] postData = Encoding.UTF8.GetBytes(@"{""port"":7080, ""disableClientCache"":false, ""dataSourcePath"":""D:\\arcgisserver\\arcgiscache\\CharlotteRaster.tpk"",""dataSourceType"":""ArcGISTilePackage"", ""tilingSchemePath"":null, ""allowMemoryCache"":true, ""visualStyle"":""None"", ""name"":""ServiceName1"", ""displayNodataTile"":false}");



































   2:             HttpWebRequest myReq = WebRequest.Create("http://localhost:7080/PBS/rest/admin/addService") as HttpWebRequest;



































   3:             myReq.Method = "POST";



































   4:             string username = "Administrator";



































   5:             string password = "123456";



































   6:             string usernamePassword = username + ":" + password;



































   7:             //注意格式 “用户名:密码”,之后Base64编码



































   8:             myReq.Headers.Add("Authorization", Convert.ToBase64String(Encoding.UTF8.GetBytes(usernamePassword)));



































   9:             myReq.ContentLength = postData.Length;



































  10:             using (System.IO.Stream requestStream = myReq.GetRequestStream())



































  11:             {



































  12:                 requestStream.Write(postData, 0, postData.Length);



































  13:             }            



































  14:             WebResponse wr = myReq.GetResponse();



































  15:             System.IO.Stream receiveStream = wr.GetResponseStream();



































  16:             System.IO.StreamReader reader = new System.IO.StreamReader(receiveStream, Encoding.UTF8);



































  17:             string content = reader.ReadToEnd();



































  18:             receiveStream.Close();



































  19:             reader.Close();



























响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。如果操作成功,detail message将返回PBS服务信息的JSON字符串,如果失败,将返回详细错误原因。

















~删除服务(deleteService):v2.0.3,该操作地址为“http://serverip:port/PBS/rest/admin/deleteService”,参数列表如下:




















  • name:(必须)需要删除的服务名称;






  • port:(必须)需要删除的服务所在端口号;





响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。

















~开启内存缓存(enable):v2.0.4,该操作地址为“http://serverip:port/PBS/rest/admin/memCache/enable”,参数列表如下:




















  • memSize:(可选)内存缓存功能占用的内存大小,默认为64(M)。





如果内存缓存功能已经开启,返回结果依然为true,但会有额外提示。








响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。

















~关闭内存缓存(disable):v2.0.4,该操作地址为“http://serverip:port/PBS/rest/admin/memCache/disable”,此操作不需要参数(请求体为空即可,如有则忽略)。如果内存缓存功能已经关闭,返回结果依然为true,但会有额外提示。








响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。

















~清除某个服务的内存缓存(clearByService):v2.0.4,该操作地址为“http://serverip:port/PBS/rest/admin/memCache/clearByService”,参数列表如下:




















  • name:(必须)需要清除内存缓存的服务名称;






  • port:(必须)需要清除内存缓存服务所在端口号;





响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。

















~改变ArcGISDynamicMapService数据源的附加参数(changeParams):v2.0.5,该操作地址为“http://serverip:port/PBS/rest/admin/ArcGISDynamicMapService/changeParams”,参数列表如下:



















响应内容:JSON字符串,格式:{"success"": [ture|false],"message": [detail message]}。








后续版本将增加更多操作…

















六、服务使用








启动好的服务都会暴露出来两个REST服务地址(v3.0版本开始支持WMTS规范), 









image_thumb2

















ArcGIS REST URL可供所有ArcGIS客户端API,包括Javascript/Flex/Silverlight/iOS/Windows Phone/Android,以及即将推出的ArcGIS Runtime直接使用;由于OpenLayer中可通过ArcGIS93REST图层直接加载ArcGIS的服务,因此PBS服务也可直接被OpenLayers客户端使用;而OGC WMTS URL则供所有支持WMTS规范的客户端使用。








比如在ArcGIS API for Javascript中,我们在地图中添加一个底图图层,Url地址指向PBS发布的某个服务:


























image_thumb[2]

















这样就能直接通过PBS为我们提供的,类似于原生ArcGIS缓存地图服务的Url地址,访问到第三方的底图数据了。开发人员从此免去了在客户端自定义图层,去加载第三方切片的麻烦。比如通过PBS提供的服务,分别在ArcGIS API for Javascript/Flex/Silverlight中调用Google Maps地图。



































image_thumb[4]

















image_thumb[2]

















image_thumb[7] v3.0版本开始,通过PBS发布的所有服务兼容OGC的WMTS规范(目前为1.0.0版本),支持KVP和RESTful两种编码方式。下图为不同客户端(ArcMap,OpenLayers,ArcGIS API for Silverlight,SuperMap iClient for Silverlight)分别以WMTS方式加载由PBS发布的MapBox数据源的底图。 
wmts








除此之外,从1.0.6版本开始,PBS增加了风格化的选项,可以在不需要重新切图的情况下(动态地图服务则无需切图),直接改变所有底图服务的视觉呈现效果。目前提供视觉风格选项:灰度图(Gray)和反色图(Invert),用于特殊目的。比如使用灰度图可突出显示业务内容,详见这里








2.0.3版本新增泛黄(tint)与浮雕(embossed)两种效果。


























VisualSytle

















七、格式转换

















v2.0.6版本开始,PBS提供部分数据源格式之间的转换功能。




















  • ArcGIS Cache转换到MBTiles格式:可将ArcGIS的缓存文件(紧凑/松散)转换成单个MBTiles格式文件,方便数据迁移。













    arcgistombtiles

























  • Online Maps转换/下载到MBTiles格式:可将在线地图下载成单个MBTiles格式文件,方便你的方便。整个过程耗时取决于你的网速和在线地图数据源服务器的速度。v2.0.7版本开始,提供按Shapefile文件下载切片功能,对于不规则区域,可大幅减少切片下载数量。类似ArcGIS Server中的Map caching based on feature boundaries,此功能仅对大比例尺有效;请提前对Shapefile文件做要素合并,节点抽希等处理。按Shapefile文件范围下载时,下载进度,结果文件预计大小等信息无效。

















    onlinemapstombtiles 捕获






v2.0.7版本开始,为转换后的MBTiles文件增加了”压缩”选项,如果转换结果中,尤其在大比例尺下,包含大量沙漠,海洋等区域,可大幅减小MBTiles结果文件的体积。具体原理请参考MBTiles规范。例如,存储国内某城市0-17级切片的.mbtiles文件,不勾选”压缩”选项时文件大小220MB,经过”压缩”后的文件大小为150MB。”压缩”过程耗时取决于文件内容的多少,另外请确保磁盘剩余空间大于压缩前文件体积。








上述转换会根据切片数量不同自动增加工作线程数:数据源为ArcGIS Cache时,每个线程处理128×128个切片;数据源为在线地图时,每个线程处理16×16个切片。
























关于PBS的性能

















PBS利用WCF REST框架开发,支持多用户,多并发请求,性能仅受机器硬件限制。初步用Apache JMeter做了测试,在我的笔记本上,通过PBS的REST服务,请求Sqlite数据库中一张22kb的图片,500个并发请求的响应时间在10ms以下:

















image 在磁盘性能更好的服务器上测试,1000个并发请求的相应时间可以在10ms以下。








而实际使用中,单个底图服务达到上千个并发请求的情况还是比较少见的,所以PBS可以满足大多数需求。








从2.0版本开始,PBS增加了内存缓存功能。可将已生成过的切片数据自动缓存在机器内存中,之后可从内存中直接返回该切片,而不是动态生成。








image








2.0.1版本增加对单个服务是否启用内存缓存的控制,并增加输出动态生成切片数量和内存缓存切片数量的信息。

















image








2.0.2版本增加对单一服务清除内存缓存的功能。








只需在Memory Cache菜单下,勾选Enable选项,即可启用内存缓存功能。该特性可显著提高PBS性能,尤其对于动态缓存地图服务功能(影像数据或动态地图服务作为数据源),在几乎不占用cpu资源的情况下,支持的并发数可提高数十倍。该功能利用Memcached完成,它是一个免费的高性能分布式缓存系统(http://memcached.org/)。








默认情况下,Memory Cache会使用64M机器内存来缓存切片数据,达到64M后,会自动替换掉最早的缓存数据。使用机器内存的大小可通过PortableBasemapServer.exe.config配置文件进行配置,只需修改其中MemcachedSize节点的数值即可。








比如对于影像数据作为数据源的动态缓存地图服务功能,在服务器机器上,可配置更多的物理内存(比如4G)供PBS使用。这样一来,只需在第一个客户端访问时生成一次切片数据,后续的请求就可直接从内存中获得切片。以内存方式替代cpu的工作和硬盘的存储空间,使得PBS投入实际生产运行成为可能。








经测试(笔记本环境),对于PBS转发的在线地图服务(Google Maps)中的一张切片,没有使用内存缓存功能时,100个并发请求响应时间平均为10秒左右(和我的网速慢也有很大关系),因为每次请求都需要在线下载该切片;使用了内存缓存功能后,对于同样的一个切片,100个并发请求响应时间平均为2毫秒(该切片已在内存中的情况,下同),500个并发平均响应时间为6毫秒,1000个并发平均响应时间为200毫秒左右。在内存更好的服务器上测试,可获得更理想的结果。

















总结
























对于ArcGIS用户来说,通过PBS,可直接加载第三方的离线数据源(MAC/MBTile),而不需要按照ArcGIS的切图规则重新组织切片;可将动态地图服务转换成动态缓存地图服务,无需自己在客户端API中自定义图层;可使用多种数据源;








对于OpenLayers用户,可使用更多的,内容更丰富的底图数据;








Portable Basemap Server可装入U盘带走,在任何具有.NET Framework 4.0环境的机器上直接运行,无需安装。一个U盘即可提供多种底图,方便开发者使用;








后续计划加入更多数据源,比如本地影像数据(已加入),以及为更多客户端提供支持。

















下载地址

















2012.11.14:Portable Basemap Server已在CodePlex上开源,LGPL协议。








http://www.arcgis.com/home/item.html?id=48bf53da123e442ab8ac9aed52747552








如果大家对于软件有任何意见或建议,欢迎在此篇博客中留言回复。

2011年6月29日星期三

在路上

    去年差不多这个时候刚好完成从西安到北京的骑车旅行,时间过去整整一年了。虽然当初有朋友说你写点什么让大家围观一下吧,毕竟自行车挺不容易的,但是由于自己比较懒,至今也没有写点东西。但其实就这件事本身来说什么都不用写。写出来的文字本身证明不了任何东西,就像骑车这件事本身也证明不了其它事情一样。
    不明真相的同学总觉得骑这么长距离肯定是具有很强耐力的人才能做到的事情,其实不是,从小跑1000米都让我觉得是一件万分痛苦和艰难的事情,每天100多公里的路程并不需要你想象中那么非凡的耐力;还有的同学可能觉得路程这么长很容易迷路,能够顺利到达终点一定得有很强的规划能力和实践经验,其实也不是,沿着国道走,凡是岔路口总有硕大的指路牌告诉你方向,再加上一张可以问路的嘴巴,想迷路确实是一件不容易的事情。
    所以,重要的其实是在路上这个过程。和其他事情一样,这个过程只属于经历过的人。如果有机会,请你一定要尝试,因为《Into the Wild》里面说过,the core of mans' spirit comes from new experiences。
    生活就是一本书。以前用一种读者的心态在说,书里面的人有的可爱,有的可恨,但大多数人都已经不会再敢爱敢恨;现在自己也成了这本书中的一个角色,明白了为什么总是旁观者轻(松)。生活在有些时候确实让我们觉得无力,或者不想反抗,但这都是因为你已经偏离了自己想要走的那条路。走在路上时间长了,难免会因为不堪负重而丢掉一些东西,但不时地回头看看并提醒自己,别忘记出发时的美好心态和憧憬,这样你走过的路越多,看到的美丽风景就越多。

西安到北京骑行路线(2010.6.16-2010.6.27)
Day1:西安-->渭南市-->华阴 128.34km
Day2:华阴-->潼关-->灵宝 89.7km
Day3:灵宝-->陕县-->三门峡-->渑池 117.83km
Day4:渑池-->义马-->新安-->洛阳-->白马寺-->偃师 113.53km
Day5:偃师-->巩义-->荥阳-->郑州 138.51km
Day6:郑州-->新乡-->淇县 123.59km
Day7:淇县-->鹤壁-->安阳-->磁县-->邯郸-->永年 148.72km
Day8:永年-->邢台-->内丘-->高邑 104.7km
Day9:高邑-->元氏-->石家庄-->正定-->新乐 119.03km
Day10:新乐-->定州-->望都-->保定 111.80km
Day11:保定-->徐水-->定兴-->高碑店-->涿州 95.35km
Day12:涿州-->北京 91.12km

bike from xi\'an to beijing西安到北京骑行

2011年6月24日星期五

2011 Esri中国开发者大会讲座:ArcGIS API for Windows Phone进阶视频

内容介绍:
  • 快速入门
  • 界面设计
  • 触摸 & 手势
  • 应用程序执行模型(Execution Model)
  • 位置服务
  • 离线应用(全离线演示从1小时17分钟开始)

2011年6月11日星期六

Windows Phone 7 解锁/破解/越狱步骤 NODO版本有效

  为什么要解锁windows phone机器?不解锁只能通过zune marketplace来下载和安装市场上的软件,解锁后才能用windows phone developer tools里的application deployment工具将自己的.xap程序部署到手机上。当然只是临时做测试用,有条件还是需要注册微软每年99美元的开发者账号,来绑定自己的机器以部署程序吧,大家懂的。
  现在国内市面上还没有windows phone行货,有消息称最早在今年8月份行货机器有望上市。目前windows phone有4个版本,去年发布时最初的第一个版本7.0.7004.0,今年2月份的第一个更新版本7.0.7008.0,4月份的NODO版本(7.0.7390.0),和最新的7.0.7392.0安全更新版本。这两天拿到了htc的hd7机器做测试,是未解锁的NODO版本,无奈中文资料比较少,只好上神坛xda找答案。
  目前wp的解锁工具只有一个,就是http://www.chevronwp7.com/放出的ChevronWP7,但是该工具只适用于7004和7008版本,7390以上版本无效,必须刷回之前的版本才能解锁。解锁之后需要额外的步骤,保证zune同步时机器不会重新被锁,并且升级到NODO版本后,解锁依然有效。现将完整步骤整理如下(主要参考http://forum.xda-developers.com/showthread.php?t=1043000此贴中TechJunkiesCA的回复)。

一、将7390版本刷回最初的7004版本(如果你是7004或7008版本,可跳过此步骤)

  按照http://forum.xda-developers.com/showthread.php?t=876451这个帖子中的说明,首先确定手机的原始运营商:

In order to identify your HD 7 phone ROM version see in your phone settings>about>more information:
Firmware revision number: 2250.09.15401.728
Your phone ROM version will be: 1.54.728.01
The characterisric value (CV) is: 728
Your Operator name and CIDs i.e.: hTC_Asia_SEA operator, with CIDs HTC__044, HTC_621, HTC__622, HTC__038 can be found with this CV from following classification:
1. 666 : BellMobilty operator, with CID BM___001
2. 707: hTC_Asia operator, with CIDs HTC__044, HTC_621, HTC__622, HTC__038
3. 728: hTC_Asia_SEA operator, with CIDs HTC__044, HTC_621, HTC__622, HTC__038
4. 401: HTC_Europe operator, with CIDs HTC__001, HTC__203, HTC__102, HTC__032, HTC__405, HTC__304
5. 207: O2_DE, with CID O2___102
6. 206: O2_UK, with CID O2___001
7. 841: Telstra operator, with CID TELST001
8. 901: TIM operator, with CID TIM__401
9. 531: TMOUS operator, with CID T-MOB010

  这台机器Firmware最后三位数字是207(对应O2_DE),可得知是销往德国(de)的o2机器。找到帖子下面贴出的对应rom,RUU_Schubert_O2_DE_1.61.207.01_Radio_5.52.09.16_22 .33a.50.10U_by_ansar,下载,解压。
1、长按电源键,关机
2、按住下音量键不放,按电源键,进入bootloader(三色屏)模式(此时可松开下音量键)
3、用usb线将手机与电脑连接
4、等待windows系统自动查找并安装驱动程序
5、驱动安装完成之后,确保手机屏幕上白色屏部分显示“usb”字样(驱动安装之前是“serial”)
image
6、此时可以运行下载好的ROMUpdateUtility.exe(ruu工具),严格按照屏幕提示操作
  如果你之前用过HTC的RUU刷windows mobile机器或者刷android机器,那么最后一步应该非常熟悉。刷机完成之后,检查OS Version应当是7004或者7008。

二、利用ChevronWP7对手机进行解锁

  首先到http://forum.xda-developers.com/showthread.php?t=938106这个帖子中下载必要的工具:Windows Phone 7 Developer ToolsChevronWP7工具TCPView for Windows。WPDT对于开发者来说不是问题,肯定已经安装了(否则你需要先安装vs2010,然后安装WPDT)。下载ChevronWP7工具,压缩包中会包含ChevronWP7.exe,ChevronWP7.cer和ChevronWP7.reg三个文件。之后可以开始:
1、在电脑上运行ChevronWP7.reg。会将注册表中[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\WindowsPhone\ProxyPorts]的DeviceReg一项值改为dword:000069c5
2、在手机上安装ChevronWP7.cer证书。可将ChevronWP7.cer做为附件发送到自己的邮箱,然后在手机上用浏览器打开该附件,屏幕会显示黑底的小白盾,继续点击“Install”即可
3、确保你机器的443端口没有被占用。运行tcpview.exe工具,查看Local Port一列中显示为https的程序(会占用443端口),全部结束之
4、将手机设置为飞行模式
5、将手机利用usb线与电脑连接,使用Zune软件进行非guest方式同步。如果没有安装Zune(windows自己的itunes),需要提前安装。如果同步方式那块显示的是“Guest Sync”,点击之,运行一下向导,使得你的计算机变成该手机的主要同步电脑(非guest方式同步)
6、以管理员身份运行ChevronWP7.exe进行解锁。确保手机屏幕没有锁定(可在设置中将桌面锁定设为never),处于开始画面;以管理员身份运行ChevronWP7.exe,将两个方框打钩,点击unlock。顺利的话不到5秒钟即可完成,按钮会变成relock。此时最好不要拔出usb线,接着进行下面的第三步。
  至此已完成解锁。可利用WPDT自带的Application Deployment工具,在手机屏幕处于非锁定的状态下,部署任意的.xap文件了。
image

三、确保下次用Zune同步时,手机不会重新被锁

  仅仅利用ChevronWP7.exe解锁后,如果断开与usb线的连接,以后再次插入usb,用Zune同步后,机器可能再次被锁,还需要进行解锁步骤。为防止此情况发生,需要进行以下步骤,确保以后用Zune同步时,机器不会被再次锁定。下面的步骤只适用于htc机器(因为touchxplorer只能在htc机器上运行),其他手机请参考这里
1、按照http://forum.xda-developers.com/showthread.php?t=913748此贴中的说明,依次下载TouchXplorerHTC Connection Setupunlockit(其实是XBMOD.Files.Deployer)三个.xap文件,分别解压并且将它们安装到手机中
2、在手机上运行XBMOD.Files.Deployer。会将CustClear.provxml和restoreCustClear.provxml两个文件解压到My Documents/My Ringtones目录下
3、运行TouchXplorer工具(wp里的资源管理器),将上述两个文件拷贝到\Windows目录下
image
4、运行HTC Connection Setup工具,点击ok,此步骤可选。如果你的手机里有sim卡,需要执行此步,否则可跳过
  至此已经完成了所有的步骤。可以利用Zune同步后将你的手机升级至最新的7392 NODO版本,也不会被再次锁定了:)
image

如何部署大于64M的.xap文件到手机上?

  下载了大名鼎鼎的The Harvest(xap大小86.4m)想尝试一下,但用Application Deployment部署时会提示“Error-设备没有连接”。搜索xda,发现有人说在更新NODO后,大于75M的xap便无法部署了,大家纷纷跟帖表示确有此问题。但万能的xda网友toothfish再次给出解决办法
1、备份你的xap,以防万一
2、用解压缩工具打开xap文件,将其中体积较大的一些文件,比如Content文件夹解压缩出来,并从压缩包里删除之
3、记下WMAppManifest.xml文件中的productID的值(一个guid)
4、将修改过后的xap(体积应该小于64m)部署到机器上
5、使用Windows Phone Device Manager自带的Touchexperience工具,将第二步中分离出来的那部分文件,拷贝到手机的Applications\Install\"Product ID"\Install目录中,注意维持与原xap文件中同样的目录结构
6、你已经将大xap文件部署成功了~
  其实原理比较简单,做过windows phone开发的朋友都知道,一般会将程序中用到的资源文件,比如一些媒体文件,以Content方式编译到xap中单独的文件夹里;而windows phone程序部署的真正过程也如上所示,只是将xap解压到了特定的文件夹中。因此便可以用上面的办法来移花接木了。
  还要提醒一点,我的机器上已经安装了mango sdk,所以会和Windows Phone Device Manager程序有冲突,因此我用Advanced Explorer来完成拷贝文件到手机中的过程。
image

  无法部署大xap的情况好像只会在机器上既装了mango sdk,并且手机版本为NODO时才会出现,否则(比如将手机还原到7008版本)应当可以直接部署成功。