1. 程式人生 > >Leaflet,OpenLayers3載入ArcGIS切片(png格式,Exploded鬆散型)

Leaflet,OpenLayers3載入ArcGIS切片(png格式,Exploded鬆散型)

需求

  做了一個簡單的WebGIS應用,不想因為載入切片就安裝一臺GIS伺服器。於是想直接訪問圖片的方式來載入地圖。

需解決的問題

  leafletjs目前是不能夠直接載入ArcGIS服務切片的,但可以藉助esri-leaflet外掛來載入。如果沒有安裝arcgis server將切片進行釋出時,這些切片還是無法進行訪問,這個外掛是面向arcgis服務應用開發的。

  leafletjs自身可以通過類似於下面這種方式直接載入地圖切片:
  L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png')
  但ArcGIS切出了的切片不符合這樣的格式,他們是這樣的:
  這裡寫圖片描述


  那麼更改切片資料夾名稱、切片名稱顯然不太合適。

解決方法

  ArcGIS切片資料夾和檔名都是以16進位制的形式命名的,因此我們通過重寫x,y的方式,就是將原來的x,y更改為以16進製表示的形式就可以了。

  其中:
  切片資料夾都是以R開頭的,表示row,也就是y;
  切片名稱都是以C開頭的,表示col,也就是x.

  通過leafletjs的L.TileLayer類的getTileUrl方法:

L.TileLayer = L.TileLayer.extend({

        getTileUrl: function (tilePoint) {

            var oo = "00000000"
var xx = tilePoint.x.toString(16); xx = "C" + oo.substring(0, 8 - xx.length) + xx; var yy = (tilePoint.y - Math.pow(2, tilePoint.z - 2)).toString(16);//這裡減去偏移值 yy = "R" + oo.substring(0, 8 - yy.length) + yy; return L.Util.template(this._url, L.extend
({ s: this._getSubdomain(tilePoint), z: "L" + tilePoint.z, x: xx, y: yy }, this.options)); } });

接下來和普通載入切片的形式一樣:

var river_layer = L.tileLayer('http://192.168.9.41/ywwry/data/_alllayers/{z}/{y}/{x}.png');
var riverLayer = L.layerGroup([river_layer])
map.addLayer(riverLayer)
riverLayer.setZIndex(1)

載入完成!

注意事項

參考系

  這裡我載入的是座標系為EPSG4490的地圖切片,所以我們在定義map時需要設定為EPSG4326.兩者的切片原點都是一樣的。如果是其他參考系,根據情況進行修改。

切片級別修改

  有時候切片資料夾命名不正確,比如
  這裡寫圖片描述
  
  裡面的資料夾L00在這裡實際上表示的是我的第7級。
  如果是這樣,可以對資料夾名稱進行修改,工作量不大。也可以在重寫getTileUrl方法時修改程式碼。

切片載入時出現的行列號偏移

  這個問題不容易被發現,而這裡就是這種情況。 我將行列號表示為十六進位制,並以arcgis切片的格式進行格式化,但總是無法載入圖片。我發現當第九級時切片的y軸方向偏移了128,第八級時是64,第七級時是32.很有規律,那麼我使titlePoint.y減去這個偏移值Math.pow(2, tilePoint.z - 2)就可以了。
  我不知道其他人載入時會不會出現這個問題,如果出現了就應該靈活處理下。

OpenLayers3 載入切片

   補充時間2016年10月19日08:42:07

  現將Leaflet替換為OpenLayers3,載入同樣的切片。

    var riverLayer = new ol.layer.Tile({
        source: new ol.source.XYZ({
            projection: 'EPSG:4326',
            maxZoom: 17,
            minZoom: 7,
            tileUrlFunction: function(tileCoord){
                var oo = "00000000";
                var zz = tileCoord[0];
                var z = "L" + zz;
                var xx = tileCoord[1].toString(16);
                var x = "C" + oo.substring(0, 8 - xx.length) + xx;
                var yy = (-tileCoord[2] - 1).toString(16); //注意此處,計算方式變了
                var y = "R" + oo.substring(0, 8 - yy.length) + yy;
                return 'data/_alllayers/' + z + '/' + y + '/' + x + '.png';
            }
        })

    })

    map.addLayer(riverLayer);

OpenLayers3 載入這種切片與Leaflet思路是相同的,需要注意的是y軸方向上的變化。比如var yy = (-tileCoord[2] - 1).toString(16); 如果不減去1的話,就發現載入的切片恰好偏移1個切片的大小。

糾正前:
river切片偏移了一個切片的距離

糾正後:
這裡寫圖片描述

一定要注意觀察,靈活變通。