ArcGIS緊湊型切片讀取與應用1-解析(附源碼)

1.前言

     ArcGIS 發佈的切片服務分爲緊湊型切片和傳統的分散型切片以及最新ArcGIS por新增的矢量切片。傳統的分散型切片面臨的問題是文件個數太多,部署拷貝過程十分的耗時,緊湊型切片是對分散型切片進行壓縮處理的。一個.bundle文件可以存上萬張切片,有利於部署拷貝,.bundlx文件提供切片索引。本教材分爲三個模塊依次是

(1)文件解析。

(2)webgis動態加載緊湊型切片。

(3)緊湊型批量轉分散型。

下面是對緊湊型切片解析的過程,實現使用的c#代碼。

2.解析

    解析過程我是參考github上的一個就node.js實現的開源項目,項目地址:https://github.com/fuzhenn/tiler-arcgis-bundle,現在進入解析過程,在8級切片下面緊湊型文件的切片目錄如下。

TIM截圖20190225135339

     大家可以發現所有.bundlx切片索引文件大小都是81kb,查閱資料發現每個切片索引都存放着128*128個切片的索引地址。但是並不是每個.bundle文件都有128*128個切片,例如1級切片只有4個圖片,其餘位置會爲空字節表示。解析方式就是通過切片的X,Y,Z作爲參數解析出對應的索引文件名稱,然後從索引文件讀取切片的索引位置,最後切片文件中讀取對應字節流,保存成圖片即可,流程如下。

TIM截圖20190225151354

核心實現代碼如下:

1.通過xyz獲取文件名稱與路徑

/// <summary>
/// 查找切片對應的文件路徑
/// </summary>
/// <param name="root">路徑</param>
/// <param name="level">切片等級</param>
/// <param name="rGroup"></param>
/// <param name="cGroup"></param>
/// <returns></returns>
private string getBundlePath(string root,int level, int rGroup , int cGroup ) {
     var bundlesDir = root;
     var l = level.ToString();
     var lLength = l.Length;
     if (lLength < 2)
     {
         for (var i = 0; i < 2 - lLength; i++)
         {
             l = "0" + l;
         }
     }
     l = "L" + l;

    var r = rGroup.ToString("X");
     var rLength = r.Length;
     if (rLength < 4)
     {
         for (var i = 0; i < 4 - rLength; i++)
         {
             r = "0" + r;
         }
     }
     r = "R" + r;

    var c = cGroup.ToString("X");
     var cLength = c.Length;
     if (cLength < 4)
     {
         for (var i = 0; i < 4 - cLength; i++)
         {
             c = "0" + c;
         }
     }
     c = "C" + c;
     var bundlePath=string.Format  (@"{0}\_alllayers\{1}\{2}{3}", bundlesDir,
         l, r, c);
     return bundlePath;
}

2.通過xy獲取索引值

 int packSize = 128;

var rGroup = Convert.ToInt32(packSize * Convert.ToInt32(y / packSize));
var cGroup = Convert.ToInt32(packSize * Convert.ToInt32(x / packSize));

context.index = packSize * (x - cGroup) + (y - rGroup);

3.通過讀取索引文件,根據索引值獲取切片索引位置

/// <summary>
/// 讀取切片
/// </summary>
/// <param name="context"></param>
/// <returns></returns>
private byte[] readTileFromBundleV1(bundlx context)
{
     var bundlxFileName = context.bundlxFileName;
     var bundleFileName = context.bundleFileName;
     var index = context.index;
     using (FileStream file = new FileStream(bundlxFileName, FileMode.Open))
     {
         byte[] buffer = new byte [5];
         byte[] bufferfile = new byte[file.Length];
         file.Read(bufferfile,0,(int)file.Length);
         //讀取bundlx文件存儲該切片的位置
         buffer = bufferfile.Skip(16 + 5 * index).Take(4).ToArray();
         //偏移量
         var offset = BitConverter.ToInt32(buffer,0);
        return readTile(bundleFileName, offset);
     }
}

4.讀取具體切片數據

  /// <summary>
        /// 讀取切片對應字節
        /// </summary>
        /// <param name="bundleFileName"></param>
        /// <param name="offset"></param>
        /// <returns></returns>
        private byte[] readTile(string bundleFileName,int offset)
        {
            using (FileStream file = new FileStream(bundleFileName, FileMode.Open))
            {
                byte[] buffer = new byte[4];
                byte[] bufferfile = new byte[file.Length];
                file.Read(bufferfile, 0, (int)file.Length);
                //獲取bundle具體切片文件字節數
                buffer = bufferfile.Skip(offset).Take(4).ToArray();
                var length = BitConverter.ToInt32(buffer,0);
                byte[] tileData = new byte[length];
               //根據索引和字節數讀出文件位置
                tileData = bufferfile.Skip(offset + 4).Take(length).ToArray();
                return tileData;
            }
        }

3.成果

將字節流保存成.png圖片輸出,對應項目image項目,代碼已經上傳Github,下篇寫一下webgis動態加載緊湊型切片。

image

 

百度網盤鏈接:https://pan.baidu.com/s/1I-Bj3EQSN57pQHvKZ2hBUA   提取碼:lliw

github項目地址:https://github.com/HuHongYong/TilerArcgisBundle

作者:ATtuing

出處:http://www.cnblogs.com/ATtuing

本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接。


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章