Search code examples
openlayersopenlayers-6

problem with rendering tile vector source using the RGF93 / Lambert-93 -- France coordinate system


jsFiddle is given here: here

I am new to Open Layers 6 and I am trying to display Vector tile data on a map based, more or less, on the example given in the Open Layers workshop.

The URL for the vector tile source supplied in the above example code was not working so I am using the Vector Tile Source described in this page. There I read that the source is defined using using the RGF93 / Lambert-93 (EPSG:2154) coordinate system and then, using Google, I found that coordinate system's definition and bounds on this page.

In the code that follows I am using the projection's definition and the projected bounds from that last link.

Even though data do appear on the map, they appear only on the farthest left side of the screen and only at zoom level 2 as shown below:

enter image description here

If I change the zoom level, nothing is plotted on the screen.

The code is given below (see also link to JsFiddle above):

/*
 * Provenance:
 * 
 *     https://cloud.maptiler.com/tiles/v3-2154/
 *     https://epsg.io/2154
 *
 */
const EPSG_2154 = 'EPSG:2154';

proj4.defs(EPSG_2154
           , "+proj=lcc +lat_1=49 +lat_2=44 +lat_0=46.5 +lon_0=3 +x_0=700000 +y_0=6600000 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs");
ol.proj.proj4.register(proj4);





const proj = ol.proj.get(EPSG_2154);
proj.setExtent([-378305.81, 6093283.21, 1212610.74, 7186901.68]);
const extent = proj.getExtent();

console.log('extent is: ', extent);




const key = '7A1r9pfPUNpumR1hzV0k';
const layer = new ol.layer.VectorTile({
    source: new ol.source.VectorTile({
        attributions: [
            '<a href="https://www.maptiler.com/copyright/" target="_blank">&copy; MapTiler</a> <a href="https://www.openstreetmap.org/copyright" target="_blank">&copy; OpenStreetMap contributors</a>'
        ],
        /*
         *    It is important that the Vector Tile Source projection be explicitly declared and
         *    be the same as the view projection, otherwise you get:
         *
         *        https://github.com/openlayers/openlayers/issues/11429
         *
         */
        projection: EPSG_2154,
        format: new ol.format.MVT(),
        url: `https://api.maptiler.com/tiles/v3-2154/{z}/{x}/{y}.pbf?key=${key}`,
        maxZoom: 14
    })
});

const center = ol.extent.getCenter(extent);
console.log('center is: ', center);
const map = new ol.Map({
    target: 'map-container',
    view: new ol.View({
        projection: EPSG_2154,
        center,
        zoom: 2
    })
});

map.addLayer(layer);

My questions are:

  1. why isn't France plotted right on the center of the map given that I am using the exact "projected bounds" as defined here and setting them on the projection using setExtent and given that I am also using ol.extent.getCenter to obtain the center?
  2. why do data only appear at zoom level 2 and disappear altogether at zoom levels 1 or 3?
  3. what should I do to get the map of France nicely centered and zoomed in the middle of map?

Solution

  • Just as some of the MapTiler examples use a TileJSON (see https://github.com/mapbox/tilejson-spec/tree/master/2.2.0) for raster tiles, there are also TileJSONs for vector tiles, for example the style https://api.maptiler.com/maps/basic-2154/style.json?key=7A1r9pfPUNpumR1hzV0k contains the link

    "sources":{"openmaptiles":{"url":"https://api.maptiler.com/tiles/v3-2154/tiles.json?key=7A1r9pfPUNpumR1hzV0k","type":"vector"}}
    

    which in turn defines the tilegrid. If you wanted to avoid the black magic of hardcoding the tilegrid options you could fetch the TileJSON url and construct a tilegrid and vector tile source from the contents with code similar to https://github.com/OrdnanceSurvey/OS-Data-Hub-API-Demos/blob/master/OSVectorTileAPI/OpenLayers/map.js#L52-L71