/* 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_source_WMTS from 'ol/source/WMTS.js'
import {getWidth as ol_extent_getWidth} from 'ol/extent.js'
import ol_tilegrid_WMTS from 'ol/tilegrid/WMTS.js'
import {get as ol_proj_get} from 'ol/proj.js'
import ol_ext_Ajax from '../util/Ajax.js'
/** IGN's Geoportail WMTS source
* @constructor
* @extends {ol.source.WMTS}
* @param {olx.source.Geoportail=} options WMTS options
* @param {string=} options.layer Geoportail layer name
* @param {number} options.minZoom
* @param {number} options.maxZoom
* @param {string} options.server
* @param {string} [options.gppKey] api key, default none
* @param {string} options.authentication basic authentication associated with the gppKey as btoa("login:pwd")
* @param {string} options.format image format, default 'image/jpeg'
* @param {string} options.style layer style, default 'normal'
* @param {string} options.crossOrigin default 'anonymous'
* @param {string} options.wrapX default true
*/
var ol_source_Geoportail = class olsourceGeoportail extends ol_source_WMTS {
constructor(layer, options) {
options = options || {}
if (layer.layer) {
options = layer
layer = options.layer
}
var matrixIds = new Array()
var resolutions = new Array() //[156543.03392804103,78271.5169640205,39135.75848201024,19567.879241005125,9783.939620502562,4891.969810251281,2445.9849051256406,1222.9924525628203,611.4962262814101,305.74811314070485,152.87405657035254,76.43702828517625,38.218514142588134,19.109257071294063,9.554628535647034,4.777314267823517,2.3886571339117584,1.1943285669558792,0.5971642834779396,0.29858214173896974,0.14929107086948493,0.07464553543474241];
var size = ol_extent_getWidth(ol_proj_get('EPSG:3857').getExtent()) / 256
for (var z = 0; z <= (options.maxZoom ? options.maxZoom : 20); z++) {
matrixIds[z] = z
resolutions[z] = size / Math.pow(2, z)
}
var tg = new ol_tilegrid_WMTS({
origin: [-20037508, 20037508],
resolutions: resolutions,
matrixIds: matrixIds
})
tg.minZoom = (options.minZoom ? options.minZoom : 0)
var attr = [ ol_source_Geoportail.defaultAttribution ]
if (options.attributions) attr = options.attributions
var server = options.server || 'https://data.geopf.fr/wmts' // 'https://wxs.ign.fr/geoportail/wmts' old version
var gppKey = options.gppKey || options.key || ''
var wmts_options = {
url: ol_source_Geoportail.getServiceURL(server, gppKey),
layer: layer,
matrixSet: 'PM',
format: options.format ? options.format : 'image/jpeg',
projection: 'EPSG:3857',
tileGrid: tg,
style: options.style ? options.style : 'normal',
attributions: attr,
crossOrigin: (typeof options.crossOrigin == 'undefined') ? 'anonymous' : options.crossOrigin,
wrapX: !(options.wrapX === false)
}
super(wmts_options)
this._server = server
this._gppKey = gppKey
// Load url using basic authentification
if (options.authentication) {
this.setTileLoadFunction(ol_source_Geoportail.tileLoadFunctionWithAuthentication(options.authentication, this.getFormat()))
}
}
/** Get a tile load function to load tiles with basic authentication
* @param {string} authentication as btoa("login:pwd")
* @param {string} format mime type
* @return {function} tile load function to load tiles with basic authentication
*/
static tileLoadFunctionWithAuthentication(authentication, format) {
if (!authentication)
return undefined
return function (tile, src) {
var xhr = new XMLHttpRequest()
xhr.open("GET", src)
xhr.setRequestHeader("Authorization", "Basic " + authentication)
xhr.responseType = "arraybuffer"
xhr.onload = function () {
var arrayBufferView = new Uint8Array(this.response)
var blob = new Blob([arrayBufferView], { type: format })
var urlCreator = window.URL || window.webkitURL
var imageUrl = urlCreator.createObjectURL(blob)
tile.getImage().src = imageUrl
}
xhr.onerror = function () {
tile.getImage().src = ""
}
xhr.send()
}
}
/** Get service URL according to server url or standard url
*/
serviceURL() {
return ol_source_Geoportail.getServiceURL(this._server, this._gppKey)
}
/**
* Return the associated API key of the Map.
* @function
* @return the API key.
* @api stable
*/
getGPPKey() {
return this._gppKey
}
/**
* Set the associated API key to the Map.
* @param {String} key the API key.
* @param {String} authentication as btoa("login:pwd")
* @api stable
*/
setGPPKey(key, authentication) {
this._gppKey = key
var serviceURL = this.serviceURL()
this.setTileUrlFunction(function () {
var url = ol_source_Geoportail.prototype.getTileUrlFunction().apply(this, arguments)
if (url) {
var args = url.split("?")
return serviceURL + "?" + args[1]
}
else
return url
})
// Load url using basic authentification
if (authentication) {
this.setTileLoadFunction(ol_source_Geoportail.tileLoadFunctionWithAuthentication(authentication, this.getFormat()))
}
}
/** Return the GetFeatureInfo URL for the passed coordinate, resolution, and
* projection. Return `undefined` if the GetFeatureInfo URL cannot be
* constructed.
* @param {ol.Coordinate} coord
* @param {Number} resolution
* @param {ol.proj.Projection} projection default the source projection
* @param {Object} options
* @param {string} options.INFO_FORMAT response format text/plain, text/html, application/json, default text/plain
* @return {String|undefined} GetFeatureInfo URL.
*/
getFeatureInfoUrl(coord, resolution, projection, options) {
options = options || {}
if (!projection)
projection = this.getProjection()
var tileCoord = this.tileGrid.getTileCoordForCoordAndResolution(coord, resolution)
var ratio = 1
var url = this.getTileUrlFunction()(tileCoord, ratio, projection)
if (!url)
return url
var tileResolution = this.tileGrid.getResolution(tileCoord[0])
var tileExtent = this.tileGrid.getTileCoordExtent(tileCoord)
var i = Math.floor((coord[0] - tileExtent[0]) / (tileResolution / ratio))
var j = Math.floor((tileExtent[3] - coord[1]) / (tileResolution / ratio))
return url.replace(/Request=GetTile/i, 'Request=getFeatureInfo')
+ '&INFOFORMAT=' + (options.INFO_FORMAT || 'text/plain')
+ '&I=' + i
+ '&J=' + j
}
/** Get feature info
* @param {ol.Coordinate} coord
* @param {Number} resolution
* @param {ol.proj.Projection} projection default the source projection
* @param {Object} options
* @param {string} options.INFO_FORMAT response format text/plain, text/html, application/json, default text/plain
* @param {function} options.callback a function that take the response as parameter
* @param {function} options.error function called when an error occurred
*/
getFeatureInfo(coord, resolution, options) {
var url = this.getFeatureInfoUrl(coord, resolution, null, options)
ol_ext_Ajax.get({
url: url,
dataType: options.format || 'text/plain',
options: {
encode: false
},
success: function (resp) {
if (options.callback)
options.callback(resp)
},
error: options.error || function () { }
})
}
}
/** Standard IGN-GEOPORTAIL attribution
*/
ol_source_Geoportail.defaultAttribution = 'Géoservices © IGN-France';
/** Get service URL according to server url or standard url
*/
ol_source_Geoportail.getServiceURL = function(server, gppKey) {
// Old gppkey
if (gppKey === 'gpf') gppKey = '';
// Check server
if (!server) {
if (gppKey) {
server = 'https://data.geopf.fr/private/wmts';
} else {
server = 'https://data.geopf.fr/wmts';
}
}
// Add api key
if (/geopf/.test(server)) {
if (gppKey) {
return server + '?apikey=' + gppKey;
} else {
return server;
}
} else {
return server.replace(/^(https?:\/\/[^/]*)(.*)$/, "$1/" + gppKey + "$2")
}
/*
return (window.geoportailConfig ? window.geoportailConfig.url : "https://wxs.ign.fr/") + gppKey + "/geoportail/wmts"
*/
}
export default ol_source_Geoportail