import ol_control_WMSCapabilities from './WMSCapabilities.js'; import ol_View from 'ol/View.js' import ol_tilegrid_WMTS from 'ol/tilegrid/WMTS.js' import ol_format_WMTSCapabilities from 'ol/format/WMTSCapabilities.js' import ol_layer_Tile from 'ol/layer/Tile.js' import ol_source_WMTS from 'ol/source/WMTS.js' import { get as ol_proj_get } from 'ol/proj.js' import { transformExtent as ol_proj_transformExtent } from 'ol/proj.js' import { getWidth as ol_extent_getWidth } from 'ol/extent.js' /** WMTSCapabilities * @constructor * @fires load * @fires capabilities * @extends {ol_control_WMSCapabilities} * @param {*} options * @param {string|Element} [options.target] the target to set the dialog, use document.body to have fullwindow dialog * @param {string} [options.proxy] proxy to use when requesting Getcapabilites, default none (suppose the service use CORS) * @param {string} [options.placeholder='service url...'] input placeholder, default 'service url...' * @param {string} [options.title=WMTS] dialog title, default 'WMTS' * @param {string} [options.searchLabel='search'] Label for search button, default 'search' * @param {string} [options.loadLabel='load'] Label for load button, default 'load' * @param {Array} [options.srs] an array of supported srs, default map projection code or 'EPSG:3857' * @param {number} [options.timeout=1000] Timeout for getCapabilities request, default 1000 * @param {boolean} [options.cors=false] Use CORS, default false * @param {string} [options.optional] a list of optional url properties (when set in the request url), separated with ',' * @param {boolean} [options.trace=false] Log layer info, default false * @param {*} [options.services] a key/url object of services for quick access in a menu */ var ol_control_WMTSCapabilities = class olcontrolWMTSCapabilities extends ol_control_WMSCapabilities { constructor(options) { options = options || {}; options.title = options.title || 'WMTS'; super(options); this.getDialog().set('className', this.getDialog().get('className') + ' ol-wmtscapabilities' ); } /** Get service parser * @private */ _getParser() { var pars = new ol_format_WMTSCapabilities(); return { read: function (data) { var resp = pars.read(data); resp.Capability = { Layer: resp.Contents, }; // Generic attribution for layers resp.Capability.Layer.Attribution = { Title: resp.ServiceProvider.ProviderName }; // Remove non image format var layers = []; resp.Contents.Layer.forEach(function (l) { if (l.Format && /jpeg|png/.test(l.Format[0])) { layers.push(l); } }); resp.Contents.Layer = layers; return resp; }.bind(this) }; } /** Get Capabilities request parameters * @param {*} options */ getRequestParam(options) { return { SERVICE: 'WMTS', REQUEST: 'GetCapabilities', VERSION: options.version || '1.0.0' }; } /** Get tile grid options only for EPSG:3857 projection * @returns {*} * @private */ _getTG(tileMatrixSet, minZoom, maxZoom, tilePrefix) { var matrixIds = new Array(); var resolutions = new Array(); var size = ol_extent_getWidth(ol_proj_get('EPSG:3857').getExtent()) / 256; for (var z = 0; z <= (maxZoom ? maxZoom : 20); z++) { var id = tilePrefix ? tileMatrixSet + ':' + z : z; matrixIds[z] = id; resolutions[z] = size / Math.pow(2, z); } return { origin: [-20037508, 20037508], resolutions: resolutions, matrixIds: matrixIds, minZoom: (minZoom ? minZoom : 0) }; } /** Get WMTS tile grid (only EPSG:3857) * @param {sting} tileMatrixSet * @param {number} minZoom * @param {number} maxZoom * @param {boolean} tilePrefix * @returns {ol_tilegrid_WMTS} * @private */ getTileGrid(tileMatrixSet, minZoom, maxZoom, tilePrefix) { return new ol_tilegrid_WMTS(this._getTG(tileMatrixSet, minZoom, maxZoom, tilePrefix)); } /** Check if the TileMatrixSet is supported * @param {Object} tm * @returns {boolean} */ isSupportedSet(tm) { if (/^PM_.*/.test(tm.TileMatrixSet)) return true; return this.supportedSets.indexOf(tm.TileMatrixSet) >= 0; } /** Return a WMTS options for the given capabilities * @param {*} caps layer capabilities (read from the capabilities) * @param {*} parent capabilities * @return {*} options */ getOptionsFromCap(caps, parent) { var bbox = caps.WGS84BoundingBox; if (bbox) bbox = ol_proj_transformExtent(bbox, 'EPSG:4326', this.getMap().getView().getProjection()); // Tilematrix zoom var minZoom = Infinity, maxZoom = -Infinity; var tmatrix; caps.TileMatrixSetLink.forEach(function (tm) { if (this.isSupportedSet(tm)) { tmatrix = tm; caps.TileMatrixSet = tm.TileMatrixSet; } }.bind(this)); if (!tmatrix) { this.showError({ type: 'TileMatrix' }); return; } if (tmatrix.TileMatrixSetLimits) { var tilePrefix = tmatrix.TileMatrixSetLimits[0].TileMatrix.split(':').length > 1; tmatrix.TileMatrixSetLimits.forEach(function (tm) { var zoom = tm.TileMatrix.split(':').pop(); minZoom = Math.min(minZoom, parseInt(zoom)); maxZoom = Math.max(maxZoom, parseInt(zoom)); }); } else { minZoom = 0; maxZoom = 20; } var view = new ol_View(); view.setZoom(minZoom); var layer_opt = { title: caps.Title, extent: bbox, abstract: caps.Abstract, maxResolution: view.getResolution() }; var source_opt = { url: parent.url, layer: caps.Identifier, matrixSet: caps.TileMatrixSet, format: caps.Format[0] || 'image/jpeg', projection: 'EPSG:3857', //tileGrid: tg, tilePrefix: tilePrefix, minZoom: minZoom, maxZoom: maxZoom, style: caps.Style ? caps.Style[0].Identifier : 'normal', attributions: caps.Attribution.Title, crossOrigin: this.get('cors') ? 'anonymous' : null, wrapX: (this.get('wrapX') !== false), }; // Fill form this._fillForm({ title: layer_opt.title, layers: source_opt.layer, style: source_opt.style, format: source_opt.format, minZoom: minZoom, maxZoom: maxZoom, extent: bbox ? bbox.join(',') : '', projection: source_opt.projection, attribution: source_opt.attributions || '', version: '1.0.0' }); // Trace if (this.get('trace')) { // Source source_opt.tileGrid = 'TILEGRID'; var tso = JSON.stringify([source_opt], null, "\t").replace(/\\"/g, '"'); tso = tso.replace('"TILEGRID"', 'new ol_tilegrid_WMTS(' + JSON.stringify(this._getTG(source_opt.matrixSet, source_opt.minZoom, source_opt.maxZoom, source_opt.tilePrefix), null, '\t').replace(/\n/g, '\n\t\t') + ')' ); delete source_opt.tileGrid; // Layer layer_opt.source = "SOURCE"; var t = "new ol.layer.Tile (" + JSON.stringify(layer_opt, null, "\t") + ")"; t = t.replace(/\\"/g, '"') .replace('"SOURCE"', "new ol.source.WMTS(" + tso + ")") .replace(/\\t/g, "\t").replace(/\\n/g, "\n") .replace(/"tileGrid": {/g, '"tileGrid": new ol.tilegrid.WMTS({') .replace(/},\n(\t*)"style"/g, '}),\n$1"style"') .replace("([\n\t", "(") .replace("}\n])", "})"); console.log(t); delete layer_opt.source; } var returnedLegend = undefined; if (caps.Style && caps.Style[0] && caps.Style[0].LegendURL && caps.Style[0].LegendURL[0]) { returnedLegend = [ caps.Style[0].LegendURL[0].href ]; } return ({ layer: layer_opt, source: source_opt, data: { title: caps.Title, abstract: caps.Abstract, legend: returnedLegend, } }); } /** Get WMS options from control form * @return {*} original original options * @return {*} options * @private */ _getFormOptions() { var options = this._currentOptions || {}; if (!options.layer) options.layer = {}; if (!options.source) options.source = {}; if (!options.data) options.data = {}; var minZoom = parseInt(this._elements.formMinZoom.value) || 0; var maxZoom = parseInt(this._elements.formMaxZoom.value) || 20; var ext = []; if (this._elements.formExtent.value) { this._elements.formExtent.value.split(',').forEach(function (b) { ext.push(parseFloat(b)); }); } if (ext.length !== 4) ext = undefined; var attributions = []; if (this._elements.formAttribution.value) attributions.push(this._elements.formAttribution.value); var view = new ol_View({ projection: this.getMap().getView().getProjection() }); view.setZoom(minZoom); var layer_opt = { title: this._elements.formTitle.value, extent: ext, abstract: options.layer.abstract || '', maxResolution: view.getResolution() }; var source_opt = { url: this._elements.input.value, layer: this._elements.formLayer.value, matrixSet: options.source.matrixSet || 'PM', format: this._elements.formFormat.options[this._elements.formFormat.selectedIndex].value, projection: 'EPSG:3857', minZoom: minZoom, maxZoom: maxZoom, // tileGrid: this._getTG(options.source.matrixSet || 'PM', minZoom, maxZoom), style: this._elements.formStyle.value || 'normal', attributions: attributions, crossOrigin: this._elements.formCrossOrigin.checked ? 'anonymous' : null, wrapX: (this.get('wrapX') !== false), }; return ({ layer: layer_opt, source: source_opt, data: { title: this._elements.formTitle.value, abstract: options.data.abstract, legend: options.data.legend, } }); } /** Create a new layer using options received by getOptionsFromCap method * @param {*} options */ getLayerFromOptions(options) { if (!options) return; options.source.tileGrid = this.getTileGrid(options.source.matrixSet, options.source.minZoom, options.source.maxZoom, options.source.tilePrefix); options.layer.source = new ol_source_WMTS(options.source); var layer = new ol_layer_Tile(options.layer); // Restore options delete options.layer.source; delete options.source.tileGrid; return layer; } } /** An array of supported sets (basically EPSG:3857) * @api */ ol_control_WMSCapabilities.prototype.supportedSets = [ 'PM', '3857', 'EPSG:3857', 'EPSG:900913', 'webmercator', 'GoogleMapsCompatible' ] export default ol_control_WMTSCapabilities