【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定義新坐標系的內容,實現過程也比預想要順利,因此作為一個小番外添加進來,也是對上一篇文章末尾提到的問題進行一個補充。實現結果如下:

 

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM