1

I have a map projected on EPSG:3857. I must add ocean areas around the globe. Areas come from different GeoJSON files that are added via a select. Most of geojson files have a projection WGS84 (EPSG:4326). Some of them have a orthographic projection (those in the Arctic and Antarctic). Via another select I should be able to change view projection (following the example).

I want that layers change their projection according to the view projection chosen. But I failed to do it, as when I change view projection with the code below, the layers remain visible with their own native projection.

My code is

//projection for north pole
proj4.defs("ORTHO","+proj=ortho +lat_0=85.5333333333 +lon_0=-72.53333333339999 +x_0=0 +y_0=0 +a=6370997 +b=6370997 +units=m +no_defs ");

//area style
var defaultStyle =
 new ol.style.Style({
  fill: new ol.style.Fill({
  color: [251,183,82,0.8]
 }),
 stroke: new ol.style.Stroke({
 color: [251,118,74,1],
 width: 1
 })
});  

//layers
/*NON POLAR*/
var source_ALL_NON_POLAR_GEOJSON_IMMA_WGS84 =
  new ol.source.Vector({
  url: 'polar_examples/new/ALL_NON_POLAR_GEOJSON_IMMA_WGS84.geojson',
  format: new ol.format.GeoJSON({
  }),
dataProjection: 'EPSG:4326'
});

/*POLAR*/
var source_ortho_North =
  new ol.source.Vector({
  format: new ol.format.GeoJSON({
  }),
url: 'polar_examples/new/ARCTIC_GEOJSON_FAKE_ORTHOGRAPHICnorth.geojson',
});

var layer_ortho_North =
  new ol.layer.Vector({
  source: source_ortho_North,
  style: defaultStyle,
  name: 'ortho_North',
  visible: true,
});

var ocean_map =
  new ol.layer.Tile({
    source: new ol.source.XYZ({
    url: 'https://services.arcgisonline.com/arcgis/rest/services/' +
    'Ocean/World_Ocean_Base/MapServer/tile/{z}/{y}/{x}'
    }),
  visible: true,
  });
var map = new ol.Map({
    layers: [],
    target: 'map',
    view: new ol.View({
      //projection:'EPSG:3857', //view projection mercator
      projection: "ORTHO", //view projection ortho
      center: ol.proj.fromLonLat([0, 90], 'EPSG:3408'),//ortho center
      //center: ol.proj.transform([-97.6114, 38.8403], 'EPSG:3857', 'EPSG:4326'),//mercator center
      zoom: 2,
      minZoom: 1
    })

//adding layers
  map.addLayer(ocean_map); 
  map.addLayer(layer_ortho_North);
  // map.addLayer(layer_ALL_NON_POLAR_GEOJSON_IMMA_WGS84); 

To test it I used to comment each projection and layer to be added, in order to see what happens (the select switcher are not implemented yet).

Reading about the problem I found that, when getting the source, it is possible to set a new projection type to the GeoJSON file features matching the one used for the map.

new ol.source.Vector({
 features: new ol.format.GeoJSON().readFeatures(source, {
 dataProjection: 'EPSG:4326', //geojson projection
 featureProjection:'EPSG:3408', //view projection
 })
});

However I don't have a clue about what to use as "source" for the readFeatures function. I tried to add the GeoJSON file name but it doesn't work.

1
  • Just use the source you want to transform, for example source_ortho_North.
    – TomazicM
    Jun 10, 2020 at 20:17

1 Answer 1

3

Features and overlays do not automatically reproject if you change the view projection, but you can add some code to update them

    map.getOverlays().forEach(function(overlay){
        var position = overlay.getPosition();
        if (position) {
            overlay.setPosition(ol.proj.transform(position, oldProjection, newProjection));
        }
    });

    map.getLayers().forEach(function(layer) {
        var source = layer.getSource();
        if (source && source.forEachFeature) {
            source.forEachFeature(function(feature) {
                feature.getGeometry().transform(oldProjection, newProjection);
            });
        }
    });

Clearing and refreshing the vector source after changing view projection should also work.

Your arctic data will need a custom loader as OpenLayers is not recognising the data projection

var source_NSIDCEase_GridNorth =
  new ol.source.Vector({
    format: new ol.format.GeoJSON(),
    attributions: ['NSIDCSIPSnorth'],
    loader: function(extent, resolution, projection) {
     var url = 'ARCTIC_GEOJSON_FAKE_NSIDCEASEGRIDnorth.geojson';
     var xhr = new XMLHttpRequest();
     xhr.open('GET', url);
     xhr.onload = function() {
       if (xhr.status == 200) {
         source_NSIDCEase_GridNorth.addFeatures(
           source_NSIDCEase_GridNorth.getFormat().readFeatures(xhr.responseText, {
             dataProjection: 'EPSG:3408',
             featureProjection: projection
           }));
        }
     }
     xhr.send();
   },
  });

Unfortunately using both sets of your data in the same view isn't going to work well. Most of the WGS84 data is outside the range of a polar projection, and the some of the polar data polygons in eastern Russia and the Aleutians cross the dateline and will not display correctly if transformed to a global projection.enter image description here

5
  • Hi Mike, thanks for your answer. I tried the map.getLayers().forEach, but it seems not working. Two questions: 1) for the orthographic projection I don't have any idea of what kind of EPSG should I insert. 2) I tried to simplify the things to project a Ease-Grid North (EPSG:3408) over a EPSG:3857 projection, but still is wrong. I added my codes to the following fiddle (which however gives an error that I don't have on my local machine). But at least you can see the code. Jun 10, 2020 at 22:36
  • jsfiddle cannot load your geojsons as your server doesn't allow cross-origin access, and a cyclic reference in the source object is causing an error when console.log is used in jsfiddle. When I downloaded the geojsons and ran the code locally OpenLayers wasn't recognising the CRS of the arctic geojson so not transforming the features.
    – Mike
    Jun 11, 2020 at 11:47
  • Thanks @Mike, so basically I cannot simply switch between one projection view and another one, as my data will not be reprojected correctly. Am I right? Do you have any suggestion? Jun 11, 2020 at 12:31
  • How well it works will depend on the projection. Because your arctic data has polygons which cross the dateline it will not look good in a projection such as EPSG:3857 or EPSG:4326. You can use a polar or orthographic projection, but they can show no more than half the world so you must check that features are valid in the projection and will need to reload the data from the geojson each time you change projection jsfiddle.net/3eh7951g
    – Mike
    Jun 11, 2020 at 14:56
  • Thanks @Myke, the custom loader works perfectly, and data are loaded correctly on the orthographic projection. Concerning the EPSG:3857 view, the problem with dateline can be solved in QGIS before exporting the geojson file. Jun 11, 2020 at 16:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.