Thursday, April 13, 2017

Open Layers 3 - Playing with Projections

I big issue when plotting GIS maps is the projection of your data. Open layers 3 gives much more flexibility, than Open layers 2 used to do, on that field. With the latest versions of OL3 you can even reproject rasters and tiles on the client side. This is awesome in it?
But how is it working?
Lets go through some example cases.

 Case 1.I am not a mapping geek. I just want to show a map.
This is the simplest case. Just load a tile layer and let ol3 to choose the projection. This would be the EPSG:3857  as most public tile layers services provide their tile data in EPSG:3857. This is OSM, Google, Bing map etc. So ,just to make clear, if you dont provide any projection during map config EPSG:3857 shall be used and any layer we add on map should be reprojected on that projection on client side if needed.

 ------> Here is an example (CASE1). And its fiddle here

 var map = new ol.Map({  
     layers: [  
      new ol.layer.Tile({  
       source: new ol.source.OSM()  
      })  
     ],  
     target: 'map',  
     view: new ol.View({  
      center: [0, 0],  
      zoom: 2  
     })  
    });  


 Case 2.I am a bit more advanced user. So I want to have control of the map projection
Now if you want to give your map a projection other than EPSG:3857 then you have to assign it to the ol.view of your map. In this case there are 2 sub cases.

   - subcase1. I want to project in EPSG:4326
In this subcase there is no special treatment. Just assign EPSG:4326 on the view of your map.


-------> Here is an example (CASE2 - subcase1). And its fiddle here

 var map = new ol.Map({  
  layers: [  
   new ol.layer.Tile({  
    source: new ol.source.OSM()  
   })  
  ],  
  target: 'map',  
  view: new ol.View({  
   projection:'EPSG:4326',//here is your 4326 projection
   center: [0, 0],  
   zoom: 2  
  })  
 });  

- subcase2. I want to project in a projection other than 4326 or 3857 and the projection code I am looking for exist in the epsg.io database.
In this subcase ol3 need an external library to go on. This is proj4js.js (further info and download here)
So we need to follow the steps below.
1. Load the external library within our html page
2. Search for our projection in the http://epsg.io/. Once we find the projection we are looking for  we go to Export --> Proj4js and then we do copy-paste the javascript definition of our projection.



3. Next step is to add the line of code we just copied to our javascript section.
So lets say we are looking for EPSG:2100 which is the National Greek Projection. Then we need to add this line of code:
 proj4.defs("EPSG:2100","+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=-199.87,74.79,246.62,0,0,0,0 +units=m +no_defs");  

So now ol3 is aware about our new projection. It would also be good to add the extent for our new projection, using the following

 var 2100extent= [-34387.6695, 3691163.5140, 1056496.8434, 4641211.3222];  
 proj.get('EPSG:2100').setExtent(2100extent);  

So lets put in all together now. We want our map to be projected on EPSG:2100 and thus all layers added on map to be reprojected on EPSG:2100


 var extent2100 = [-34387.6695, 3691163.5140, 1056496.8434, 4641211.3222];  
  proj4.defs("EPSG:2100","+proj=tmerc +lat_0=0 +lon_0=24 +k=0.9996 +x_0=500000 +y_0=0 +ellps=GRS80 +towgs84=-199.87,74.79,246.62,0,0,0,0 +units=m +no_defs");  
 ol.proj.get('EPSG:2100').setExtent(extent2100);  
 var layer = new ol.layer.Tile({  
     source: new ol.source.OSM()  
   });  
 var map = new ol.Map({  
  layers: [layer],  
  target: 'map',  
  view: new ol.View({  
   projection: 'EPSG:2100',  
    center: [510457.300375, 4150059.924838],  
   zoom: 4  
  })  
 });  


An here is a fiddle

What if I want to add a wms layer to the map with my custom projection???? Do I need to tell ol3 so reproject my wms layer?????

Well, the direct answer is no you dont have to. Unless you want the reprojection to take place on the server side. Which is not normal for myself. Reprojecting on the server side would stretch my server. So as long as I have the option to do it on client and so not heavy-load my server I prefer to do it on client.

So lets go back to the question. You just have to cofigure your WMS layer and add it to your map. Like so:


 var wmslayer = new ol.layer.Image({  
      source: new ol.source.ImageWMS({  
       url: 'http://suite.opengeo.org/geoserver/wms',  
       params: {'LAYERS': 'opengeo:countries'},  
       serverType: 'geoserver'  
      })  
     }) 
map.addLayer(wmslayer);


And here is one more fiddle to see it live

TO BE CONTINUED WITH FEW MORE CASES ..........

Urban Growth Lab - UGLab

Proud to release a first version of the UGLab project .  UGLab is a python open source project capable to execute Urban Growth predictions f...