原文地址連接:http://blog.sina.com.cn/s/blog_921dfd9b010165i3.html
圖層是空間數據的載體,如果你對ArcGIS Server稍有了解的話,就能明白API裏不同類型的圖層對應了服務器端發佈的不同Service,可以分成兩大類:靜態圖層和動態圖層。
靜態圖層泛指緩存過的地圖服務,除非服務端刪除或更新緩存,否則客戶端請求的數據永遠是固定不變的,而動態圖層正好相反,服務器根據每個請求動態的生成數據,一靜一動各有用途。
表3-2-1 不同類型圖層的繼承關係
AGSLayer是所有圖層的基類,聲明瞭空間參考、最大範圍、初始範圍、單位和圖層委託等基本屬性,還有圖層加載的相關方法。
表3-2-2圖層類的屬性和方法
1 靜態圖層
靜態圖層根據一定的規則提前生成緩存,這樣客戶端的請求就能直接調用緩存地圖切片,顯著提高了地圖請求的響應速度。常常用於那些使用頻率高、更新週期長的基礎地理數據,包括大家常常用到的電子地圖、地形圖、衛星影像圖等。
AGSTiledLayer繼承自AGSLayer,同時也派生出不同類型的靜態圖層:
表3-2-3 靜態圖層的繼承關係
在MVC結構中,AGSTiledLayer屬於Model角色,對應的View角色是AGSTiledLayerView。其中實現了關鍵的異步獲取切片數據操作,並獲取到切片服務的緩存規則:
表3-2-4 靜態圖層的方法和屬性
注意:如果靜態服務圖層的空間參考與MapView的不一致,就無法顯示。
1.1 切片地圖服務圖層(AGSTiledMapServiceLayer)
切片地圖服務圖層是最常用的服務,ArcGIS在線提供了一系列,其切片規則(tiling Schema)裏描述了切片的尺寸、格式、比例尺、級別等信息。
“雖然圖層已經初始化並添加到地圖中,但切片信息還是空值?”,建議先判斷加載成功與否,尤其是在網速不好的情況下:
1.2 微軟Bing服務圖層(AGSBingMapLayer)
由於Esri與微軟之間的合作關係,保證了ArcGIS用戶也能使用最新的微軟Bing全球影像地圖服務,當然這也是靜態服務,加入用戶的密匙(在ArcGISServer Manager頁面可獲取)就能使用:
- NSString* bingMapsKey = @"--your--key--";
- AGSBingMapLayer* layer = [[AGSBingMapLayeralloc]initWithAppID:bingMapsKeystyle:AGSBingMapLayerStyleAerial];
*Bing服務空間參考爲橫軸Web摩卡託:
WGS1984 Web Mercator (Auxiliary Sphere) ,WKID=102100:
1.3 OSM服務圖層(AGSOpenStreetMapLayer)
Esri與OpenStreetMap之間也建立了合作關係, ArcGIS用戶同樣也能使用OpenStreetMap全球矢量地圖服務:
*OpenStreetMap服務空間參考爲橫軸Web摩卡託:
WGS1984 Web Mercator (Auxiliary Sphere) ,WKID=102100:
1.4 自定義切片圖層(Custom TiledLayer)
國內流行的切片地圖還有:谷歌地圖、百度地圖、MapABC、天地圖等,各家地圖的切片策略有差異但原理相同,瞭解其切片策略信息後,繼承AGSTiledLayer拓展自定義切片圖層 (Custom TiledLayer),就能正常使用該切片地圖。
Esri提供了一個訪問本地切片(png或jpg)的類 “OfflineTiledLayer”,可以作爲我們設計自定義切片圖層的參考,包含3部分:切片圖層對象,切片數據解析委託和切片請求操作。下面的流程示意圖能看出自定義切片加載的整個過程:
圖3-2-6 自定義切片圖層的調用流程
“OfflineTiledLayer“繼承了AGSTiledLayer,並重寫了切片信息(tileInfo)和切片獲取方法(retrieveImageAsyncForTile),其初始化方法(initWithDataFramePath)也很簡單:
- //繼承了AGSTiledLayer
- @interface OfflineTiledLayer :AGSTiledLayer {
- ...
- }
- //自定義切片服務元數據
- @implementation OfflineTiledLayer
- -(AGSUnits) units { //todo }
- -(AGSSpatialReference*) spatialReference {//todo }
- -(AGSEnvelope*) fullEnvelope { //todo }
- -(AGSEnvelope*) initialEnvelope { //todo }
- -(AGSTileInfo*) tileInfo { //todo }
- (NSOperation*)retrieveImageAsyncForTile:(AGSTile*)tile {
- //todo }
- //初始化方法-path:切片路徑
- - (id)initWithDataFramePath:(NSString*)patherror:(NSError**)outError;
- ...
- @end
初始化方法中需要輸入“切片文件路徑”,下圖的示例數據是10.0版本的鬆散型(Exploded)切片緩存,切片服務元數據就保存在conf.cdi和conf.xml兩個XML文件中,其中conf.cdi記錄了地圖全圖範圍、而conf.xml記錄了空間參考、切片格式等信息,其中和切片組織(LODInfos)對應了_alllayers目錄下的級別(L)-行號(R)-列號(C),簡單理解就是用指定網格按指定比例尺一層層的把地圖切成規則的圖片矩陣,建立起了網格與切片文件的對應關係,使用時按網格檢索切片文件,並動態拼接起來。
*關於切片規則的詳細介紹,請參考網上其他資料。
圖3-2-7 鬆散型切片的組織結構
1. 解析切片元數據:
“OfflineCacheParserDelegate“負責從元數據(conf.cdi和conf.xml)中解析出自定義的切片信息並構建出關鍵的AGSTileInfo對象:
- - (id)initWithDataFramePath:(NSString *)path error:(NSError**) outError {
- if (self = [super init]) {
- self.dataFramePath = path;
- //解析 conf.cdi
- NSString* confCDI = [[NSBundlemainBundle] pathForResource:@"conf" ofType:@"cdi"inDirectory: _dataFramePath ];
- NSXMLParser* xmlParser = [[NSXMLParser alloc]initWithContentsOfURL:[NSURL fileURLWithPath:confCDI]];
- OfflineCacheParserDelegate*parserDelegate = [[[OfflineCacheParserDelegate alloc] init] autorelease] ;
- [xmlParsersetDelegate:parserDelegate];
- [xmlParser parse];
- [xmlParser release];
- //解析 conf.xml
- NSString* confXML = [[NSBundlemainBundle] pathForResource:@"conf" ofType:@"xml"inDirectory: _dataFramePath];
- ...
- }
以下是XML元數據的具體解析方法:
- -(void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementNamenamespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName
- {
- if ([elementNameisEqualToString:@"LODInfo"]){
- self.lod = [[[AGSLODalloc]initWithLevel:_level resolution:_resolution scale:_scale] autorelease];
- [self.lods addObject:_lod];
- }else if ([elementNameisEqualToString:@"CacheInfo"]){
- _tileSize = CGSizeMake(_tileWidth,_tileHeight);
- self.spatialReference =[[[AGSSpatialReference alloc] initWithWKID:_WKID WKT:_WKT] autorelease];
- self.tileOrigin = [[[AGSPointalloc] initWithX:_tileOriginX y:_tileOriginYspatialReference:_spatialReference] autorelease];
- self.fullEnvelope = [AGSEnvelopeenvelopeWithXmin:_xmin
- ymin:_ymin
- xmax:_xmax
- ymax:_ymax
- spatialReference:_spatialReference];
- self.tileInfo = [[[AGSTileInfoalloc] initWithDpi: _dpi
- format:_tileFormat
- lods:_lods
- origin:_tileOrigin
- spatialReference:_spatialReference
- tileSize:_tileSize] autorelease];
- }
- }
2. 請求和獲取切片數據:
“OfflineTileOperation“按照地圖所請求AGSTile的level, row, column參數獲取本地切片圖片文件,將其填充到Image屬性:
- //根據 Level, Row,Column獲取切片
- @try {
- //Level ('L' followed by 2 digits)
- NSString *decLevel = [NSStringstringWithFormat:@"Ld",self.tile.level];
- //Row ('R' followed by 8hexadecimal digits)
- NSString *hexRow = [NSStringstringWithFormat:@"Rx",self.tile.row];
- //Column ('C' followed by 8hexadecimal digits)
- NSString *hexCol = [NSStringstringWithFormat:@"Cx",self.tile.column];
- NSString*dir = [_allLayersPathstringByAppendingFormat:@"/%@/%@",decLevel,hexRow];
- //查找PNG格式切片
- NSString *tileImagePath =[[NSBundle mainBundle] pathForResource:hexCol ofType:@"png"inDirectory:dir];
- ...
- }
- @catch (NSException *exception) {
- NSLog(@"main: Caught Exception%@: %@", [exception name], [exception reason]);
- }
- @finally {
- //Invoke the layer's action method
- [_target performSelector:_actionwithObject:self];
- }"font-size:10px;color:windowtext;">
*OfflineTiledLayer用來解釋自定義切片服務圖層設計原理,不適合大規模離線使用,因爲鬆散型的切片小文件分發、更新非常耗時,建議採用下一節的AGSLocalTiledLayer接口+切片包TPK壓縮格式。
*加載其他在線切片地圖(百度地圖、天地圖和谷歌地圖)的方法和代碼,我會在後續章節專門做介紹。
1.5 本地切片圖層(AGSLocalTiledLayer)
本地切片圖層(AGSLocalTiledLayer)也叫離線切片圖層,是上一節“OfflineTiledLayer”示例的升級版,其面向的切片緩存數據源是ArcGIS 10.1新推出的切片地圖包(.tpk文件)。如果用localTiledLayerWithName方法加載,會依次遍歷該應用的bundle和Document目錄,意味着如果tpk文件不大,可以直接將其打包在應用的資源文件中分發,如果tpk文件很大,也允許用戶通過Itunes手動加載數據,前者的優點是分發簡單,後者的優點是應用與數據不綁定,自由加載。
切片地圖包(tile package)是緊湊型(compact)切片緩存數據的壓縮包,提高了切片緩存數據的分發效率,可以用10.1桌面“分享爲TPK”,也可以自己手動構建,詳細過程可參考:http://blog.csdn.net/arcgis_mobile/article/details/8048549.