【GISER && Painter】矢量切片(Vector tile)番外一:Proj4js

說明:番外篇是對正篇矢量切片(Vector tile)中提到的一些值得繼續延伸的關注點繼續進行探索和學習,所涉及的內容以解決實際問題爲主要導向。

一、新的需求?

  在完成了矢量切片的工作後,新的需求出現了, 也就是我在上一篇中所提到的:我所擁有的歷史數據都是基於某一個特定的Projection,那麼如何利用GeoServer以及OpenLayers去制定一個針對特定座標系的矢量切片呢?

  其實很簡單,回顧一下我們上一篇文章是如何實現並調用矢量切片的:

  發佈數據 --> 配置參數【選擇數據格式(GeoJSON/TopoJSON/MapBox Vector tile(MVT))、選擇tile size(256*256)、選擇gridsets】 --> 預覽數據 --> OL3調用數據

  那在哪一個環節會出問題?

  1)數據發佈和切片的生成:你可以把數據想象成爲蛋糕,不同座標系下的數據就是不同形狀的蛋糕,按照同一種方法去切割不同形狀的蛋糕,那肯定會出問題。

面對不同形狀的蛋糕,也應該採取不同的策略去制定切法

  2)數據調用:每一塊不同形狀的蛋糕在完成切片後,留下的最小存在單元的形狀也肯定是不一樣的,如果是橢圓,所切出來的小塊肯定是有着平滑邊緣的蛋糕塊,而五角星的每一小塊很有可能是有着尖銳邊緣的蛋糕塊,所以我們想要把切出來的蛋糕塊完美的放在某一個容器中端出來,那這個容器肯定需要和蛋糕塊的形狀契合,所以,在調用數據的時候,也需要爲數據提供一個契合的數據框架。

  通過上述分析,我們已經知道了應該在哪裏進行補充工作了,那麼接下來就讓我們一起去實現吧。

二、基於某一個特定的座標系實現的矢量切片

   首先在發佈數據時,我們應當找到當下準備發佈數據的座標系信息,你可以通過ArcGIS加載該數據來查看,在此我使用的是深圳市綠道數據,基於EPSG:4490,即China Geodetic Coordinate System 2000

  1) 進入GeoServer的發佈數據頁面

  還記得在發佈數據過程中,爲切片數據配置的頁面嗎?我們需要在頁面上完成數據格式(GeoJSON/TopoJSON/MapBox Vector tile(MVT))、tile size(256*256)、gridsets等配置。

  但這裏要注意的是,你會發現在gridset這一欄裏默認的只有EPSG:4326和EPSG:900913的切片格網方案,而我這裏使用的數據是EPSG:4490,蛋糕形狀變了, 切的刀法也應該有所變化。所以我們需要針對EPSG:4490定製一個切蛋糕方案:

  2)自定義gridset

  從GeoServer面板左邊的菜單欄中進入Tile Caching的Gridsets子菜單,然後在Gridsets的管理頁面中選擇新建一個gridset,接下來你就能看到這樣一個頁面:

   

  在這個頁面,你有很多參數需要配置,配置完之後點擊保存即可:

  - Name

  - Coordinate Reference System : 與之對應的座標系編碼

  - Gridset bounds:範圍(會影響到切片的參數)

  - tile size:256*256

  - Tile Matrix Set:根據你的數據和需要設置縮放級別

   

  最後,在上一個配置參數的頁面,將新配置的gridset添加進去

  

  好了,我們現在已經用合適而恰當的方法把蛋糕切好了,接下來我們需要爲這些數據蛋糕找到合適的容器。

三、在OL3中自定義座標系

  1)OpenLayers中的座標系

  在OpenLayers3中,提供了好幾種默認已經定義好的座標系,這其中就有我們熟悉的EPSG:4326,EPSG:900913 or EPSG:3857等等,能夠保證一般情況下的使用,但對於特定需求,可能就需要藉助外力的幫助,而這個外力就是:Proj4js

  2)Proj4js

  在github上,關於Proj4js的定義是這樣的:

  Proj4js is a JavaScript library to transform point coordinates from one coordinate system to another, including datum transformations. 
  // Proj4js主要是一個用來將點座標從源座標系統轉換到另一個目標座標系統的JS庫,包括基準轉換
  Originally a port of PROJ.4 and GCTCP C it is a part of the MetaCRS group of projects.
  // 本項目起源於PROJ.4和GCTCP C

  PS:定義中提到的基準轉換,應該是大地測量學裏面的術語,我也不是很瞭解,稍微查了一下資料,在此作爲冷知識補充一下:

  我們通常所說的座標系統,是由座標系和基準構成的,所謂的基準指的是爲了描述空間位置而定義的點、線、面,在大地測量中,基準指的是描述地球形狀的地球橢球參數。

  回到正題,這裏是Proj4js在github中的地址:https://github.com/proj4js/proj4js, proj4js中提到了兩種用途:

  1)轉換座標點;

  //其中fromProjection是源座標系,toProjection指的是目標座標系
  //如果你沒有提供fromProjection,則默認fromProjection爲WGS84座標系
  //fromProjection,toProjection等參數可以是ol中的projection對象,也可以是一個WKT String

  proj4(promProjection,toProjection,coordinates);

  2)定義命名一個自定義座標系統

  //定義一個新的座標系統
  proj4.defs('WGS84', "+title=WGS 84 (long/lat) +proj=longlat +ellps=WGS84 +datum=WGS84 +units=degrees");

  需要補充一點,在Proj4js中已經預定義了幾種projection:

  - 'EPSG:4326' or 'WGS84'

  - 'EPSG:4269'

  - 'EPSG:3857' or 'EPSG:3785' or 'GOOGLE' or 'EPSG:900913' or 'EPSG:102113'

 

  根據文檔中的介紹,我們使用Proj4js去定義一個新的ol3中的projection對象:

  a)首先,和所有的JS庫一樣,請不要忘記在頁面完成對庫的引用,

 <script type="text/javascript" src="lib/proj4js/dist/proj4.js"></script>

  b)其次,在你的JS文件中加入以下代碼:

  function loadVectorTile_4490(){
   //定義EPSG:4490,具體的字符串參數你可以在:http://epsg.io中查詢到,只需輸入你的projection的EPSG碼或者座標系的名稱
   //即可獲得相應座標系的字符串參數,直接將其複製到代碼中即可

   proj4.defs("EPSG:4490","+proj=longlat +ellps=GRS80 +no_defs");
   //獲得定義的座標系
   var projection4490 = new ol.proj.get('EPSG:4490');
   //給定義的座標系統限定範圍,此處4490的範圍與4326類似,因爲他們的單位都是degree
   projection4490.setExtent([-180,-90,180,90]);

   var layerName2 = 'szdata:greenway';
     var layerProjection2 = '4490';      
   //矢量切片圖層
     var vectorTile_GreenWay = new ol.layer.VectorTile({
         title:"深圳綠道-VectorTile",
         style: new ol.style.Style({
            stroke: new ol.style.Stroke({
                color:'#548B54'
            })
     }), projection: projection4490,
     //矢量切片數據 source: new ol.source.VectorTile({
       projeciton: projection4490, format: new ol.format.GeoJSON(),
tileGrid: ol.tilegrid.createXYZ({
          extent: ol.proj.get('EPSG:4490').getExtent(),
          maxZoom: 13 }),
      tilePixelRatio:1,
      
//發出獲取切片的請求
      tileUrlFunction: function(tileCoord){
                return '/geoserver/gwc/service/tms/1.0.0/'
                +layerName+'@EPSG%3A'+layerProjection+'@geojson/'+(tileCoord[0]-1)
                + '/'+tileCoord[1] + '/' + (Math.pow(2,tileCoord[0]-1)+tileCoord[2]) + '.geojson';
            }
      })
    });

    //需要注意的是,要給view設定一個合適的Projection屬性,不然數據無法正常顯示
    var map = new ol.Map({
        target: 'map',
   layers: [
          new ol.layer.Tile({
            source: new ol.source.OSM();
          }),
          vectorTile_GreenWay
        ],

   view: new ol.View({
            //view中的projection
             projection: projection4490,
              center: [114.15, 22.65]

        })

    });
  }

  c) 其實最後的實現很簡單,只不過在上一篇文章的內容中添加了一個Proj4js定義新座標系的內容,實現過程也比預想要順利,因此作爲一個小番外添加進來,也是對上一篇文章末尾提到的問題進行一個補充。實現結果如下:

 

  

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