/* Copyright (c) 2019 Jean-Marc VIGLINO,
released under the CeCILL-B license (French BSD license)
(http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.txt).
*/
import ol_layer_Tile from 'ol/layer/Tile.js'
import ol_format_WMTSCapabilities from 'ol/format/WMTSCapabilities.js'
import ol_ext_Ajax from '../util/Ajax.js'
import {transformExtent as ol_proj_transformExtent} from 'ol/proj.js'
// import {intersects as ol_extent_intersects} from 'ol/extent.js'
import ol_source_Geoportail from '../source/Geoportail.js'
/** IGN's Geoportail WMTS layer definition
* @constructor
* @extends {ol.layer.Tile}
* @param {olx.layer.WMTSOptions=} options WMTS options if not defined default are used
* @param {string} options.layer Geoportail layer name
* @param {string} options.gppKey Geoportail API key, default use layer registered key
* @param {ol.projectionLike} [options.projection=EPSG:3857] projection for the extent, default EPSG:3857
* @param {olx.source.WMTSOptions=} tileoptions WMTS options if not defined default are used
*/
var ol_layer_Geoportail = class ollayerGeoportail extends ol_layer_Tile {
constructor(layer, options, tileoptions) {
options = options || {}
tileoptions = tileoptions || {}
// use function(options, tileoption) when layer is set in options
if (typeof (layer) !== 'string') {
tileoptions = options || {}
options = layer
layer = options.layer
}
var maxZoom = options.maxZoom
// A source is defined
if (options.source) {
layer = options.source.getLayer()
options.gppKey = options.source.getGPPKey()
}
var capabilities = window.geoportailConfig ? window.geoportailConfig.capabilities[options.gppKey || options.key] || window.geoportailConfig.capabilities["default"] || ol_layer_Geoportail.capabilities : ol_layer_Geoportail.capabilities
capabilities = capabilities[layer]
if (!capabilities)
capabilities = ol_layer_Geoportail.capabilities[layer]
if (!capabilities) {
capabilities = { title: layer, originators: [] }
console.error("ol.layer.Geoportail: no layer definition for \"" + layer + "\"\nTry to use ol/layer/Geoportail~loadCapabilities() to get it.")
// throw new Error("ol.layer.Geoportail: no layer definition for \""+layer+"\"");
}
// tile options & default params
for (var i in capabilities) {
if (typeof tileoptions[i] == "undefined")
tileoptions[i] = capabilities[i]
}
if (options.gppKey || options.key) tileoptions.gppKey = options.gppKey || options.key;
// if (!tileoptions.gppKey && !tileoptions.key) tileoptions.gppKey = options.gppKey || options.key
if (!options.source) options.source = new ol_source_Geoportail(layer, tileoptions)
if (!options.title) options.title = capabilities.title
if (!options.name) options.name = layer
options.layer = layer
if (!options.queryable) options.queryable = capabilities.queryable
if (!options.desc) options.desc = capabilities.desc
if (!options.extent && capabilities.bbox) {
if (capabilities.bbox[0] > -170 && capabilities.bbox[2] < 170) {
options.extent = ol_proj_transformExtent(capabilities.bbox, 'EPSG:4326', options.projection || 'EPSG:3857')
}
}
options.maxZoom = maxZoom
// calculate layer max resolution
if (!options.maxResolution && tileoptions.minZoom) {
options.source.getTileGrid().minZoom -= (tileoptions.minZoom > 1 ? 2 : 1)
options.maxResolution = options.source.getTileGrid().getResolution(options.source.getTileGrid().minZoom)
options.source.getTileGrid().minZoom = tileoptions.minZoom
}
super(options)
this._originators = capabilities.originators
// BUG GPP / OLD VERSION: Attributions constraints are not set properly :(
/** /
// Set attribution according to the originators
var counter = 0;
// Get default attribution
var getAttrib = function(title, o) {
if (this.get('attributionMode')==='logo') {
if (!title) return ol_source_Geoportail.prototype.attribution;
else return '
';
} else {
if (!title) return ol_source_Geoportail.prototype.attribution;
else return '© '+title+''
}
}.bind(this);
var currentZ, currentCenter = [];
var setAttribution = function(e) {
var a, o, i;
counter--;
if (!counter) {
var z = e.frameState.viewState.zoom;
console.log(e)
if (z===currentZ
&& e.frameState.viewState.center[0]===currentCenter[0]
&& e.frameState.viewState.center[1]===currentCenter[1]){
return;
}
currentZ = z;
currentCenter = e.frameState.viewState.center;
var ex = e.frameState.extent;
ex = ol_proj_transformExtent (ex, e.frameState.viewState.projection, 'EPSG:4326');
if (this._originators) {
var attrib = this.getSource().getAttributions();
// ol v5
if (typeof(attrib)==='function') attrib = attrib();
attrib.splice(0, attrib.length);
var maxZoom = 0;
for (a in this._originators) {
o = this._originators[a];
for (i=0; i maxZoom
&& ol_extent_intersects(ex, o.constraint[i].bbox)) {
maxZoom = o.constraint[i].maxZoom;
}
}
}
if (maxZoom < z) z = maxZoom;
if (this.getSource().getTileGrid() && z < this.getSource().getTileGrid().getMinZoom()) {
z = this.getSource().getTileGrid().getMinZoom();
}
for (a in this._originators) {
o = this._originators[a];
if (!o.constraint.length) {
attrib.push (getAttrib(a, o));
} else {
for (i=0; i= o.constraint[i].minZoom
&& ol_extent_intersects(ex, o.constraint[i].bbox)) {
attrib.push (getAttrib(a, o));
break;
}
}
}
}
if (!attrib.length) attrib.push ( getAttrib() );
this.getSource().setAttributions(attrib);
}
}
}.bind(this);
this.on('precompose', function(e) {
counter++;
setTimeout(function () { setAttribution(e) }, 500);
});
/**/
}
/** Register new layer capability
* @param {string} layer layer name
* @param {*} capability
*/
static register(layer, capability) {
ol_layer_Geoportail.capabilities[layer] = capability
}
/** Check if a layer registered with a key?
* @param {string} layer layer name
* @returns {boolean}
*/
static isRegistered(layer) {
return ol_layer_Geoportail.capabilities[layer] && ol_layer_Geoportail.capabilities[layer].key
}
/** Load capabilities from the service
* @param {string} gppKey the API key to get capabilities for
* @return {*} Promise-like response
*/
static loadCapabilities(gppKey) {
var onSuccess = function () { }
var onError = function () { }
var onFinally = function () { }
this.getCapabilities(gppKey).then(function (c) {
ol_layer_Geoportail.capabilities = c
onSuccess(c)
}).catch(function (e) {
onError(e)
}).finally(function (c) {
onFinally(c)
})
var response = {
then: function (callback) {
if (typeof (callback) === 'function')
onSuccess = callback
return response
},
catch: function (callback) {
if (typeof (callback) === 'function')
onError = callback
return response
},
finally: function (callback) {
if (typeof (callback) === 'function')
onFinally = callback
return response
}
}
return response
}
/** Get Key capabilities
* @param {string} gppKey the API key to get capabilities for
* @return {*} Promise-like response, use then, catch and finally to get the response
*/
static getCapabilities(gppKey) {
// Generic API key (for compatibility)
if (gppKey === 'gpf') gppKey = undefined;
var onSuccess = function () { }
var onError = function () { }
var onFinally = function () { }
// Find min max zoom in the list
function getMinMaxZoom(z) {
var zoom = {
min: parseFloat(z[0].TileMatrix),
max: parseFloat(z[0].TileMatrix)
}
for (var k=1; k 0,
style: (l.Style && l.Style.length ? l.Style[0].Identifier : 'normal'),
tilematrix: 'PM',
title: l.Title,
legend: legend
}
}
// Return capabilities
onSuccess(capabilities, themes)
onFinally(capabilities, themes)
}
})
// Promise like response
var response = {
then: function (callback) {
if (typeof (callback) === 'function'){
onSuccess = callback
}
return response
},
catch: function (callback) {
if (typeof (callback) === 'function'){
onError = callback
}
return response
},
finally: function (callback) {
if (typeof (callback) === 'function'){
onFinally = callback
}
return response
},
}
return response
}
}
/** Default capabilities for main layers
*/
ol_layer_Geoportail.capabilities = {
"GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2": {"layer":"GEOGRAPHICALGRIDSYSTEMS.PLANIGNV2","theme":"cartes","desc":"Cartographie multi-échelles sur le territoire national, issue des bases de données vecteur de l’IGN, mis à jour régulièrement et réalisée selon un processus entièrement automatisé.","server":"https://data.geopf.fr/wmts","bbox":[-175,-85,175,85],"format":"image/png","minZoom":0,"maxZoom":19,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Plan IGN v2"},
"CADASTRALPARCELS.PARCELLAIRE_EXPRESS": {"layer":"CADASTRALPARCELS.PARCELLAIRE_EXPRESS","theme":"parcellaire","desc":"Plan cadastral informatisé vecteur de la DGFIP édition Juillet 2023.","server":"https://data.geopf.fr/wmts","bbox":[-63.3725,-21.4756,55.9259,51.3121],"format":"image/png","minZoom":0,"maxZoom":19,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"PCI vecteur"},
"ORTHOIMAGERY.ORTHOPHOTOS": {"layer":"ORTHOIMAGERY.ORTHOPHOTOS","theme":"ortho","desc":"Photographies aériennes","server":"https://data.geopf.fr/wmts","bbox":[-180,-89,180,89],"format":"image/jpeg","minZoom":0,"maxZoom":20,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":true,"style":"normal","tilematrix":"PM","title":"Photographies aériennes"},
// Need API key
"GEOGRAPHICALGRIDSYSTEMS.MAPS": {"layer":"GEOGRAPHICALGRIDSYSTEMS.MAPS","theme":"cartes","desc":"Cartes IGN","server":"https://data.geopf.fr/private/wmts","bbox":[-180,-68.1389,180,80],"format":"image/jpeg","minZoom":0,"maxZoom":18,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Cartes IGN"},
// Other layers
"ADMINEXPRESS-COG-CARTO.LATEST": {"layer":"ADMINEXPRESS-COG-CARTO.LATEST","theme":"administratif","desc":"Limites administratives Express COG code officiel géographique 2023","server":"https://data.geopf.fr/wmts","bbox":[-63.3725,-21.4756,55.9259,51.3121],"format":"image/png","minZoom":6,"maxZoom":16,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":true,"style":"normal","tilematrix":"PM","title":"ADMINEXPRESS COG CARTO"},
"GEOGRAPHICALGRIDSYSTEMS.SLOPES.MOUNTAIN": {"layer":"GEOGRAPHICALGRIDSYSTEMS.SLOPES.MOUNTAIN","theme":"cartes","desc":"Carte des zones ayant une valeur de pente supérieure à 30°-35°-40°-45° d'après la BD ALTI au pas de 5m","server":"https://data.geopf.fr/wmts","bbox":[-63.1614,-21.5446,56.0018,51.0991],"format":"image/png","minZoom":0,"maxZoom":17,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Carte des pentes"},
"ELEVATION.SLOPES": {"layer":"ELEVATION.SLOPES","theme":"altimetrie","desc":"La couche altitude se compose d'un MNT (Modèle Numérique de Terrain) affiché en teintes hypsométriques et issu de la BD ALTI®.","server":"https://data.geopf.fr/wmts","bbox":[-179.5,-75,179.5,75],"format":"image/jpeg","minZoom":6,"maxZoom":14,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Altitude"},
"GEOGRAPHICALGRIDSYSTEMS.MAPS.BDUNI.J1": { "key":"cartes", "server":"https://wxs.ign.fr/geoportail/wmts","layer":"GEOGRAPHICALGRIDSYSTEMS.MAPS.BDUNI.J1","title":"Plan IGN j+1","format":"image/png","style":"normal","queryable":false,"tilematrix":"PM","minZoom":0,"maxZoom":18,"bbox":[-179.5,-75,179.5,75],"desc":"Plan IGN j+1","originators":{"IGN":{"href":"http://www.ign.fr","attribution":"Institut national de l'information géographique et forestière","logo":"https://wxs.ign.fr/static/logos/IGN/IGN.gif","minZoom":0,"maxZoom":18,"constraint":[{"minZoom":0,"maxZoom":18,"bbox":[-179,-80,179,80]}]}}},
// "GEOGRAPHICALGRIDSYSTEMS.MAPS.BDUNI.J1": { "theme":"cartes", "server":"https://data.geopf.fr/wmts","layer":"GEOGRAPHICALGRIDSYSTEMS.MAPS.BDUNI.J1","title":"Plan IGN j+1","format":"image/png","style":"normal","queryable":false,"tilematrix":"PM","minZoom":0,"maxZoom":18,"bbox":[-179.5,-75,179.5,75],"desc":"Plan IGN j+1","originators":{"IGN":{"href":"http://www.ign.fr","attribution":"Institut national de l'information géographique et forestière","logo":"https://wxs.ign.fr/static/logos/IGN/IGN.gif","minZoom":0,"maxZoom":18,"constraint":[{"minZoom":0,"maxZoom":18,"bbox":[-179,-80,179,80]}]}}},
"TRANSPORTNETWORKS.ROADS": {"layer":"TRANSPORTNETWORKS.ROADS","theme":"topographie","desc":"Affichage du réseau routier français et européen.","server":"https://data.geopf.fr/wmts","bbox":[-63.9692,-21.4969,55.9644,71.5841],"format":"image/png","minZoom":6,"maxZoom":18,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Routes"},
"GEOGRAPHICALNAMES.NAMES": {"layer":"GEOGRAPHICALNAMES.NAMES","theme":"topographie","desc":"Affichage des noms des villes, villages, lieux-dits ...","server":"https://data.geopf.fr/wmts","bbox":[-63.9692,-21.4969,55.9644,71.5841],"format":"image/png","minZoom":6,"maxZoom":18,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Dénominations géographiques","legend":["https://data.geopf.fr/annexes/ressources/legendes/LEGEND.jpg"]},
"CARTES.NATURALEARTH": {"layer":"CARTES.NATURALEARTH","theme":"cartes","desc":"Carte générale du monde politique avec les frontières et capitales d'Etat, les entités administratives secondaires, villes principales, fleuves, lacs et océans. Edition : 1.4.0","server":"https://data.geopf.fr/wmts","bbox":[-179.5,-75,179.5,75],"format":"image/jpeg","minZoom":1,"maxZoom":9,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Monde Natural Earth","legend":["https://data.geopf.fr/annexes/ressources/legendes/LEGEND.jpg"]},
"GEOGRAPHICALGRIDSYSTEMS.MAPS.OVERVIEW": {"layer":"GEOGRAPHICALGRIDSYSTEMS.MAPS.OVERVIEW","key":"","theme":"cartes","desc":"Carte Mondiale pour la mini-vue","server":"https://data.geopf.fr/wmts","bbox":[-179.5,-75,179.5,75],"format":"image/jpeg","minZoom":1,"maxZoom":8,"originators":{"Geoservices":{"attribution":"Géoservices","href":"https://geoservices.ign.fr/"}},"queryable":false,"style":"normal","tilematrix":"PM","title":"Carte Mondiale pour la mini-vue","legend":["https://data.geopf.fr/annexes/ressources/legendes/LEGEND.jpg"]},
};
/** List of theme with a regexp to filter layers by theme (with getcapabilities)
* @API
*/
ol_layer_Geoportail.themes = [{
theme: 'edugeo',
rex: /EDUGEO|PVA_IGN_zone-marais|VERDUN|DOUAUMONT/
}, {
theme: 'cartes',
rex: /GEOGRAPHICALGRIDSYSTEMS|CARTES|SCAN/
}, {
theme: 'energie',
rex: /CHALEUR|CHAUD|FROID|METHAN|CONSO|ENR|ELECTRIQUE|EOLIEN|SOLAIRE|PRODUCTIBLE|GEOTHERM|PROD\.INSTALLATION|POTENTIEL\.HYDRO/
}, {
theme: 'risque',
rex: /SISMIC|RISKZONE/
}, {
theme: 'agriculture',
rex: /AGRICULTURE|PAC/
}, {
theme: 'altimetrie',
rex: /ELEVATION|SLOPE|ISOHYPSE/
}, {
theme: 'parcellaire',
rex: /PARCELS|Parcellaire|RPG|PCRS|PCI/
}, {
theme: 'administratif',
rex: /ADMIN/
}, {
theme: 'ocsge',
rex: /OCSGE|CoSIA/
}, {
theme: 'clc',
rex: /\.CLC|\.CHA/
}, {
theme: 'environnement',
rex: /PROTECTEDAREAS|FORETS|DEBROUSSAILLEMENT|LANDCOVER|PROTECTEDSITES|CHASSE|INPE|OFB/
}, {
theme: 'topographie',
rex: /BDCARTO|PARKING|RAILWAYS|BUILDINGS|RUNWAYS|UTILITYANDGOVERNMENTALSERVICES|GEOGRAPHICALNAMES\.NAMES|HYDROGRAPHY|TRANSPORTNETWORKS\.ROADS$|hedge.hedge/
}, {
theme: 'transport',
rex: /TRANSPORT|SECUROUTE|AUTOROUT/
}, {
theme: 'economie',
rex: /INSEE|AREAMANAGEMENT|PINEL|PRIORITYDISCTRICT/
}, {
theme: 'agriculture',
rex: /LANDUSE|PRAIRIES/
}, {
theme: 'satellite',
rex: /ORTHO-SAT|SPOT5|RAPIDEYE/
}, {
theme: 'orthohisto',
rex: /ORTHOPHOTOS\d|ORTHO-EXPRESS-\d/
}, {
theme: 'ortho',
rex: /ORTHOIMAGERY/
}];
export default ol_layer_Geoportail