diff --git a/.gitignore b/.gitignore index 52622bd..7ea2259 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ /node_modules/ bundle.js +dist/app.js diff --git a/_readme_.md b/_readme_.md deleted file mode 100644 index 9883596..0000000 --- a/_readme_.md +++ /dev/null @@ -1,20 +0,0 @@ -# OpenLayers + Webpack - -This example demonstrates how the `ol` package can be used with webpack 2. - -Clone the project. - - git clone git@gist.github.com:79025aef325cd2837364400a105405b8.git ol-webpack - -Install the project dependencies. - - cd ol-webpack - npm install - -Create a bundle for the browser. - - npm run build - -Open `index.html` to see the result. - - open index.html diff --git a/dist/index.html b/dist/index.html new file mode 100644 index 0000000..f56460d --- /dev/null +++ b/dist/index.html @@ -0,0 +1,14 @@ + + + + + Using OpenLayers with Webpack + + + + +
+ + + diff --git a/dist/main.css b/dist/main.css new file mode 100644 index 0000000..cd35c8c --- /dev/null +++ b/dist/main.css @@ -0,0 +1,264 @@ +.ol-box { + box-sizing: border-box; + border-radius: 2px; + border: 2px solid blue; +} + +.ol-mouse-position { + top: 8px; + right: 8px; + position: absolute; +} + +.ol-scale-line { + background: rgba(0,60,136,0.3); + border-radius: 4px; + bottom: 8px; + left: 8px; + padding: 2px; + position: absolute; +} +.ol-scale-line-inner { + border: 1px solid #eee; + border-top: none; + color: #eee; + font-size: 10px; + text-align: center; + margin: 1px; + will-change: contents, width; +} +.ol-overlay-container { + will-change: left,right,top,bottom; +} + +.ol-unsupported { + display: none; +} +.ol-viewport, .ol-unselectable { + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0,0,0,0); +} +.ol-selectable { + -webkit-touch-callout: default; + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} +.ol-grabbing { + cursor: -webkit-grabbing; + cursor: -moz-grabbing; + cursor: grabbing; +} +.ol-grab { + cursor: move; + cursor: -webkit-grab; + cursor: -moz-grab; + cursor: grab; +} +.ol-control { + position: absolute; + background-color: rgba(255,255,255,0.4); + border-radius: 4px; + padding: 2px; +} +.ol-control:hover { + background-color: rgba(255,255,255,0.6); +} +.ol-zoom { + top: .5em; + left: .5em; +} +.ol-rotate { + top: .5em; + right: .5em; + transition: opacity .25s linear, visibility 0s linear; +} +.ol-rotate.ol-hidden { + opacity: 0; + visibility: hidden; + transition: opacity .25s linear, visibility 0s linear .25s; +} +.ol-zoom-extent { + top: 4.643em; + left: .5em; +} +.ol-full-screen { + right: .5em; + top: .5em; +} +@media print { + .ol-control { + display: none; + } +} + +.ol-control button { + display: block; + margin: 1px; + padding: 0; + color: white; + font-size: 1.14em; + font-weight: bold; + text-decoration: none; + text-align: center; + height: 1.375em; + width: 1.375em; + line-height: .4em; + background-color: rgba(0,60,136,0.5); + border: none; + border-radius: 2px; +} +.ol-control button::-moz-focus-inner { + border: none; + padding: 0; +} +.ol-zoom-extent button { + line-height: 1.4em; +} +.ol-compass { + display: block; + font-weight: normal; + font-size: 1.2em; + will-change: transform; +} +.ol-touch .ol-control button { + font-size: 1.5em; +} +.ol-touch .ol-zoom-extent { + top: 5.5em; +} +.ol-control button:hover, +.ol-control button:focus { + text-decoration: none; + background-color: rgba(0,60,136,0.7); +} +.ol-zoom .ol-zoom-in { + border-radius: 2px 2px 0 0; +} +.ol-zoom .ol-zoom-out { + border-radius: 0 0 2px 2px; +} + + +.ol-attribution { + text-align: right; + bottom: .5em; + right: .5em; + max-width: calc(100% - 1.3em); +} + +.ol-attribution ul { + margin: 0; + padding: 0 .5em; + font-size: .7rem; + line-height: 1.375em; + color: #000; + text-shadow: 0 0 2px #fff; +} +.ol-attribution li { + display: inline; + list-style: none; + line-height: inherit; +} +.ol-attribution li:not(:last-child):after { + content: " "; +} +.ol-attribution img { + max-height: 2em; + max-width: inherit; + vertical-align: middle; +} +.ol-attribution ul, .ol-attribution button { + display: inline-block; +} +.ol-attribution.ol-collapsed ul { + display: none; +} +.ol-attribution:not(.ol-collapsed) { + background: rgba(255,255,255,0.8); +} +.ol-attribution.ol-uncollapsible { + bottom: 0; + right: 0; + border-radius: 4px 0 0; + height: 1.1em; + line-height: 1em; +} +.ol-attribution.ol-uncollapsible img { + margin-top: -.2em; + max-height: 1.6em; +} +.ol-attribution.ol-uncollapsible button { + display: none; +} + +.ol-zoomslider { + top: 4.5em; + left: .5em; + height: 200px; +} +.ol-zoomslider button { + position: relative; + height: 10px; +} + +.ol-touch .ol-zoomslider { + top: 5.5em; +} + +.ol-overviewmap { + left: 0.5em; + bottom: 0.5em; +} +.ol-overviewmap.ol-uncollapsible { + bottom: 0; + left: 0; + border-radius: 0 4px 0 0; +} +.ol-overviewmap .ol-overviewmap-map, +.ol-overviewmap button { + display: inline-block; +} +.ol-overviewmap .ol-overviewmap-map { + border: 1px solid #7b98bc; + height: 150px; + margin: 2px; + width: 150px; +} +.ol-overviewmap:not(.ol-collapsed) button{ + bottom: 1px; + left: 2px; + position: absolute; +} +.ol-overviewmap.ol-collapsed .ol-overviewmap-map, +.ol-overviewmap.ol-uncollapsible button { + display: none; +} +.ol-overviewmap:not(.ol-collapsed) { + background: rgba(255,255,255,0.8); +} +.ol-overviewmap-box { + border: 2px dotted rgba(0,60,136,0.7); +} + +.ol-overviewmap .ol-overviewmap-box:hover { + cursor: move; +} + +html, body { + margin: 0; + height: 100%; } + +#map { + position: absolute; + top: 0; + bottom: 0; + width: 100%; } + + +/*# sourceMappingURL=main.css.map*/ \ No newline at end of file diff --git a/dist/main.css.map b/dist/main.css.map new file mode 100644 index 0000000..592f809 --- /dev/null +++ b/dist/main.css.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///./node_modules/ol/ol.css","webpack:///./src/app.scss"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;AAGA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAEA;AACA;AACA;;AC1PA;AACA;AACA,eAAe;;AAEf;AACA;AACA;AACA;AACA,cAAc","file":"main.css","sourcesContent":[".ol-box {\n box-sizing: border-box;\n border-radius: 2px;\n border: 2px solid blue;\n}\n\n.ol-mouse-position {\n top: 8px;\n right: 8px;\n position: absolute;\n}\n\n.ol-scale-line {\n background: rgba(0,60,136,0.3);\n border-radius: 4px;\n bottom: 8px;\n left: 8px;\n padding: 2px;\n position: absolute;\n}\n.ol-scale-line-inner {\n border: 1px solid #eee;\n border-top: none;\n color: #eee;\n font-size: 10px;\n text-align: center;\n margin: 1px;\n will-change: contents, width;\n}\n.ol-overlay-container {\n will-change: left,right,top,bottom;\n}\n\n.ol-unsupported {\n display: none;\n}\n.ol-viewport, .ol-unselectable {\n -webkit-touch-callout: none;\n -webkit-user-select: none;\n -moz-user-select: none;\n -ms-user-select: none;\n user-select: none;\n -webkit-tap-highlight-color: rgba(0,0,0,0);\n}\n.ol-selectable {\n -webkit-touch-callout: default;\n -webkit-user-select: text;\n -moz-user-select: text;\n -ms-user-select: text;\n user-select: text;\n}\n.ol-grabbing {\n cursor: -webkit-grabbing;\n cursor: -moz-grabbing;\n cursor: grabbing;\n}\n.ol-grab {\n cursor: move;\n cursor: -webkit-grab;\n cursor: -moz-grab;\n cursor: grab;\n}\n.ol-control {\n position: absolute;\n background-color: rgba(255,255,255,0.4);\n border-radius: 4px;\n padding: 2px;\n}\n.ol-control:hover {\n background-color: rgba(255,255,255,0.6);\n}\n.ol-zoom {\n top: .5em;\n left: .5em;\n}\n.ol-rotate {\n top: .5em;\n right: .5em;\n transition: opacity .25s linear, visibility 0s linear;\n}\n.ol-rotate.ol-hidden {\n opacity: 0;\n visibility: hidden;\n transition: opacity .25s linear, visibility 0s linear .25s;\n}\n.ol-zoom-extent {\n top: 4.643em;\n left: .5em;\n}\n.ol-full-screen {\n right: .5em;\n top: .5em;\n}\n@media print {\n .ol-control {\n display: none;\n }\n}\n\n.ol-control button {\n display: block;\n margin: 1px;\n padding: 0;\n color: white;\n font-size: 1.14em;\n font-weight: bold;\n text-decoration: none;\n text-align: center;\n height: 1.375em;\n width: 1.375em;\n line-height: .4em;\n background-color: rgba(0,60,136,0.5);\n border: none;\n border-radius: 2px;\n}\n.ol-control button::-moz-focus-inner {\n border: none;\n padding: 0;\n}\n.ol-zoom-extent button {\n line-height: 1.4em;\n}\n.ol-compass {\n display: block;\n font-weight: normal;\n font-size: 1.2em;\n will-change: transform;\n}\n.ol-touch .ol-control button {\n font-size: 1.5em;\n}\n.ol-touch .ol-zoom-extent {\n top: 5.5em;\n}\n.ol-control button:hover,\n.ol-control button:focus {\n text-decoration: none;\n background-color: rgba(0,60,136,0.7);\n}\n.ol-zoom .ol-zoom-in {\n border-radius: 2px 2px 0 0;\n}\n.ol-zoom .ol-zoom-out {\n border-radius: 0 0 2px 2px;\n}\n\n\n.ol-attribution {\n text-align: right;\n bottom: .5em;\n right: .5em;\n max-width: calc(100% - 1.3em);\n}\n\n.ol-attribution ul {\n margin: 0;\n padding: 0 .5em;\n font-size: .7rem;\n line-height: 1.375em;\n color: #000;\n text-shadow: 0 0 2px #fff;\n}\n.ol-attribution li {\n display: inline;\n list-style: none;\n line-height: inherit;\n}\n.ol-attribution li:not(:last-child):after {\n content: \" \";\n}\n.ol-attribution img {\n max-height: 2em;\n max-width: inherit;\n vertical-align: middle;\n}\n.ol-attribution ul, .ol-attribution button {\n display: inline-block;\n}\n.ol-attribution.ol-collapsed ul {\n display: none;\n}\n.ol-attribution:not(.ol-collapsed) {\n background: rgba(255,255,255,0.8);\n}\n.ol-attribution.ol-uncollapsible {\n bottom: 0;\n right: 0;\n border-radius: 4px 0 0;\n height: 1.1em;\n line-height: 1em;\n}\n.ol-attribution.ol-uncollapsible img {\n margin-top: -.2em;\n max-height: 1.6em;\n}\n.ol-attribution.ol-uncollapsible button {\n display: none;\n}\n\n.ol-zoomslider {\n top: 4.5em;\n left: .5em;\n height: 200px;\n}\n.ol-zoomslider button {\n position: relative;\n height: 10px;\n}\n\n.ol-touch .ol-zoomslider {\n top: 5.5em;\n}\n\n.ol-overviewmap {\n left: 0.5em;\n bottom: 0.5em;\n}\n.ol-overviewmap.ol-uncollapsible {\n bottom: 0;\n left: 0;\n border-radius: 0 4px 0 0;\n}\n.ol-overviewmap .ol-overviewmap-map,\n.ol-overviewmap button {\n display: inline-block;\n}\n.ol-overviewmap .ol-overviewmap-map {\n border: 1px solid #7b98bc;\n height: 150px;\n margin: 2px;\n width: 150px;\n}\n.ol-overviewmap:not(.ol-collapsed) button{\n bottom: 1px;\n left: 2px;\n position: absolute;\n}\n.ol-overviewmap.ol-collapsed .ol-overviewmap-map,\n.ol-overviewmap.ol-uncollapsible button {\n display: none;\n}\n.ol-overviewmap:not(.ol-collapsed) {\n background: rgba(255,255,255,0.8);\n}\n.ol-overviewmap-box {\n border: 2px dotted rgba(0,60,136,0.7);\n}\n\n.ol-overviewmap .ol-overviewmap-box:hover {\n cursor: move;\n}\n","html, body {\n margin: 0;\n height: 100%; }\n\n#map {\n position: absolute;\n top: 0;\n bottom: 0;\n width: 100%; }\n"],"sourceRoot":""} \ No newline at end of file diff --git a/dist/main.js b/dist/main.js new file mode 100644 index 0000000..d034da0 --- /dev/null +++ b/dist/main.js @@ -0,0 +1,32170 @@ +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter }); +/******/ } +/******/ }; +/******/ +/******/ // define __esModule on exports +/******/ __webpack_require__.r = function(exports) { +/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { +/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); +/******/ } +/******/ Object.defineProperty(exports, '__esModule', { value: true }); +/******/ }; +/******/ +/******/ // create a fake namespace object +/******/ // mode & 1: value is a module id, require it +/******/ // mode & 2: merge all properties of value into the ns +/******/ // mode & 4: return value when already ns object +/******/ // mode & 8|1: behave like require +/******/ __webpack_require__.t = function(value, mode) { +/******/ if(mode & 1) value = __webpack_require__(value); +/******/ if(mode & 8) return value; +/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value; +/******/ var ns = Object.create(null); +/******/ __webpack_require__.r(ns); +/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value }); +/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key)); +/******/ return ns; +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 10); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +module.exports = rbush; +module.exports.default = rbush; + +var quickselect = __webpack_require__(11); + +function rbush(maxEntries, format) { + if (!(this instanceof rbush)) return new rbush(maxEntries, format); + + // max entries in a node is 9 by default; min node fill is 40% for best performance + this._maxEntries = Math.max(4, maxEntries || 9); + this._minEntries = Math.max(2, Math.ceil(this._maxEntries * 0.4)); + + if (format) { + this._initFormat(format); + } + + this.clear(); +} + +rbush.prototype = { + + all: function () { + return this._all(this.data, []); + }, + + search: function (bbox) { + + var node = this.data, + result = [], + toBBox = this.toBBox; + + if (!intersects(bbox, node)) return result; + + var nodesToSearch = [], + i, len, child, childBBox; + + while (node) { + for (i = 0, len = node.children.length; i < len; i++) { + + child = node.children[i]; + childBBox = node.leaf ? toBBox(child) : child; + + if (intersects(bbox, childBBox)) { + if (node.leaf) result.push(child); + else if (contains(bbox, childBBox)) this._all(child, result); + else nodesToSearch.push(child); + } + } + node = nodesToSearch.pop(); + } + + return result; + }, + + collides: function (bbox) { + + var node = this.data, + toBBox = this.toBBox; + + if (!intersects(bbox, node)) return false; + + var nodesToSearch = [], + i, len, child, childBBox; + + while (node) { + for (i = 0, len = node.children.length; i < len; i++) { + + child = node.children[i]; + childBBox = node.leaf ? toBBox(child) : child; + + if (intersects(bbox, childBBox)) { + if (node.leaf || contains(bbox, childBBox)) return true; + nodesToSearch.push(child); + } + } + node = nodesToSearch.pop(); + } + + return false; + }, + + load: function (data) { + if (!(data && data.length)) return this; + + if (data.length < this._minEntries) { + for (var i = 0, len = data.length; i < len; i++) { + this.insert(data[i]); + } + return this; + } + + // recursively build the tree with the given data from scratch using OMT algorithm + var node = this._build(data.slice(), 0, data.length - 1, 0); + + if (!this.data.children.length) { + // save as is if tree is empty + this.data = node; + + } else if (this.data.height === node.height) { + // split root if trees have the same height + this._splitRoot(this.data, node); + + } else { + if (this.data.height < node.height) { + // swap trees if inserted one is bigger + var tmpNode = this.data; + this.data = node; + node = tmpNode; + } + + // insert the small tree into the large tree at appropriate level + this._insert(node, this.data.height - node.height - 1, true); + } + + return this; + }, + + insert: function (item) { + if (item) this._insert(item, this.data.height - 1); + return this; + }, + + clear: function () { + this.data = createNode([]); + return this; + }, + + remove: function (item, equalsFn) { + if (!item) return this; + + var node = this.data, + bbox = this.toBBox(item), + path = [], + indexes = [], + i, parent, index, goingUp; + + // depth-first iterative tree traversal + while (node || path.length) { + + if (!node) { // go up + node = path.pop(); + parent = path[path.length - 1]; + i = indexes.pop(); + goingUp = true; + } + + if (node.leaf) { // check current node + index = findItem(item, node.children, equalsFn); + + if (index !== -1) { + // item found, remove the item and condense tree upwards + node.children.splice(index, 1); + path.push(node); + this._condense(path); + return this; + } + } + + if (!goingUp && !node.leaf && contains(node, bbox)) { // go down + path.push(node); + indexes.push(i); + i = 0; + parent = node; + node = node.children[0]; + + } else if (parent) { // go right + i++; + node = parent.children[i]; + goingUp = false; + + } else node = null; // nothing found + } + + return this; + }, + + toBBox: function (item) { return item; }, + + compareMinX: compareNodeMinX, + compareMinY: compareNodeMinY, + + toJSON: function () { return this.data; }, + + fromJSON: function (data) { + this.data = data; + return this; + }, + + _all: function (node, result) { + var nodesToSearch = []; + while (node) { + if (node.leaf) result.push.apply(result, node.children); + else nodesToSearch.push.apply(nodesToSearch, node.children); + + node = nodesToSearch.pop(); + } + return result; + }, + + _build: function (items, left, right, height) { + + var N = right - left + 1, + M = this._maxEntries, + node; + + if (N <= M) { + // reached leaf level; return leaf + node = createNode(items.slice(left, right + 1)); + calcBBox(node, this.toBBox); + return node; + } + + if (!height) { + // target height of the bulk-loaded tree + height = Math.ceil(Math.log(N) / Math.log(M)); + + // target number of root entries to maximize storage utilization + M = Math.ceil(N / Math.pow(M, height - 1)); + } + + node = createNode([]); + node.leaf = false; + node.height = height; + + // split the items into M mostly square tiles + + var N2 = Math.ceil(N / M), + N1 = N2 * Math.ceil(Math.sqrt(M)), + i, j, right2, right3; + + multiSelect(items, left, right, N1, this.compareMinX); + + for (i = left; i <= right; i += N1) { + + right2 = Math.min(i + N1 - 1, right); + + multiSelect(items, i, right2, N2, this.compareMinY); + + for (j = i; j <= right2; j += N2) { + + right3 = Math.min(j + N2 - 1, right2); + + // pack each entry recursively + node.children.push(this._build(items, j, right3, height - 1)); + } + } + + calcBBox(node, this.toBBox); + + return node; + }, + + _chooseSubtree: function (bbox, node, level, path) { + + var i, len, child, targetNode, area, enlargement, minArea, minEnlargement; + + while (true) { + path.push(node); + + if (node.leaf || path.length - 1 === level) break; + + minArea = minEnlargement = Infinity; + + for (i = 0, len = node.children.length; i < len; i++) { + child = node.children[i]; + area = bboxArea(child); + enlargement = enlargedArea(bbox, child) - area; + + // choose entry with the least area enlargement + if (enlargement < minEnlargement) { + minEnlargement = enlargement; + minArea = area < minArea ? area : minArea; + targetNode = child; + + } else if (enlargement === minEnlargement) { + // otherwise choose one with the smallest area + if (area < minArea) { + minArea = area; + targetNode = child; + } + } + } + + node = targetNode || node.children[0]; + } + + return node; + }, + + _insert: function (item, level, isNode) { + + var toBBox = this.toBBox, + bbox = isNode ? item : toBBox(item), + insertPath = []; + + // find the best node for accommodating the item, saving all nodes along the path too + var node = this._chooseSubtree(bbox, this.data, level, insertPath); + + // put the item into the node + node.children.push(item); + extend(node, bbox); + + // split on node overflow; propagate upwards if necessary + while (level >= 0) { + if (insertPath[level].children.length > this._maxEntries) { + this._split(insertPath, level); + level--; + } else break; + } + + // adjust bboxes along the insertion path + this._adjustParentBBoxes(bbox, insertPath, level); + }, + + // split overflowed node into two + _split: function (insertPath, level) { + + var node = insertPath[level], + M = node.children.length, + m = this._minEntries; + + this._chooseSplitAxis(node, m, M); + + var splitIndex = this._chooseSplitIndex(node, m, M); + + var newNode = createNode(node.children.splice(splitIndex, node.children.length - splitIndex)); + newNode.height = node.height; + newNode.leaf = node.leaf; + + calcBBox(node, this.toBBox); + calcBBox(newNode, this.toBBox); + + if (level) insertPath[level - 1].children.push(newNode); + else this._splitRoot(node, newNode); + }, + + _splitRoot: function (node, newNode) { + // split root node + this.data = createNode([node, newNode]); + this.data.height = node.height + 1; + this.data.leaf = false; + calcBBox(this.data, this.toBBox); + }, + + _chooseSplitIndex: function (node, m, M) { + + var i, bbox1, bbox2, overlap, area, minOverlap, minArea, index; + + minOverlap = minArea = Infinity; + + for (i = m; i <= M - m; i++) { + bbox1 = distBBox(node, 0, i, this.toBBox); + bbox2 = distBBox(node, i, M, this.toBBox); + + overlap = intersectionArea(bbox1, bbox2); + area = bboxArea(bbox1) + bboxArea(bbox2); + + // choose distribution with minimum overlap + if (overlap < minOverlap) { + minOverlap = overlap; + index = i; + + minArea = area < minArea ? area : minArea; + + } else if (overlap === minOverlap) { + // otherwise choose distribution with minimum area + if (area < minArea) { + minArea = area; + index = i; + } + } + } + + return index; + }, + + // sorts node children by the best axis for split + _chooseSplitAxis: function (node, m, M) { + + var compareMinX = node.leaf ? this.compareMinX : compareNodeMinX, + compareMinY = node.leaf ? this.compareMinY : compareNodeMinY, + xMargin = this._allDistMargin(node, m, M, compareMinX), + yMargin = this._allDistMargin(node, m, M, compareMinY); + + // if total distributions margin value is minimal for x, sort by minX, + // otherwise it's already sorted by minY + if (xMargin < yMargin) node.children.sort(compareMinX); + }, + + // total margin of all possible split distributions where each node is at least m full + _allDistMargin: function (node, m, M, compare) { + + node.children.sort(compare); + + var toBBox = this.toBBox, + leftBBox = distBBox(node, 0, m, toBBox), + rightBBox = distBBox(node, M - m, M, toBBox), + margin = bboxMargin(leftBBox) + bboxMargin(rightBBox), + i, child; + + for (i = m; i < M - m; i++) { + child = node.children[i]; + extend(leftBBox, node.leaf ? toBBox(child) : child); + margin += bboxMargin(leftBBox); + } + + for (i = M - m - 1; i >= m; i--) { + child = node.children[i]; + extend(rightBBox, node.leaf ? toBBox(child) : child); + margin += bboxMargin(rightBBox); + } + + return margin; + }, + + _adjustParentBBoxes: function (bbox, path, level) { + // adjust bboxes along the given tree path + for (var i = level; i >= 0; i--) { + extend(path[i], bbox); + } + }, + + _condense: function (path) { + // go through the path, removing empty nodes and updating bboxes + for (var i = path.length - 1, siblings; i >= 0; i--) { + if (path[i].children.length === 0) { + if (i > 0) { + siblings = path[i - 1].children; + siblings.splice(siblings.indexOf(path[i]), 1); + + } else this.clear(); + + } else calcBBox(path[i], this.toBBox); + } + }, + + _initFormat: function (format) { + // data format (minX, minY, maxX, maxY accessors) + + // uses eval-type function compilation instead of just accepting a toBBox function + // because the algorithms are very sensitive to sorting functions performance, + // so they should be dead simple and without inner calls + + var compareArr = ['return a', ' - b', ';']; + + this.compareMinX = new Function('a', 'b', compareArr.join(format[0])); + this.compareMinY = new Function('a', 'b', compareArr.join(format[1])); + + this.toBBox = new Function('a', + 'return {minX: a' + format[0] + + ', minY: a' + format[1] + + ', maxX: a' + format[2] + + ', maxY: a' + format[3] + '};'); + } +}; + +function findItem(item, items, equalsFn) { + if (!equalsFn) return items.indexOf(item); + + for (var i = 0; i < items.length; i++) { + if (equalsFn(item, items[i])) return i; + } + return -1; +} + +// calculate node's bbox from bboxes of its children +function calcBBox(node, toBBox) { + distBBox(node, 0, node.children.length, toBBox, node); +} + +// min bounding rectangle of node children from k to p-1 +function distBBox(node, k, p, toBBox, destNode) { + if (!destNode) destNode = createNode(null); + destNode.minX = Infinity; + destNode.minY = Infinity; + destNode.maxX = -Infinity; + destNode.maxY = -Infinity; + + for (var i = k, child; i < p; i++) { + child = node.children[i]; + extend(destNode, node.leaf ? toBBox(child) : child); + } + + return destNode; +} + +function extend(a, b) { + a.minX = Math.min(a.minX, b.minX); + a.minY = Math.min(a.minY, b.minY); + a.maxX = Math.max(a.maxX, b.maxX); + a.maxY = Math.max(a.maxY, b.maxY); + return a; +} + +function compareNodeMinX(a, b) { return a.minX - b.minX; } +function compareNodeMinY(a, b) { return a.minY - b.minY; } + +function bboxArea(a) { return (a.maxX - a.minX) * (a.maxY - a.minY); } +function bboxMargin(a) { return (a.maxX - a.minX) + (a.maxY - a.minY); } + +function enlargedArea(a, b) { + return (Math.max(b.maxX, a.maxX) - Math.min(b.minX, a.minX)) * + (Math.max(b.maxY, a.maxY) - Math.min(b.minY, a.minY)); +} + +function intersectionArea(a, b) { + var minX = Math.max(a.minX, b.minX), + minY = Math.max(a.minY, b.minY), + maxX = Math.min(a.maxX, b.maxX), + maxY = Math.min(a.maxY, b.maxY); + + return Math.max(0, maxX - minX) * + Math.max(0, maxY - minY); +} + +function contains(a, b) { + return a.minX <= b.minX && + a.minY <= b.minY && + b.maxX <= a.maxX && + b.maxY <= a.maxY; +} + +function intersects(a, b) { + return b.minX <= a.maxX && + b.minY <= a.maxY && + b.maxX >= a.minX && + b.maxY >= a.minY; +} + +function createNode(children) { + return { + children: children, + height: 1, + leaf: true, + minX: Infinity, + minY: Infinity, + maxX: -Infinity, + maxY: -Infinity + }; +} + +// sort an array so that items come in groups of n unsorted items, with groups sorted between each other; +// combines selection algorithm with binary divide & conquer approach + +function multiSelect(arr, left, right, n, compare) { + var stack = [left, right], + mid; + + while (stack.length) { + right = stack.pop(); + left = stack.pop(); + + if (right - left <= n) continue; + + mid = left + Math.ceil((right - left) / n / 2) * n; + quickselect(arr, mid, left, right, compare); + + stack.push(left, mid, mid, right); + } +} + + +/***/ }), +/* 1 */, +/* 2 */, +/* 3 */, +/* 4 */, +/* 5 */, +/* 6 */, +/* 7 */, +/* 8 */, +/* 9 */, +/* 10 */ +/***/ (function(module, exports, __webpack_require__) { + +__webpack_require__(13); +module.exports = __webpack_require__(12); + + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +(function (global, factory) { + true ? module.exports = factory() : + undefined; +}(this, (function () { 'use strict'; + +function quickselect(arr, k, left, right, compare) { + quickselectStep(arr, k, left || 0, right || (arr.length - 1), compare || defaultCompare); +} + +function quickselectStep(arr, k, left, right, compare) { + + while (right > left) { + if (right - left > 600) { + var n = right - left + 1; + var m = k - left + 1; + var z = Math.log(n); + var s = 0.5 * Math.exp(2 * z / 3); + var sd = 0.5 * Math.sqrt(z * s * (n - s) / n) * (m - n / 2 < 0 ? -1 : 1); + var newLeft = Math.max(left, Math.floor(k - m * s / n + sd)); + var newRight = Math.min(right, Math.floor(k + (n - m) * s / n + sd)); + quickselectStep(arr, k, newLeft, newRight, compare); + } + + var t = arr[k]; + var i = left; + var j = right; + + swap(arr, left, k); + if (compare(arr[right], t) > 0) swap(arr, left, right); + + while (i < j) { + swap(arr, i, j); + i++; + j--; + while (compare(arr[i], t) < 0) i++; + while (compare(arr[j], t) > 0) j--; + } + + if (compare(arr[left], t) === 0) swap(arr, left, j); + else { + j++; + swap(arr, j, right); + } + + if (j <= k) left = j + 1; + if (k <= j) right = j - 1; + } +} + +function swap(arr, i, j) { + var tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; +} + +function defaultCompare(a, b) { + return a < b ? -1 : a > b ? 1 : 0; +} + +return quickselect; + +}))); + + +/***/ }), +/* 12 */ +/***/ (function(module, exports, __webpack_require__) { + +// extracted by mini-css-extract-plugin + +/***/ }), +/* 13 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +__webpack_require__.r(__webpack_exports__); + +// CONCATENATED MODULE: ./node_modules/ol/util.js +/** + * @module ol/util + */ + +/** + * @return {?} Any return. + */ +function util_abstract() { + return /** @type {?} */ ((function() { + throw new Error('Unimplemented abstract method.'); + })()); +} + +/** + * Inherit the prototype methods from one constructor into another. + * + * Usage: + * + * function ParentClass(a, b) { } + * ParentClass.prototype.foo = function(a) { } + * + * function ChildClass(a, b, c) { + * // Call parent constructor + * ParentClass.call(this, a, b); + * } + * inherits(ChildClass, ParentClass); + * + * var child = new ChildClass('a', 'b', 'see'); + * child.foo(); // This works. + * + * @param {!Function} childCtor Child constructor. + * @param {!Function} parentCtor Parent constructor. + * @function module:ol.inherits + * @deprecated + * @api + */ +function inherits(childCtor, parentCtor) { + childCtor.prototype = Object.create(parentCtor.prototype); + childCtor.prototype.constructor = childCtor; +} + +/** + * Counter for getUid. + * @type {number} + * @private + */ +var uidCounter_ = 0; + +/** + * Gets a unique ID for an object. This mutates the object so that further calls + * with the same object as a parameter returns the same value. Unique IDs are generated + * as a strictly increasing sequence. Adapted from goog.getUid. + * + * @param {Object} obj The object to get the unique ID for. + * @return {string} The unique ID for the object. + * @function module:ol.getUid + * @api + */ +function getUid(obj) { + return obj.ol_uid || (obj.ol_uid = String(++uidCounter_)); +} + +/** + * OpenLayers version. + * @type {string} + */ +var VERSION = '5.3.3'; + +//# sourceMappingURL=util.js.map +// CONCATENATED MODULE: ./node_modules/ol/AssertionError.js +/** + * @module ol/AssertionError + */ + + +/** + * Error object thrown when an assertion failed. This is an ECMA-262 Error, + * extended with a `code` property. + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error. + */ +var AssertionError_AssertionError = /*@__PURE__*/(function (Error) { + function AssertionError(code) { + var path = VERSION === 'latest' ? VERSION : 'v' + VERSION.split('-')[0]; + var message = 'Assertion failed. See https://openlayers.org/en/' + path + + '/doc/errors/#' + code + ' for details.'; + + Error.call(this, message); + + /** + * Error code. The meaning of the code can be found on + * https://openlayers.org/en/latest/doc/errors/ (replace `latest` with + * the version found in the OpenLayers script's header comment if a version + * other than the latest is used). + * @type {number} + * @api + */ + this.code = code; + + /** + * @type {string} + */ + this.name = 'AssertionError'; + + // Re-assign message, see https://github.com/Rich-Harris/buble/issues/40 + this.message = message; + } + + if ( Error ) AssertionError.__proto__ = Error; + AssertionError.prototype = Object.create( Error && Error.prototype ); + AssertionError.prototype.constructor = AssertionError; + + return AssertionError; +}(Error)); + +/* harmony default export */ var ol_AssertionError = (AssertionError_AssertionError); + +//# sourceMappingURL=AssertionError.js.map +// CONCATENATED MODULE: ./node_modules/ol/CollectionEventType.js +/** + * @module ol/CollectionEventType + */ + +/** + * @enum {string} + */ +/* harmony default export */ var CollectionEventType = ({ + /** + * Triggered when an item is added to the collection. + * @event module:ol/Collection.CollectionEvent#add + * @api + */ + ADD: 'add', + /** + * Triggered when an item is removed from the collection. + * @event module:ol/Collection.CollectionEvent#remove + * @api + */ + REMOVE: 'remove' +}); + +//# sourceMappingURL=CollectionEventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/ObjectEventType.js +/** + * @module ol/ObjectEventType + */ + +/** + * @enum {string} + */ +/* harmony default export */ var ObjectEventType = ({ + /** + * Triggered when a property is changed. + * @event module:ol/Object.ObjectEvent#propertychange + * @api + */ + PROPERTYCHANGE: 'propertychange' +}); + +//# sourceMappingURL=ObjectEventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/obj.js +/** + * @module ol/obj + */ + + +/** + * Polyfill for Object.assign(). Assigns enumerable and own properties from + * one or more source objects to a target object. + * See https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/assign. + * + * @param {!Object} target The target object. + * @param {...Object} var_sources The source object(s). + * @return {!Object} The modified target object. + */ +var obj_assign = (typeof Object.assign === 'function') ? Object.assign : function(target, var_sources) { + var arguments$1 = arguments; + + if (target === undefined || target === null) { + throw new TypeError('Cannot convert undefined or null to object'); + } + + var output = Object(target); + for (var i = 1, ii = arguments.length; i < ii; ++i) { + var source = arguments$1[i]; + if (source !== undefined && source !== null) { + for (var key in source) { + if (source.hasOwnProperty(key)) { + output[key] = source[key]; + } + } + } + } + return output; +}; + + +/** + * Removes all properties from an object. + * @param {Object} object The object to clear. + */ +function obj_clear(object) { + for (var property in object) { + delete object[property]; + } +} + + +/** + * Get an array of property values from an object. + * @param {Object} object The object from which to get the values. + * @return {!Array} The property values. + * @template K,V + */ +function getValues(object) { + var values = []; + for (var property in object) { + values.push(object[property]); + } + return values; +} + + +/** + * Determine if an object has any properties. + * @param {Object} object The object to check. + * @return {boolean} The object is empty. + */ +function obj_isEmpty(object) { + var property; + for (property in object) { + return false; + } + return !property; +} + +//# sourceMappingURL=obj.js.map +// CONCATENATED MODULE: ./node_modules/ol/events.js +/** + * @module ol/events + */ + + + +/** + * Key to use with {@link module:ol/Observable~Observable#unByKey}. + * @typedef {Object} EventsKey + * @property {Object} [bindTo] + * @property {ListenerFunction} [boundListener] + * @property {boolean} callOnce + * @property {number} [deleteIndex] + * @property {ListenerFunction} listener + * @property {import("./events/Target.js").EventTargetLike} target + * @property {string} type + * @api + */ + + +/** + * Listener function. This function is called with an event object as argument. + * When the function returns `false`, event propagation will stop. + * + * @typedef {function((Event|import("./events/Event.js").default)): (void|boolean)} ListenerFunction + * @api + */ + + +/** + * @param {EventsKey} listenerObj Listener object. + * @return {ListenerFunction} Bound listener. + */ +function bindListener(listenerObj) { + var boundListener = function(evt) { + var listener = listenerObj.listener; + var bindTo = listenerObj.bindTo || listenerObj.target; + if (listenerObj.callOnce) { + unlistenByKey(listenerObj); + } + return listener.call(bindTo, evt); + }; + listenerObj.boundListener = boundListener; + return boundListener; +} + + +/** + * Finds the matching {@link module:ol/events~EventsKey} in the given listener + * array. + * + * @param {!Array} listeners Array of listeners. + * @param {!Function} listener The listener function. + * @param {Object=} opt_this The `this` value inside the listener. + * @param {boolean=} opt_setDeleteIndex Set the deleteIndex on the matching + * listener, for {@link module:ol/events~unlistenByKey}. + * @return {EventsKey|undefined} The matching listener object. + */ +function findListener(listeners, listener, opt_this, opt_setDeleteIndex) { + var listenerObj; + for (var i = 0, ii = listeners.length; i < ii; ++i) { + listenerObj = listeners[i]; + if (listenerObj.listener === listener && + listenerObj.bindTo === opt_this) { + if (opt_setDeleteIndex) { + listenerObj.deleteIndex = i; + } + return listenerObj; + } + } + return undefined; +} + + +/** + * @param {import("./events/Target.js").EventTargetLike} target Target. + * @param {string} type Type. + * @return {Array|undefined} Listeners. + */ +function getListeners(target, type) { + var listenerMap = getListenerMap(target); + return listenerMap ? listenerMap[type] : undefined; +} + + +/** + * Get the lookup of listeners. + * @param {Object} target Target. + * @param {boolean=} opt_create If a map should be created if it doesn't exist. + * @return {!Object>} Map of + * listeners by event type. + */ +function getListenerMap(target, opt_create) { + var listenerMap = target.ol_lm; + if (!listenerMap && opt_create) { + listenerMap = target.ol_lm = {}; + } + return listenerMap; +} + + +/** + * Remove the listener map from a target. + * @param {Object} target Target. + */ +function removeListenerMap(target) { + delete target.ol_lm; +} + + +/** + * Clean up all listener objects of the given type. All properties on the + * listener objects will be removed, and if no listeners remain in the listener + * map, it will be removed from the target. + * @param {import("./events/Target.js").EventTargetLike} target Target. + * @param {string} type Type. + */ +function removeListeners(target, type) { + var listeners = getListeners(target, type); + if (listeners) { + for (var i = 0, ii = listeners.length; i < ii; ++i) { + /** @type {import("./events/Target.js").default} */ (target). + removeEventListener(type, listeners[i].boundListener); + obj_clear(listeners[i]); + } + listeners.length = 0; + var listenerMap = getListenerMap(target); + if (listenerMap) { + delete listenerMap[type]; + if (Object.keys(listenerMap).length === 0) { + removeListenerMap(target); + } + } + } +} + + +/** + * Registers an event listener on an event target. Inspired by + * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html + * + * This function efficiently binds a `listener` to a `this` object, and returns + * a key for use with {@link module:ol/events~unlistenByKey}. + * + * @param {import("./events/Target.js").EventTargetLike} target Event target. + * @param {string} type Event type. + * @param {ListenerFunction} listener Listener. + * @param {Object=} opt_this Object referenced by the `this` keyword in the + * listener. Default is the `target`. + * @param {boolean=} opt_once If true, add the listener as one-off listener. + * @return {EventsKey} Unique key for the listener. + */ +function listen(target, type, listener, opt_this, opt_once) { + var listenerMap = getListenerMap(target, true); + var listeners = listenerMap[type]; + if (!listeners) { + listeners = listenerMap[type] = []; + } + var listenerObj = findListener(listeners, listener, opt_this, false); + if (listenerObj) { + if (!opt_once) { + // Turn one-off listener into a permanent one. + listenerObj.callOnce = false; + } + } else { + listenerObj = /** @type {EventsKey} */ ({ + bindTo: opt_this, + callOnce: !!opt_once, + listener: listener, + target: target, + type: type + }); + /** @type {import("./events/Target.js").default} */ (target). + addEventListener(type, bindListener(listenerObj)); + listeners.push(listenerObj); + } + + return listenerObj; +} + + +/** + * Registers a one-off event listener on an event target. Inspired by + * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html + * + * This function efficiently binds a `listener` as self-unregistering listener + * to a `this` object, and returns a key for use with + * {@link module:ol/events~unlistenByKey} in case the listener needs to be + * unregistered before it is called. + * + * When {@link module:ol/events~listen} is called with the same arguments after this + * function, the self-unregistering listener will be turned into a permanent + * listener. + * + * @param {import("./events/Target.js").EventTargetLike} target Event target. + * @param {string} type Event type. + * @param {ListenerFunction} listener Listener. + * @param {Object=} opt_this Object referenced by the `this` keyword in the + * listener. Default is the `target`. + * @return {EventsKey} Key for unlistenByKey. + */ +function listenOnce(target, type, listener, opt_this) { + return listen(target, type, listener, opt_this, true); +} + + +/** + * Unregisters an event listener on an event target. Inspired by + * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html + * + * To return a listener, this function needs to be called with the exact same + * arguments that were used for a previous {@link module:ol/events~listen} call. + * + * @param {import("./events/Target.js").EventTargetLike} target Event target. + * @param {string} type Event type. + * @param {ListenerFunction} listener Listener. + * @param {Object=} opt_this Object referenced by the `this` keyword in the + * listener. Default is the `target`. + */ +function unlisten(target, type, listener, opt_this) { + var listeners = getListeners(target, type); + if (listeners) { + var listenerObj = findListener(listeners, listener, opt_this, true); + if (listenerObj) { + unlistenByKey(listenerObj); + } + } +} + + +/** + * Unregisters event listeners on an event target. Inspired by + * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html + * + * The argument passed to this function is the key returned from + * {@link module:ol/events~listen} or {@link module:ol/events~listenOnce}. + * + * @param {EventsKey} key The key. + */ +function unlistenByKey(key) { + if (key && key.target) { + /** @type {import("./events/Target.js").default} */ (key.target). + removeEventListener(key.type, key.boundListener); + var listeners = getListeners(key.target, key.type); + if (listeners) { + var i = 'deleteIndex' in key ? key.deleteIndex : listeners.indexOf(key); + if (i !== -1) { + listeners.splice(i, 1); + } + if (listeners.length === 0) { + removeListeners(key.target, key.type); + } + } + obj_clear(key); + } +} + + +/** + * Unregisters all event listeners on an event target. Inspired by + * https://google.github.io/closure-library/api/source/closure/goog/events/events.js.src.html + * + * @param {import("./events/Target.js").EventTargetLike} target Target. + */ +function unlistenAll(target) { + var listenerMap = getListenerMap(target); + if (listenerMap) { + for (var type in listenerMap) { + removeListeners(target, type); + } + } +} + +//# sourceMappingURL=events.js.map +// CONCATENATED MODULE: ./node_modules/ol/Disposable.js +/** + * @module ol/Disposable + */ + +/** + * @classdesc + * Objects that need to clean up after themselves. + */ +var Disposable_Disposable = function Disposable() { + /** + * The object has already been disposed. + * @type {boolean} + * @private + */ + this.disposed_ = false; +}; + +/** + * Clean up. + */ +Disposable_Disposable.prototype.dispose = function dispose () { + if (!this.disposed_) { + this.disposed_ = true; + this.disposeInternal(); + } +}; + +/** + * Extension point for disposable objects. + * @protected + */ +Disposable_Disposable.prototype.disposeInternal = function disposeInternal () {}; + +/* harmony default export */ var ol_Disposable = (Disposable_Disposable); + +//# sourceMappingURL=Disposable.js.map +// CONCATENATED MODULE: ./node_modules/ol/functions.js +/** + * @module ol/functions + */ + +/** + * Always returns true. + * @returns {boolean} true. + */ +function TRUE() { + return true; +} + +/** + * Always returns false. + * @returns {boolean} false. + */ +function FALSE() { + return false; +} + +/** + * A reusable function, used e.g. as a default for callbacks. + * + * @return {void} Nothing. + */ +function VOID() {} + +//# sourceMappingURL=functions.js.map +// CONCATENATED MODULE: ./node_modules/ol/events/Event.js +/** + * @module ol/events/Event + */ + +/** + * @classdesc + * Stripped down implementation of the W3C DOM Level 2 Event interface. + * See https://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-interface. + * + * This implementation only provides `type` and `target` properties, and + * `stopPropagation` and `preventDefault` methods. It is meant as base class + * for higher level events defined in the library, and works with + * {@link module:ol/events/Target~Target}. + */ +var Event = function Event(type) { + + /** + * @type {boolean} + */ + this.propagationStopped; + + /** + * The event type. + * @type {string} + * @api + */ + this.type = type; + + /** + * The event target. + * @type {Object} + * @api + */ + this.target = null; +}; + +/** + * Stop event propagation. + * @api + */ +Event.prototype.preventDefault = function preventDefault () { + this.propagationStopped = true; +}; + +/** + * Stop event propagation. + * @api + */ +Event.prototype.stopPropagation = function stopPropagation () { + this.propagationStopped = true; +}; + + +/** + * @param {Event|import("./Event.js").default} evt Event + */ +function stopPropagation(evt) { + evt.stopPropagation(); +} + + +/** + * @param {Event|import("./Event.js").default} evt Event + */ +function preventDefault(evt) { + evt.preventDefault(); +} + +/* harmony default export */ var events_Event = (Event); + +//# sourceMappingURL=Event.js.map +// CONCATENATED MODULE: ./node_modules/ol/events/Target.js +/** + * @module ol/events/Target + */ + + + + + + +/** + * @typedef {EventTarget|Target} EventTargetLike + */ + + +/** + * @classdesc + * A simplified implementation of the W3C DOM Level 2 EventTarget interface. + * See https://www.w3.org/TR/2000/REC-DOM-Level-2-Events-20001113/events.html#Events-EventTarget. + * + * There are two important simplifications compared to the specification: + * + * 1. The handling of `useCapture` in `addEventListener` and + * `removeEventListener`. There is no real capture model. + * 2. The handling of `stopPropagation` and `preventDefault` on `dispatchEvent`. + * There is no event target hierarchy. When a listener calls + * `stopPropagation` or `preventDefault` on an event object, it means that no + * more listeners after this one will be called. Same as when the listener + * returns false. + */ +var Target_Target = /*@__PURE__*/(function (Disposable) { + function Target() { + + Disposable.call(this); + + /** + * @private + * @type {!Object} + */ + this.pendingRemovals_ = {}; + + /** + * @private + * @type {!Object} + */ + this.dispatching_ = {}; + + /** + * @private + * @type {!Object>} + */ + this.listeners_ = {}; + + } + + if ( Disposable ) Target.__proto__ = Disposable; + Target.prototype = Object.create( Disposable && Disposable.prototype ); + Target.prototype.constructor = Target; + + /** + * @param {string} type Type. + * @param {import("../events.js").ListenerFunction} listener Listener. + */ + Target.prototype.addEventListener = function addEventListener (type, listener) { + var listeners = this.listeners_[type]; + if (!listeners) { + listeners = this.listeners_[type] = []; + } + if (listeners.indexOf(listener) === -1) { + listeners.push(listener); + } + }; + + /** + * Dispatches an event and calls all listeners listening for events + * of this type. The event parameter can either be a string or an + * Object with a `type` property. + * + * @param {{type: string, + * target: (EventTargetLike|undefined), + * propagationStopped: (boolean|undefined)}| + * import("./Event.js").default|string} event Event object. + * @return {boolean|undefined} `false` if anyone called preventDefault on the + * event object or if any of the listeners returned false. + * @api + */ + Target.prototype.dispatchEvent = function dispatchEvent (event) { + var evt = typeof event === 'string' ? new events_Event(event) : event; + var type = evt.type; + evt.target = this; + var listeners = this.listeners_[type]; + var propagate; + if (listeners) { + if (!(type in this.dispatching_)) { + this.dispatching_[type] = 0; + this.pendingRemovals_[type] = 0; + } + ++this.dispatching_[type]; + for (var i = 0, ii = listeners.length; i < ii; ++i) { + if (listeners[i].call(this, evt) === false || evt.propagationStopped) { + propagate = false; + break; + } + } + --this.dispatching_[type]; + if (this.dispatching_[type] === 0) { + var pendingRemovals = this.pendingRemovals_[type]; + delete this.pendingRemovals_[type]; + while (pendingRemovals--) { + this.removeEventListener(type, VOID); + } + delete this.dispatching_[type]; + } + return propagate; + } + }; + + /** + * @inheritDoc + */ + Target.prototype.disposeInternal = function disposeInternal () { + unlistenAll(this); + }; + + /** + * Get the listeners for a specified event type. Listeners are returned in the + * order that they will be called in. + * + * @param {string} type Type. + * @return {Array} Listeners. + */ + Target.prototype.getListeners = function getListeners (type) { + return this.listeners_[type]; + }; + + /** + * @param {string=} opt_type Type. If not provided, + * `true` will be returned if this event target has any listeners. + * @return {boolean} Has listeners. + */ + Target.prototype.hasListener = function hasListener (opt_type) { + return opt_type ? + opt_type in this.listeners_ : + Object.keys(this.listeners_).length > 0; + }; + + /** + * @param {string} type Type. + * @param {import("../events.js").ListenerFunction} listener Listener. + */ + Target.prototype.removeEventListener = function removeEventListener (type, listener) { + var listeners = this.listeners_[type]; + if (listeners) { + var index = listeners.indexOf(listener); + if (type in this.pendingRemovals_) { + // make listener a no-op, and remove later in #dispatchEvent() + listeners[index] = VOID; + ++this.pendingRemovals_[type]; + } else { + listeners.splice(index, 1); + if (listeners.length === 0) { + delete this.listeners_[type]; + } + } + } + }; + + return Target; +}(ol_Disposable)); + + +/* harmony default export */ var events_Target = (Target_Target); + +//# sourceMappingURL=Target.js.map +// CONCATENATED MODULE: ./node_modules/ol/events/EventType.js +/** + * @module ol/events/EventType + */ + +/** + * @enum {string} + * @const + */ +/* harmony default export */ var EventType = ({ + /** + * Generic change event. Triggered when the revision counter is increased. + * @event module:ol/events/Event~Event#change + * @api + */ + CHANGE: 'change', + + CLEAR: 'clear', + CONTEXTMENU: 'contextmenu', + CLICK: 'click', + DBLCLICK: 'dblclick', + DRAGENTER: 'dragenter', + DRAGOVER: 'dragover', + DROP: 'drop', + ERROR: 'error', + KEYDOWN: 'keydown', + KEYPRESS: 'keypress', + LOAD: 'load', + MOUSEDOWN: 'mousedown', + MOUSEMOVE: 'mousemove', + MOUSEOUT: 'mouseout', + MOUSEUP: 'mouseup', + MOUSEWHEEL: 'mousewheel', + MSPOINTERDOWN: 'MSPointerDown', + RESIZE: 'resize', + TOUCHSTART: 'touchstart', + TOUCHMOVE: 'touchmove', + TOUCHEND: 'touchend', + WHEEL: 'wheel' +}); + +//# sourceMappingURL=EventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/Observable.js +/** + * @module ol/Observable + */ + + + + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * An event target providing convenient methods for listener registration + * and unregistration. A generic `change` event is always available through + * {@link module:ol/Observable~Observable#changed}. + * + * @fires import("./events/Event.js").Event + * @api + */ +var Observable_Observable = /*@__PURE__*/(function (EventTarget) { + function Observable() { + + EventTarget.call(this); + + /** + * @private + * @type {number} + */ + this.revision_ = 0; + + } + + if ( EventTarget ) Observable.__proto__ = EventTarget; + Observable.prototype = Object.create( EventTarget && EventTarget.prototype ); + Observable.prototype.constructor = Observable; + + /** + * Increases the revision counter and dispatches a 'change' event. + * @api + */ + Observable.prototype.changed = function changed () { + ++this.revision_; + this.dispatchEvent(EventType.CHANGE); + }; + + /** + * Get the version number for this object. Each time the object is modified, + * its version number will be incremented. + * @return {number} Revision. + * @api + */ + Observable.prototype.getRevision = function getRevision () { + return this.revision_; + }; + + /** + * Listen for a certain type of event. + * @param {string|Array} type The event type or array of event types. + * @param {function(?): ?} listener The listener function. + * @return {import("./events.js").EventsKey|Array} Unique key for the listener. If + * called with an array of event types as the first argument, the return + * will be an array of keys. + * @api + */ + Observable.prototype.on = function on (type, listener) { + if (Array.isArray(type)) { + var len = type.length; + var keys = new Array(len); + for (var i = 0; i < len; ++i) { + keys[i] = listen(this, type[i], listener); + } + return keys; + } else { + return listen(this, /** @type {string} */ (type), listener); + } + }; + + /** + * Listen once for a certain type of event. + * @param {string|Array} type The event type or array of event types. + * @param {function(?): ?} listener The listener function. + * @return {import("./events.js").EventsKey|Array} Unique key for the listener. If + * called with an array of event types as the first argument, the return + * will be an array of keys. + * @api + */ + Observable.prototype.once = function once (type, listener) { + if (Array.isArray(type)) { + var len = type.length; + var keys = new Array(len); + for (var i = 0; i < len; ++i) { + keys[i] = listenOnce(this, type[i], listener); + } + return keys; + } else { + return listenOnce(this, /** @type {string} */ (type), listener); + } + }; + + /** + * Unlisten for a certain type of event. + * @param {string|Array} type The event type or array of event types. + * @param {function(?): ?} listener The listener function. + * @api + */ + Observable.prototype.un = function un (type, listener) { + if (Array.isArray(type)) { + for (var i = 0, ii = type.length; i < ii; ++i) { + unlisten(this, type[i], listener); + } + return; + } else { + unlisten(this, /** @type {string} */ (type), listener); + } + }; + + return Observable; +}(events_Target)); + + +/** + * Removes an event listener using the key returned by `on()` or `once()`. + * @param {import("./events.js").EventsKey|Array} key The key returned by `on()` + * or `once()` (or an array of keys). + * @api + */ +function unByKey(key) { + if (Array.isArray(key)) { + for (var i = 0, ii = key.length; i < ii; ++i) { + unlistenByKey(key[i]); + } + } else { + unlistenByKey(/** @type {import("./events.js").EventsKey} */ (key)); + } +} + + +/* harmony default export */ var ol_Observable = (Observable_Observable); + +//# sourceMappingURL=Observable.js.map +// CONCATENATED MODULE: ./node_modules/ol/Object.js +/** + * @module ol/Object + */ + + + + + + + +/** + * @classdesc + * Events emitted by {@link module:ol/Object~BaseObject} instances are instances of this type. + */ +var ObjectEvent = /*@__PURE__*/(function (Event) { + function ObjectEvent(type, key, oldValue) { + Event.call(this, type); + + /** + * The name of the property whose value is changing. + * @type {string} + * @api + */ + this.key = key; + + /** + * The old value. To get the new value use `e.target.get(e.key)` where + * `e` is the event object. + * @type {*} + * @api + */ + this.oldValue = oldValue; + + } + + if ( Event ) ObjectEvent.__proto__ = Event; + ObjectEvent.prototype = Object.create( Event && Event.prototype ); + ObjectEvent.prototype.constructor = ObjectEvent; + + return ObjectEvent; +}(events_Event)); + + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * Most non-trivial classes inherit from this. + * + * This extends {@link module:ol/Observable} with observable + * properties, where each property is observable as well as the object as a + * whole. + * + * Classes that inherit from this have pre-defined properties, to which you can + * add your owns. The pre-defined properties are listed in this documentation as + * 'Observable Properties', and have their own accessors; for example, + * {@link module:ol/Map~Map} has a `target` property, accessed with + * `getTarget()` and changed with `setTarget()`. Not all properties are however + * settable. There are also general-purpose accessors `get()` and `set()`. For + * example, `get('target')` is equivalent to `getTarget()`. + * + * The `set` accessors trigger a change event, and you can monitor this by + * registering a listener. For example, {@link module:ol/View~View} has a + * `center` property, so `view.on('change:center', function(evt) {...});` would + * call the function whenever the value of the center property changes. Within + * the function, `evt.target` would be the view, so `evt.target.getCenter()` + * would return the new center. + * + * You can add your own observable properties with + * `object.set('prop', 'value')`, and retrieve that with `object.get('prop')`. + * You can listen for changes on that property value with + * `object.on('change:prop', listener)`. You can get a list of all + * properties with {@link module:ol/Object~BaseObject#getProperties}. + * + * Note that the observable properties are separate from standard JS properties. + * You can, for example, give your map object a title with + * `map.title='New title'` and with `map.set('title', 'Another title')`. The + * first will be a `hasOwnProperty`; the second will appear in + * `getProperties()`. Only the second is observable. + * + * Properties can be deleted by using the unset method. E.g. + * object.unset('foo'). + * + * @fires ObjectEvent + * @api + */ +var Object_BaseObject = /*@__PURE__*/(function (Observable) { + function BaseObject(opt_values) { + Observable.call(this); + + // Call {@link module:ol/util~getUid} to ensure that the order of objects' ids is + // the same as the order in which they were created. This also helps to + // ensure that object properties are always added in the same order, which + // helps many JavaScript engines generate faster code. + getUid(this); + + /** + * @private + * @type {!Object} + */ + this.values_ = {}; + + if (opt_values !== undefined) { + this.setProperties(opt_values); + } + } + + if ( Observable ) BaseObject.__proto__ = Observable; + BaseObject.prototype = Object.create( Observable && Observable.prototype ); + BaseObject.prototype.constructor = BaseObject; + + /** + * Gets a value. + * @param {string} key Key name. + * @return {*} Value. + * @api + */ + BaseObject.prototype.get = function get (key) { + var value; + if (this.values_.hasOwnProperty(key)) { + value = this.values_[key]; + } + return value; + }; + + /** + * Get a list of object property names. + * @return {Array} List of property names. + * @api + */ + BaseObject.prototype.getKeys = function getKeys () { + return Object.keys(this.values_); + }; + + /** + * Get an object of all property names and values. + * @return {Object} Object. + * @api + */ + BaseObject.prototype.getProperties = function getProperties () { + return obj_assign({}, this.values_); + }; + + /** + * @param {string} key Key name. + * @param {*} oldValue Old value. + */ + BaseObject.prototype.notify = function notify (key, oldValue) { + var eventType; + eventType = getChangeEventType(key); + this.dispatchEvent(new ObjectEvent(eventType, key, oldValue)); + eventType = ObjectEventType.PROPERTYCHANGE; + this.dispatchEvent(new ObjectEvent(eventType, key, oldValue)); + }; + + /** + * Sets a value. + * @param {string} key Key name. + * @param {*} value Value. + * @param {boolean=} opt_silent Update without triggering an event. + * @api + */ + BaseObject.prototype.set = function set (key, value, opt_silent) { + if (opt_silent) { + this.values_[key] = value; + } else { + var oldValue = this.values_[key]; + this.values_[key] = value; + if (oldValue !== value) { + this.notify(key, oldValue); + } + } + }; + + /** + * Sets a collection of key-value pairs. Note that this changes any existing + * properties and adds new ones (it does not remove any existing properties). + * @param {Object} values Values. + * @param {boolean=} opt_silent Update without triggering an event. + * @api + */ + BaseObject.prototype.setProperties = function setProperties (values, opt_silent) { + for (var key in values) { + this.set(key, values[key], opt_silent); + } + }; + + /** + * Unsets a property. + * @param {string} key Key name. + * @param {boolean=} opt_silent Unset without triggering an event. + * @api + */ + BaseObject.prototype.unset = function unset (key, opt_silent) { + if (key in this.values_) { + var oldValue = this.values_[key]; + delete this.values_[key]; + if (!opt_silent) { + this.notify(key, oldValue); + } + } + }; + + return BaseObject; +}(ol_Observable)); + + +/** + * @type {Object} + */ +var changeEventTypeCache = {}; + + +/** + * @param {string} key Key name. + * @return {string} Change name. + */ +function getChangeEventType(key) { + return changeEventTypeCache.hasOwnProperty(key) ? + changeEventTypeCache[key] : + (changeEventTypeCache[key] = 'change:' + key); +} + + +/* harmony default export */ var ol_Object = (Object_BaseObject); + +//# sourceMappingURL=Object.js.map +// CONCATENATED MODULE: ./node_modules/ol/Collection.js +/** + * @module ol/Collection + */ + + + + + + +/** + * @enum {string} + * @private + */ +var Property = { + LENGTH: 'length' +}; + + +/** + * @classdesc + * Events emitted by {@link module:ol/Collection~Collection} instances are instances of this + * type. + */ +var CollectionEvent = /*@__PURE__*/(function (Event) { + function CollectionEvent(type, opt_element) { + Event.call(this, type); + + /** + * The element that is added to or removed from the collection. + * @type {*} + * @api + */ + this.element = opt_element; + + } + + if ( Event ) CollectionEvent.__proto__ = Event; + CollectionEvent.prototype = Object.create( Event && Event.prototype ); + CollectionEvent.prototype.constructor = CollectionEvent; + + return CollectionEvent; +}(events_Event)); + + +/** + * @typedef {Object} Options + * @property {boolean} [unique=false] Disallow the same item from being added to + * the collection twice. + */ + +/** + * @classdesc + * An expanded version of standard JS Array, adding convenience methods for + * manipulation. Add and remove changes to the Collection trigger a Collection + * event. Note that this does not cover changes to the objects _within_ the + * Collection; they trigger events on the appropriate object, not on the + * Collection as a whole. + * + * @fires CollectionEvent + * + * @template T + * @api + */ +var Collection_Collection = /*@__PURE__*/(function (BaseObject) { + function Collection(opt_array, opt_options) { + + BaseObject.call(this); + + var options = opt_options || {}; + + /** + * @private + * @type {boolean} + */ + this.unique_ = !!options.unique; + + /** + * @private + * @type {!Array} + */ + this.array_ = opt_array ? opt_array : []; + + if (this.unique_) { + for (var i = 0, ii = this.array_.length; i < ii; ++i) { + this.assertUnique_(this.array_[i], i); + } + } + + this.updateLength_(); + + } + + if ( BaseObject ) Collection.__proto__ = BaseObject; + Collection.prototype = Object.create( BaseObject && BaseObject.prototype ); + Collection.prototype.constructor = Collection; + + /** + * Remove all elements from the collection. + * @api + */ + Collection.prototype.clear = function clear () { + while (this.getLength() > 0) { + this.pop(); + } + }; + + /** + * Add elements to the collection. This pushes each item in the provided array + * to the end of the collection. + * @param {!Array} arr Array. + * @return {Collection} This collection. + * @api + */ + Collection.prototype.extend = function extend (arr) { + for (var i = 0, ii = arr.length; i < ii; ++i) { + this.push(arr[i]); + } + return this; + }; + + /** + * Iterate over each element, calling the provided callback. + * @param {function(T, number, Array): *} f The function to call + * for every element. This function takes 3 arguments (the element, the + * index and the array). The return value is ignored. + * @api + */ + Collection.prototype.forEach = function forEach (f) { + var array = this.array_; + for (var i = 0, ii = array.length; i < ii; ++i) { + f(array[i], i, array); + } + }; + + /** + * Get a reference to the underlying Array object. Warning: if the array + * is mutated, no events will be dispatched by the collection, and the + * collection's "length" property won't be in sync with the actual length + * of the array. + * @return {!Array} Array. + * @api + */ + Collection.prototype.getArray = function getArray () { + return this.array_; + }; + + /** + * Get the element at the provided index. + * @param {number} index Index. + * @return {T} Element. + * @api + */ + Collection.prototype.item = function item (index) { + return this.array_[index]; + }; + + /** + * Get the length of this collection. + * @return {number} The length of the array. + * @observable + * @api + */ + Collection.prototype.getLength = function getLength () { + return this.get(Property.LENGTH); + }; + + /** + * Insert an element at the provided index. + * @param {number} index Index. + * @param {T} elem Element. + * @api + */ + Collection.prototype.insertAt = function insertAt (index, elem) { + if (this.unique_) { + this.assertUnique_(elem); + } + this.array_.splice(index, 0, elem); + this.updateLength_(); + this.dispatchEvent( + new CollectionEvent(CollectionEventType.ADD, elem)); + }; + + /** + * Remove the last element of the collection and return it. + * Return `undefined` if the collection is empty. + * @return {T|undefined} Element. + * @api + */ + Collection.prototype.pop = function pop () { + return this.removeAt(this.getLength() - 1); + }; + + /** + * Insert the provided element at the end of the collection. + * @param {T} elem Element. + * @return {number} New length of the collection. + * @api + */ + Collection.prototype.push = function push (elem) { + if (this.unique_) { + this.assertUnique_(elem); + } + var n = this.getLength(); + this.insertAt(n, elem); + return this.getLength(); + }; + + /** + * Remove the first occurrence of an element from the collection. + * @param {T} elem Element. + * @return {T|undefined} The removed element or undefined if none found. + * @api + */ + Collection.prototype.remove = function remove (elem) { + var arr = this.array_; + for (var i = 0, ii = arr.length; i < ii; ++i) { + if (arr[i] === elem) { + return this.removeAt(i); + } + } + return undefined; + }; + + /** + * Remove the element at the provided index and return it. + * Return `undefined` if the collection does not contain this index. + * @param {number} index Index. + * @return {T|undefined} Value. + * @api + */ + Collection.prototype.removeAt = function removeAt (index) { + var prev = this.array_[index]; + this.array_.splice(index, 1); + this.updateLength_(); + this.dispatchEvent(new CollectionEvent(CollectionEventType.REMOVE, prev)); + return prev; + }; + + /** + * Set the element at the provided index. + * @param {number} index Index. + * @param {T} elem Element. + * @api + */ + Collection.prototype.setAt = function setAt (index, elem) { + var n = this.getLength(); + if (index < n) { + if (this.unique_) { + this.assertUnique_(elem, index); + } + var prev = this.array_[index]; + this.array_[index] = elem; + this.dispatchEvent( + new CollectionEvent(CollectionEventType.REMOVE, prev)); + this.dispatchEvent( + new CollectionEvent(CollectionEventType.ADD, elem)); + } else { + for (var j = n; j < index; ++j) { + this.insertAt(j, undefined); + } + this.insertAt(index, elem); + } + }; + + /** + * @private + */ + Collection.prototype.updateLength_ = function updateLength_ () { + this.set(Property.LENGTH, this.array_.length); + }; + + /** + * @private + * @param {T} elem Element. + * @param {number=} opt_except Optional index to ignore. + */ + Collection.prototype.assertUnique_ = function assertUnique_ (elem, opt_except) { + for (var i = 0, ii = this.array_.length; i < ii; ++i) { + if (this.array_[i] === elem && i !== opt_except) { + throw new ol_AssertionError(58); + } + } + }; + + return Collection; +}(ol_Object)); + + +/* harmony default export */ var ol_Collection = (Collection_Collection); + +//# sourceMappingURL=Collection.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapEvent.js +/** + * @module ol/MapEvent + */ + + +/** + * @classdesc + * Events emitted as map events are instances of this type. + * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map event. + */ +var MapEvent = /*@__PURE__*/(function (Event) { + function MapEvent(type, map, opt_frameState) { + + Event.call(this, type); + + /** + * The map where the event occurred. + * @type {import("./PluggableMap.js").default} + * @api + */ + this.map = map; + + /** + * The frame state at the time of the event. + * @type {?import("./PluggableMap.js").FrameState} + * @api + */ + this.frameState = opt_frameState !== undefined ? opt_frameState : null; + + } + + if ( Event ) MapEvent.__proto__ = Event; + MapEvent.prototype = Object.create( Event && Event.prototype ); + MapEvent.prototype.constructor = MapEvent; + + return MapEvent; +}(events_Event)); + +/* harmony default export */ var ol_MapEvent = (MapEvent); + +//# sourceMappingURL=MapEvent.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEvent.js +/** + * @module ol/MapBrowserEvent + */ + + +/** + * @classdesc + * Events emitted as map browser events are instances of this type. + * See {@link module:ol/PluggableMap~PluggableMap} for which events trigger a map browser event. + */ +var MapBrowserEvent = /*@__PURE__*/(function (MapEvent) { + function MapBrowserEvent(type, map, browserEvent, opt_dragging, opt_frameState) { + + MapEvent.call(this, type, map, opt_frameState); + + /** + * The original browser event. + * @const + * @type {Event} + * @api + */ + this.originalEvent = browserEvent; + + /** + * The map pixel relative to the viewport corresponding to the original browser event. + * @type {import("./pixel.js").Pixel} + * @api + */ + this.pixel = map.getEventPixel(browserEvent); + + /** + * The coordinate in view projection corresponding to the original browser event. + * @type {import("./coordinate.js").Coordinate} + * @api + */ + this.coordinate = map.getCoordinateFromPixel(this.pixel); + + /** + * Indicates if the map is currently being dragged. Only set for + * `POINTERDRAG` and `POINTERMOVE` events. Default is `false`. + * + * @type {boolean} + * @api + */ + this.dragging = opt_dragging !== undefined ? opt_dragging : false; + + } + + if ( MapEvent ) MapBrowserEvent.__proto__ = MapEvent; + MapBrowserEvent.prototype = Object.create( MapEvent && MapEvent.prototype ); + MapBrowserEvent.prototype.constructor = MapBrowserEvent; + + /** + * Prevents the default browser action. + * See https://developer.mozilla.org/en-US/docs/Web/API/event.preventDefault. + * @override + * @api + */ + MapBrowserEvent.prototype.preventDefault = function preventDefault () { + MapEvent.prototype.preventDefault.call(this); + this.originalEvent.preventDefault(); + }; + + /** + * Prevents further propagation of the current event. + * See https://developer.mozilla.org/en-US/docs/Web/API/event.stopPropagation. + * @override + * @api + */ + MapBrowserEvent.prototype.stopPropagation = function stopPropagation () { + MapEvent.prototype.stopPropagation.call(this); + this.originalEvent.stopPropagation(); + }; + + return MapBrowserEvent; +}(ol_MapEvent)); + + +/* harmony default export */ var ol_MapBrowserEvent = (MapBrowserEvent); + +//# sourceMappingURL=MapBrowserEvent.js.map +// CONCATENATED MODULE: ./node_modules/ol/has.js +/** + * @module ol/has + */ + +var ua = typeof navigator !== 'undefined' ? + navigator.userAgent.toLowerCase() : ''; + +/** + * User agent string says we are dealing with Firefox as browser. + * @type {boolean} + */ +var FIREFOX = ua.indexOf('firefox') !== -1; + +/** + * User agent string says we are dealing with Safari as browser. + * @type {boolean} + */ +var SAFARI = ua.indexOf('safari') !== -1 && ua.indexOf('chrom') == -1; + +/** + * User agent string says we are dealing with a WebKit engine. + * @type {boolean} + */ +var WEBKIT = ua.indexOf('webkit') !== -1 && ua.indexOf('edge') == -1; + +/** + * User agent string says we are dealing with a Mac as platform. + * @type {boolean} + */ +var MAC = ua.indexOf('macintosh') !== -1; + + +/** + * The ratio between physical pixels and device-independent pixels + * (dips) on the device (`window.devicePixelRatio`). + * @const + * @type {number} + * @api + */ +var DEVICE_PIXEL_RATIO = window.devicePixelRatio || 1; + + +/** + * True if the browser's Canvas implementation implements {get,set}LineDash. + * @type {boolean} + */ +var CANVAS_LINE_DASH = function() { + var has = false; + try { + has = !!document.createElement('canvas').getContext('2d').setLineDash; + } catch (e) { + // pass + } + return has; +}(); + + +/** + * Is HTML5 geolocation supported in the current browser? + * @const + * @type {boolean} + * @api + */ +var GEOLOCATION = 'geolocation' in navigator; + + +/** + * True if browser supports touch events. + * @const + * @type {boolean} + * @api + */ +var TOUCH = 'ontouchstart' in window; + + +/** + * True if browser supports pointer events. + * @const + * @type {boolean} + */ +var POINTER = 'PointerEvent' in window; + + +/** + * True if browser supports ms pointer events (IE 10). + * @const + * @type {boolean} + */ +var MSPOINTER = !!(navigator.msPointerEnabled); + + + + +//# sourceMappingURL=has.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEventType.js +/** + * @module ol/MapBrowserEventType + */ + + +/** + * Constants for event names. + * @enum {string} + */ +/* harmony default export */ var MapBrowserEventType = ({ + + /** + * A true single click with no dragging and no double click. Note that this + * event is delayed by 250 ms to ensure that it is not a double click. + * @event module:ol/MapBrowserEvent~MapBrowserEvent#singleclick + * @api + */ + SINGLECLICK: 'singleclick', + + /** + * A click with no dragging. A double click will fire two of this. + * @event module:ol/MapBrowserEvent~MapBrowserEvent#click + * @api + */ + CLICK: EventType.CLICK, + + /** + * A true double click, with no dragging. + * @event module:ol/MapBrowserEvent~MapBrowserEvent#dblclick + * @api + */ + DBLCLICK: EventType.DBLCLICK, + + /** + * Triggered when a pointer is dragged. + * @event module:ol/MapBrowserEvent~MapBrowserEvent#pointerdrag + * @api + */ + POINTERDRAG: 'pointerdrag', + + /** + * Triggered when a pointer is moved. Note that on touch devices this is + * triggered when the map is panned, so is not the same as mousemove. + * @event module:ol/MapBrowserEvent~MapBrowserEvent#pointermove + * @api + */ + POINTERMOVE: 'pointermove', + + POINTERDOWN: 'pointerdown', + POINTERUP: 'pointerup', + POINTEROVER: 'pointerover', + POINTEROUT: 'pointerout', + POINTERENTER: 'pointerenter', + POINTERLEAVE: 'pointerleave', + POINTERCANCEL: 'pointercancel' +}); + +//# sourceMappingURL=MapBrowserEventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapBrowserPointerEvent.js +/** + * @module ol/MapBrowserPointerEvent + */ + + +var MapBrowserPointerEvent = /*@__PURE__*/(function (MapBrowserEvent) { + function MapBrowserPointerEvent(type, map, pointerEvent, opt_dragging, opt_frameState) { + + MapBrowserEvent.call(this, type, map, pointerEvent.originalEvent, opt_dragging, opt_frameState); + + /** + * @const + * @type {import("./pointer/PointerEvent.js").default} + */ + this.pointerEvent = pointerEvent; + + } + + if ( MapBrowserEvent ) MapBrowserPointerEvent.__proto__ = MapBrowserEvent; + MapBrowserPointerEvent.prototype = Object.create( MapBrowserEvent && MapBrowserEvent.prototype ); + MapBrowserPointerEvent.prototype.constructor = MapBrowserPointerEvent; + + return MapBrowserPointerEvent; +}(ol_MapBrowserEvent)); + +/* harmony default export */ var ol_MapBrowserPointerEvent = (MapBrowserPointerEvent); + +//# sourceMappingURL=MapBrowserPointerEvent.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/EventType.js +/** + * @module ol/pointer/EventType + */ + +/** + * Constants for event names. + * @enum {string} + */ +/* harmony default export */ var pointer_EventType = ({ + POINTERMOVE: 'pointermove', + POINTERDOWN: 'pointerdown', + POINTERUP: 'pointerup', + POINTEROVER: 'pointerover', + POINTEROUT: 'pointerout', + POINTERENTER: 'pointerenter', + POINTERLEAVE: 'pointerleave', + POINTERCANCEL: 'pointercancel' +}); + +//# sourceMappingURL=EventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/EventSource.js +/** + * @module ol/pointer/EventSource + */ + +var EventSource_EventSource = function EventSource(dispatcher, mapping) { + + /** + * @type {import("./PointerEventHandler.js").default} + */ + this.dispatcher = dispatcher; + + /** + * @private + * @const + * @type {!Object} + */ + this.mapping_ = mapping; +}; + +/** + * List of events supported by this source. + * @return {Array} Event names + */ +EventSource_EventSource.prototype.getEvents = function getEvents () { + return Object.keys(this.mapping_); +}; + +/** + * Returns the handler that should handle a given event type. + * @param {string} eventType The event type. + * @return {function(Event)} Handler + */ +EventSource_EventSource.prototype.getHandlerForEvent = function getHandlerForEvent (eventType) { + return this.mapping_[eventType]; +}; + +/* harmony default export */ var pointer_EventSource = (EventSource_EventSource); + +//# sourceMappingURL=EventSource.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/MouseSource.js +/** + * @module ol/pointer/MouseSource + */ + +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + +/** + * @type {number} + */ +var POINTER_ID = 1; + + +/** + * @type {string} + */ +var POINTER_TYPE = 'mouse'; + + +/** + * Radius around touchend that swallows mouse events. + * + * @type {number} + */ +var DEDUP_DIST = 25; + +/** + * Handler for `mousedown`. + * + * @this {MouseSource} + * @param {MouseEvent} inEvent The in event. + */ +function mousedown(inEvent) { + if (!this.isEventSimulatedFromTouch_(inEvent)) { + // TODO(dfreedman) workaround for some elements not sending mouseup + // http://crbug/149091 + if (POINTER_ID.toString() in this.pointerMap) { + this.cancel(inEvent); + } + var e = prepareEvent(inEvent, this.dispatcher); + this.pointerMap[POINTER_ID.toString()] = inEvent; + this.dispatcher.down(e, inEvent); + } +} + +/** + * Handler for `mousemove`. + * + * @this {MouseSource} + * @param {MouseEvent} inEvent The in event. + */ +function mousemove(inEvent) { + if (!this.isEventSimulatedFromTouch_(inEvent)) { + var e = prepareEvent(inEvent, this.dispatcher); + this.dispatcher.move(e, inEvent); + } +} + +/** + * Handler for `mouseup`. + * + * @this {MouseSource} + * @param {MouseEvent} inEvent The in event. + */ +function mouseup(inEvent) { + if (!this.isEventSimulatedFromTouch_(inEvent)) { + var p = this.pointerMap[POINTER_ID.toString()]; + + if (p && p.button === inEvent.button) { + var e = prepareEvent(inEvent, this.dispatcher); + this.dispatcher.up(e, inEvent); + this.cleanupMouse(); + } + } +} + +/** + * Handler for `mouseover`. + * + * @this {MouseSource} + * @param {MouseEvent} inEvent The in event. + */ +function mouseover(inEvent) { + if (!this.isEventSimulatedFromTouch_(inEvent)) { + var e = prepareEvent(inEvent, this.dispatcher); + this.dispatcher.enterOver(e, inEvent); + } +} + +/** + * Handler for `mouseout`. + * + * @this {MouseSource} + * @param {MouseEvent} inEvent The in event. + */ +function mouseout(inEvent) { + if (!this.isEventSimulatedFromTouch_(inEvent)) { + var e = prepareEvent(inEvent, this.dispatcher); + this.dispatcher.leaveOut(e, inEvent); + } +} + + +var MouseSource = /*@__PURE__*/(function (EventSource) { + function MouseSource(dispatcher) { + var mapping = { + 'mousedown': mousedown, + 'mousemove': mousemove, + 'mouseup': mouseup, + 'mouseover': mouseover, + 'mouseout': mouseout + }; + EventSource.call(this, dispatcher, mapping); + + /** + * @const + * @type {!Object} + */ + this.pointerMap = dispatcher.pointerMap; + + /** + * @const + * @type {Array} + */ + this.lastTouches = []; + } + + if ( EventSource ) MouseSource.__proto__ = EventSource; + MouseSource.prototype = Object.create( EventSource && EventSource.prototype ); + MouseSource.prototype.constructor = MouseSource; + + /** + * Detect if a mouse event was simulated from a touch by + * checking if previously there was a touch event at the + * same position. + * + * FIXME - Known problem with the native Android browser on + * Samsung GT-I9100 (Android 4.1.2): + * In case the page is scrolled, this function does not work + * correctly when a canvas is used (WebGL or canvas renderer). + * Mouse listeners on canvas elements (for this browser), create + * two mouse events: One 'good' and one 'bad' one (on other browsers or + * when a div is used, there is only one event). For the 'bad' one, + * clientX/clientY and also pageX/pageY are wrong when the page + * is scrolled. Because of that, this function can not detect if + * the events were simulated from a touch event. As result, a + * pointer event at a wrong position is dispatched, which confuses + * the map interactions. + * It is unclear, how one can get the correct position for the event + * or detect that the positions are invalid. + * + * @private + * @param {MouseEvent} inEvent The in event. + * @return {boolean} True, if the event was generated by a touch. + */ + MouseSource.prototype.isEventSimulatedFromTouch_ = function isEventSimulatedFromTouch_ (inEvent) { + var lts = this.lastTouches; + var x = inEvent.clientX; + var y = inEvent.clientY; + for (var i = 0, l = lts.length, t = (void 0); i < l && (t = lts[i]); i++) { + // simulated mouse events will be swallowed near a primary touchend + var dx = Math.abs(x - t[0]); + var dy = Math.abs(y - t[1]); + if (dx <= DEDUP_DIST && dy <= DEDUP_DIST) { + return true; + } + } + return false; + }; + + /** + * Dispatches a `pointercancel` event. + * + * @param {Event} inEvent The in event. + */ + MouseSource.prototype.cancel = function cancel (inEvent) { + var e = prepareEvent(inEvent, this.dispatcher); + this.dispatcher.cancel(e, inEvent); + this.cleanupMouse(); + }; + + /** + * Remove the mouse from the list of active pointers. + */ + MouseSource.prototype.cleanupMouse = function cleanupMouse () { + delete this.pointerMap[POINTER_ID.toString()]; + }; + + return MouseSource; +}(pointer_EventSource)); + + +/** + * Creates a copy of the original event that will be used + * for the fake pointer event. + * + * @param {Event} inEvent The in event. + * @param {import("./PointerEventHandler.js").default} dispatcher Event handler. + * @return {Object} The copied event. + */ +function prepareEvent(inEvent, dispatcher) { + var e = dispatcher.cloneEvent(inEvent, inEvent); + + // forward mouse preventDefault + var pd = e.preventDefault; + e.preventDefault = function() { + inEvent.preventDefault(); + pd(); + }; + + e.pointerId = POINTER_ID; + e.isPrimary = true; + e.pointerType = POINTER_TYPE; + + return e; +} + + +/* harmony default export */ var pointer_MouseSource = (MouseSource); + +//# sourceMappingURL=MouseSource.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/MsSource.js +/** + * @module ol/pointer/MsSource + */ +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + +/** + * @const + * @type {Array} + */ +var POINTER_TYPES = [ + '', + 'unavailable', + 'touch', + 'pen', + 'mouse' +]; + +/** + * Handler for `msPointerDown`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerDown(inEvent) { + this.pointerMap[inEvent.pointerId.toString()] = inEvent; + var e = this.prepareEvent_(inEvent); + this.dispatcher.down(e, inEvent); +} + +/** + * Handler for `msPointerMove`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerMove(inEvent) { + var e = this.prepareEvent_(inEvent); + this.dispatcher.move(e, inEvent); +} + +/** + * Handler for `msPointerUp`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerUp(inEvent) { + var e = this.prepareEvent_(inEvent); + this.dispatcher.up(e, inEvent); + this.cleanup(inEvent.pointerId); +} + +/** + * Handler for `msPointerOut`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerOut(inEvent) { + var e = this.prepareEvent_(inEvent); + this.dispatcher.leaveOut(e, inEvent); +} + +/** + * Handler for `msPointerOver`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerOver(inEvent) { + var e = this.prepareEvent_(inEvent); + this.dispatcher.enterOver(e, inEvent); +} + +/** + * Handler for `msPointerCancel`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msPointerCancel(inEvent) { + var e = this.prepareEvent_(inEvent); + this.dispatcher.cancel(e, inEvent); + this.cleanup(inEvent.pointerId); +} + +/** + * Handler for `msLostPointerCapture`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msLostPointerCapture(inEvent) { + var e = this.dispatcher.makeEvent('lostpointercapture', inEvent, inEvent); + this.dispatcher.dispatchEvent(e); +} + +/** + * Handler for `msGotPointerCapture`. + * + * @this {MsSource} + * @param {MSPointerEvent} inEvent The in event. + */ +function msGotPointerCapture(inEvent) { + var e = this.dispatcher.makeEvent('gotpointercapture', inEvent, inEvent); + this.dispatcher.dispatchEvent(e); +} + +var MsSource = /*@__PURE__*/(function (EventSource) { + function MsSource(dispatcher) { + var mapping = { + 'MSPointerDown': msPointerDown, + 'MSPointerMove': msPointerMove, + 'MSPointerUp': msPointerUp, + 'MSPointerOut': msPointerOut, + 'MSPointerOver': msPointerOver, + 'MSPointerCancel': msPointerCancel, + 'MSGotPointerCapture': msGotPointerCapture, + 'MSLostPointerCapture': msLostPointerCapture + }; + EventSource.call(this, dispatcher, mapping); + + /** + * @const + * @type {!Object} + */ + this.pointerMap = dispatcher.pointerMap; + } + + if ( EventSource ) MsSource.__proto__ = EventSource; + MsSource.prototype = Object.create( EventSource && EventSource.prototype ); + MsSource.prototype.constructor = MsSource; + + /** + * Creates a copy of the original event that will be used + * for the fake pointer event. + * + * @private + * @param {MSPointerEvent} inEvent The in event. + * @return {Object} The copied event. + */ + MsSource.prototype.prepareEvent_ = function prepareEvent_ (inEvent) { + /** @type {MSPointerEvent|Object} */ + var e = inEvent; + if (typeof inEvent.pointerType === 'number') { + e = this.dispatcher.cloneEvent(inEvent, inEvent); + e.pointerType = POINTER_TYPES[inEvent.pointerType]; + } + + return e; + }; + + /** + * Remove this pointer from the list of active pointers. + * @param {number} pointerId Pointer identifier. + */ + MsSource.prototype.cleanup = function cleanup (pointerId) { + delete this.pointerMap[pointerId.toString()]; + }; + + return MsSource; +}(pointer_EventSource)); + +/* harmony default export */ var pointer_MsSource = (MsSource); + +//# sourceMappingURL=MsSource.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/NativeSource.js +/** + * @module ol/pointer/NativeSource + */ + +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + +/** + * Handler for `pointerdown`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerDown(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `pointermove`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerMove(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `pointerup`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerUp(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `pointerout`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerOut(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `pointerover`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerOver(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `pointercancel`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function pointerCancel(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `lostpointercapture`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function lostPointerCapture(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +/** + * Handler for `gotpointercapture`. + * + * @this {NativeSource} + * @param {Event} inEvent The in event. + */ +function gotPointerCapture(inEvent) { + this.dispatcher.fireNativeEvent(inEvent); +} + +var NativeSource = /*@__PURE__*/(function (EventSource) { + function NativeSource(dispatcher) { + var mapping = { + 'pointerdown': pointerDown, + 'pointermove': pointerMove, + 'pointerup': pointerUp, + 'pointerout': pointerOut, + 'pointerover': pointerOver, + 'pointercancel': pointerCancel, + 'gotpointercapture': gotPointerCapture, + 'lostpointercapture': lostPointerCapture + }; + EventSource.call(this, dispatcher, mapping); + } + + if ( EventSource ) NativeSource.__proto__ = EventSource; + NativeSource.prototype = Object.create( EventSource && EventSource.prototype ); + NativeSource.prototype.constructor = NativeSource; + + return NativeSource; +}(pointer_EventSource)); + +/* harmony default export */ var pointer_NativeSource = (NativeSource); + +//# sourceMappingURL=NativeSource.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/PointerEvent.js +/** + * @module ol/pointer/PointerEvent + */ + +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + +/** + * Is the `buttons` property supported? + * @type {boolean} + */ +var HAS_BUTTONS = false; + + +var PointerEvent = /*@__PURE__*/(function (_Event) { + function PointerEvent(type, originalEvent, opt_eventDict) { + _Event.call(this, type); + + /** + * @const + * @type {Event} + */ + this.originalEvent = originalEvent; + + var eventDict = opt_eventDict ? opt_eventDict : {}; + + /** + * @type {number} + */ + this.buttons = getButtons(eventDict); + + /** + * @type {number} + */ + this.pressure = getPressure(eventDict, this.buttons); + + // MouseEvent related properties + + /** + * @type {boolean} + */ + this.bubbles = 'bubbles' in eventDict ? eventDict['bubbles'] : false; + + /** + * @type {boolean} + */ + this.cancelable = 'cancelable' in eventDict ? eventDict['cancelable'] : false; + + /** + * @type {Object} + */ + this.view = 'view' in eventDict ? eventDict['view'] : null; + + /** + * @type {number} + */ + this.detail = 'detail' in eventDict ? eventDict['detail'] : null; + + /** + * @type {number} + */ + this.screenX = 'screenX' in eventDict ? eventDict['screenX'] : 0; + + /** + * @type {number} + */ + this.screenY = 'screenY' in eventDict ? eventDict['screenY'] : 0; + + /** + * @type {number} + */ + this.clientX = 'clientX' in eventDict ? eventDict['clientX'] : 0; + + /** + * @type {number} + */ + this.clientY = 'clientY' in eventDict ? eventDict['clientY'] : 0; + + /** + * @type {boolean} + */ + this.ctrlKey = 'ctrlKey' in eventDict ? eventDict['ctrlKey'] : false; + + /** + * @type {boolean} + */ + this.altKey = 'altKey' in eventDict ? eventDict['altKey'] : false; + + /** + * @type {boolean} + */ + this.shiftKey = 'shiftKey' in eventDict ? eventDict['shiftKey'] : false; + + /** + * @type {boolean} + */ + this.metaKey = 'metaKey' in eventDict ? eventDict['metaKey'] : false; + + /** + * @type {number} + */ + this.button = 'button' in eventDict ? eventDict['button'] : 0; + + /** + * @type {Node} + */ + this.relatedTarget = 'relatedTarget' in eventDict ? + eventDict['relatedTarget'] : null; + + // PointerEvent related properties + + /** + * @const + * @type {number} + */ + this.pointerId = 'pointerId' in eventDict ? eventDict['pointerId'] : 0; + + /** + * @type {number} + */ + this.width = 'width' in eventDict ? eventDict['width'] : 0; + + /** + * @type {number} + */ + this.height = 'height' in eventDict ? eventDict['height'] : 0; + + /** + * @type {number} + */ + this.tiltX = 'tiltX' in eventDict ? eventDict['tiltX'] : 0; + + /** + * @type {number} + */ + this.tiltY = 'tiltY' in eventDict ? eventDict['tiltY'] : 0; + + /** + * @type {string} + */ + this.pointerType = 'pointerType' in eventDict ? eventDict['pointerType'] : ''; + + /** + * @type {number} + */ + this.hwTimestamp = 'hwTimestamp' in eventDict ? eventDict['hwTimestamp'] : 0; + + /** + * @type {boolean} + */ + this.isPrimary = 'isPrimary' in eventDict ? eventDict['isPrimary'] : false; + + // keep the semantics of preventDefault + if (originalEvent.preventDefault) { + this.preventDefault = function() { + originalEvent.preventDefault(); + }; + } + } + + if ( _Event ) PointerEvent.__proto__ = _Event; + PointerEvent.prototype = Object.create( _Event && _Event.prototype ); + PointerEvent.prototype.constructor = PointerEvent; + + return PointerEvent; +}(events_Event)); + + +/** + * @param {Object} eventDict The event dictionary. + * @return {number} Button indicator. + */ +function getButtons(eventDict) { + // According to the w3c spec, + // http://www.w3.org/TR/DOM-Level-3-Events/#events-MouseEvent-button + // MouseEvent.button == 0 can mean either no mouse button depressed, or the + // left mouse button depressed. + // + // As of now, the only way to distinguish between the two states of + // MouseEvent.button is by using the deprecated MouseEvent.which property, as + // this maps mouse buttons to positive integers > 0, and uses 0 to mean that + // no mouse button is held. + // + // MouseEvent.which is derived from MouseEvent.button at MouseEvent creation, + // but initMouseEvent does not expose an argument with which to set + // MouseEvent.which. Calling initMouseEvent with a buttonArg of 0 will set + // MouseEvent.button == 0 and MouseEvent.which == 1, breaking the expectations + // of app developers. + // + // The only way to propagate the correct state of MouseEvent.which and + // MouseEvent.button to a new MouseEvent.button == 0 and MouseEvent.which == 0 + // is to call initMouseEvent with a buttonArg value of -1. + // + // This is fixed with DOM Level 4's use of buttons + var buttons; + if (eventDict.buttons || HAS_BUTTONS) { + buttons = eventDict.buttons; + } else { + switch (eventDict.which) { + case 1: buttons = 1; break; + case 2: buttons = 4; break; + case 3: buttons = 2; break; + default: buttons = 0; + } + } + return buttons; +} + + +/** + * @param {Object} eventDict The event dictionary. + * @param {number} buttons Button indicator. + * @return {number} The pressure. + */ +function getPressure(eventDict, buttons) { + // Spec requires that pointers without pressure specified use 0.5 for down + // state and 0 for up state. + var pressure = 0; + if (eventDict.pressure) { + pressure = eventDict.pressure; + } else { + pressure = buttons ? 0.5 : 0; + } + return pressure; +} + + +/** + * Checks if the `buttons` property is supported. + */ +(function() { + try { + var ev = new MouseEvent('click', {buttons: 1}); + HAS_BUTTONS = ev.buttons === 1; + } catch (e) { + // pass + } +})(); + +/* harmony default export */ var pointer_PointerEvent = (PointerEvent); + +//# sourceMappingURL=PointerEvent.js.map +// CONCATENATED MODULE: ./node_modules/ol/array.js +/** + * @module ol/array + */ + + +/** + * Performs a binary search on the provided sorted list and returns the index of the item if found. If it can't be found it'll return -1. + * https://github.com/darkskyapp/binary-search + * + * @param {Array<*>} haystack Items to search through. + * @param {*} needle The item to look for. + * @param {Function=} opt_comparator Comparator function. + * @return {number} The index of the item if found, -1 if not. + */ +function binarySearch(haystack, needle, opt_comparator) { + var mid, cmp; + var comparator = opt_comparator || numberSafeCompareFunction; + var low = 0; + var high = haystack.length; + var found = false; + + while (low < high) { + /* Note that "(low + high) >>> 1" may overflow, and results in a typecast + * to double (which gives the wrong results). */ + mid = low + (high - low >> 1); + cmp = +comparator(haystack[mid], needle); + + if (cmp < 0.0) { /* Too low. */ + low = mid + 1; + + } else { /* Key found or too high */ + high = mid; + found = !cmp; + } + } + + /* Key not found. */ + return found ? low : ~low; +} + + +/** + * Compare function for array sort that is safe for numbers. + * @param {*} a The first object to be compared. + * @param {*} b The second object to be compared. + * @return {number} A negative number, zero, or a positive number as the first + * argument is less than, equal to, or greater than the second. + */ +function numberSafeCompareFunction(a, b) { + return a > b ? 1 : a < b ? -1 : 0; +} + + +/** + * Whether the array contains the given object. + * @param {Array<*>} arr The array to test for the presence of the element. + * @param {*} obj The object for which to test. + * @return {boolean} The object is in the array. + */ +function includes(arr, obj) { + return arr.indexOf(obj) >= 0; +} + + +/** + * @param {Array} arr Array. + * @param {number} target Target. + * @param {number} direction 0 means return the nearest, > 0 + * means return the largest nearest, < 0 means return the + * smallest nearest. + * @return {number} Index. + */ +function linearFindNearest(arr, target, direction) { + var n = arr.length; + if (arr[0] <= target) { + return 0; + } else if (target <= arr[n - 1]) { + return n - 1; + } else { + var i; + if (direction > 0) { + for (i = 1; i < n; ++i) { + if (arr[i] < target) { + return i - 1; + } + } + } else if (direction < 0) { + for (i = 1; i < n; ++i) { + if (arr[i] <= target) { + return i; + } + } + } else { + for (i = 1; i < n; ++i) { + if (arr[i] == target) { + return i; + } else if (arr[i] < target) { + if (arr[i - 1] - target < target - arr[i]) { + return i - 1; + } else { + return i; + } + } + } + } + return n - 1; + } +} + + +/** + * @param {Array<*>} arr Array. + * @param {number} begin Begin index. + * @param {number} end End index. + */ +function reverseSubArray(arr, begin, end) { + while (begin < end) { + var tmp = arr[begin]; + arr[begin] = arr[end]; + arr[end] = tmp; + ++begin; + --end; + } +} + + +/** + * @param {Array} arr The array to modify. + * @param {!Array|VALUE} data The elements or arrays of elements to add to arr. + * @template VALUE + */ +function extend(arr, data) { + var extension = Array.isArray(data) ? data : [data]; + var length = extension.length; + for (var i = 0; i < length; i++) { + arr[arr.length] = extension[i]; + } +} + + +/** + * @param {Array} arr The array to modify. + * @param {VALUE} obj The element to remove. + * @template VALUE + * @return {boolean} If the element was removed. + */ +function array_remove(arr, obj) { + var i = arr.indexOf(obj); + var found = i > -1; + if (found) { + arr.splice(i, 1); + } + return found; +} + + +/** + * @param {Array} arr The array to search in. + * @param {function(VALUE, number, ?) : boolean} func The function to compare. + * @template VALUE + * @return {VALUE|null} The element found or null. + */ +function find(arr, func) { + var length = arr.length >>> 0; + var value; + + for (var i = 0; i < length; i++) { + value = arr[i]; + if (func(value, i, arr)) { + return value; + } + } + return null; +} + + +/** + * @param {Array|Uint8ClampedArray} arr1 The first array to compare. + * @param {Array|Uint8ClampedArray} arr2 The second array to compare. + * @return {boolean} Whether the two arrays are equal. + */ +function equals(arr1, arr2) { + var len1 = arr1.length; + if (len1 !== arr2.length) { + return false; + } + for (var i = 0; i < len1; i++) { + if (arr1[i] !== arr2[i]) { + return false; + } + } + return true; +} + + +/** + * Sort the passed array such that the relative order of equal elements is preverved. + * See https://en.wikipedia.org/wiki/Sorting_algorithm#Stability for details. + * @param {Array<*>} arr The array to sort (modifies original). + * @param {!function(*, *): number} compareFnc Comparison function. + * @api + */ +function stableSort(arr, compareFnc) { + var length = arr.length; + var tmp = Array(arr.length); + var i; + for (i = 0; i < length; i++) { + tmp[i] = {index: i, value: arr[i]}; + } + tmp.sort(function(a, b) { + return compareFnc(a.value, b.value) || a.index - b.index; + }); + for (i = 0; i < arr.length; i++) { + arr[i] = tmp[i].value; + } +} + + +/** + * @param {Array<*>} arr The array to search in. + * @param {Function} func Comparison function. + * @return {number} Return index. + */ +function findIndex(arr, func) { + var index; + var found = !arr.every(function(el, idx) { + index = idx; + return !func(el, idx, arr); + }); + return found ? index : -1; +} + + +/** + * @param {Array<*>} arr The array to test. + * @param {Function=} opt_func Comparison function. + * @param {boolean=} opt_strict Strictly sorted (default false). + * @return {boolean} Return index. + */ +function isSorted(arr, opt_func, opt_strict) { + var compare = opt_func || numberSafeCompareFunction; + return arr.every(function(currentVal, index) { + if (index === 0) { + return true; + } + var res = compare(arr[index - 1], currentVal); + return !(res > 0 || opt_strict && res === 0); + }); +} + +//# sourceMappingURL=array.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/TouchSource.js +/** + * @module ol/pointer/TouchSource + */ + +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + + + +/** + * @type {number} + */ +var CLICK_COUNT_TIMEOUT = 200; + +/** + * @type {string} + */ +var TouchSource_POINTER_TYPE = 'touch'; + +/** + * Handler for `touchstart`, triggers `pointerover`, + * `pointerenter` and `pointerdown` events. + * + * @this {TouchSource} + * @param {TouchEvent} inEvent The in event. + */ +function touchstart(inEvent) { + this.vacuumTouches_(inEvent); + this.setPrimaryTouch_(inEvent.changedTouches[0]); + this.dedupSynthMouse_(inEvent); + this.clickCount_++; + this.processTouches_(inEvent, this.overDown_); +} + +/** + * Handler for `touchmove`. + * + * @this {TouchSource} + * @param {TouchEvent} inEvent The in event. + */ +function touchmove(inEvent) { + this.processTouches_(inEvent, this.moveOverOut_); +} + +/** + * Handler for `touchend`, triggers `pointerup`, + * `pointerout` and `pointerleave` events. + * + * @this {TouchSource} + * @param {TouchEvent} inEvent The event. + */ +function touchend(inEvent) { + this.dedupSynthMouse_(inEvent); + this.processTouches_(inEvent, this.upOut_); +} + +/** + * Handler for `touchcancel`, triggers `pointercancel`, + * `pointerout` and `pointerleave` events. + * + * @this {TouchSource} + * @param {TouchEvent} inEvent The in event. + */ +function touchcancel(inEvent) { + this.processTouches_(inEvent, this.cancelOut_); +} + + +var TouchSource_TouchSource = /*@__PURE__*/(function (EventSource) { + function TouchSource(dispatcher, mouseSource) { + var mapping = { + 'touchstart': touchstart, + 'touchmove': touchmove, + 'touchend': touchend, + 'touchcancel': touchcancel + }; + EventSource.call(this, dispatcher, mapping); + + /** + * @const + * @type {!Object} + */ + this.pointerMap = dispatcher.pointerMap; + + /** + * @const + * @type {import("./MouseSource.js").default} + */ + this.mouseSource = mouseSource; + + /** + * @private + * @type {number|undefined} + */ + this.firstTouchId_ = undefined; + + /** + * @private + * @type {number} + */ + this.clickCount_ = 0; + + /** + * @private + * @type {?} + */ + this.resetId_; + + /** + * Mouse event timeout: This should be long enough to + * ignore compat mouse events made by touch. + * @private + * @type {number} + */ + this.dedupTimeout_ = 2500; + } + + if ( EventSource ) TouchSource.__proto__ = EventSource; + TouchSource.prototype = Object.create( EventSource && EventSource.prototype ); + TouchSource.prototype.constructor = TouchSource; + + /** + * @private + * @param {Touch} inTouch The in touch. + * @return {boolean} True, if this is the primary touch. + */ + TouchSource.prototype.isPrimaryTouch_ = function isPrimaryTouch_ (inTouch) { + return this.firstTouchId_ === inTouch.identifier; + }; + + /** + * Set primary touch if there are no pointers, or the only pointer is the mouse. + * @param {Touch} inTouch The in touch. + * @private + */ + TouchSource.prototype.setPrimaryTouch_ = function setPrimaryTouch_ (inTouch) { + var count = Object.keys(this.pointerMap).length; + if (count === 0 || (count === 1 && POINTER_ID.toString() in this.pointerMap)) { + this.firstTouchId_ = inTouch.identifier; + this.cancelResetClickCount_(); + } + }; + + /** + * @private + * @param {PointerEvent} inPointer The in pointer object. + */ + TouchSource.prototype.removePrimaryPointer_ = function removePrimaryPointer_ (inPointer) { + if (inPointer.isPrimary) { + this.firstTouchId_ = undefined; + this.resetClickCount_(); + } + }; + + /** + * @private + */ + TouchSource.prototype.resetClickCount_ = function resetClickCount_ () { + this.resetId_ = setTimeout( + this.resetClickCountHandler_.bind(this), + CLICK_COUNT_TIMEOUT); + }; + + /** + * @private + */ + TouchSource.prototype.resetClickCountHandler_ = function resetClickCountHandler_ () { + this.clickCount_ = 0; + this.resetId_ = undefined; + }; + + /** + * @private + */ + TouchSource.prototype.cancelResetClickCount_ = function cancelResetClickCount_ () { + if (this.resetId_ !== undefined) { + clearTimeout(this.resetId_); + } + }; + + /** + * @private + * @param {TouchEvent} browserEvent Browser event + * @param {Touch} inTouch Touch event + * @return {PointerEvent} A pointer object. + */ + TouchSource.prototype.touchToPointer_ = function touchToPointer_ (browserEvent, inTouch) { + var e = this.dispatcher.cloneEvent(browserEvent, inTouch); + // Spec specifies that pointerId 1 is reserved for Mouse. + // Touch identifiers can start at 0. + // Add 2 to the touch identifier for compatibility. + e.pointerId = inTouch.identifier + 2; + // TODO: check if this is necessary? + //e.target = findTarget(e); + e.bubbles = true; + e.cancelable = true; + e.detail = this.clickCount_; + e.button = 0; + e.buttons = 1; + e.width = inTouch.radiusX || 0; + e.height = inTouch.radiusY || 0; + e.pressure = inTouch.force || 0.5; + e.isPrimary = this.isPrimaryTouch_(inTouch); + e.pointerType = TouchSource_POINTER_TYPE; + + // make sure that the properties that are different for + // each `Touch` object are not copied from the BrowserEvent object + e.clientX = inTouch.clientX; + e.clientY = inTouch.clientY; + e.screenX = inTouch.screenX; + e.screenY = inTouch.screenY; + + return e; + }; + + /** + * @private + * @param {TouchEvent} inEvent Touch event + * @param {function(TouchEvent, PointerEvent)} inFunction In function. + */ + TouchSource.prototype.processTouches_ = function processTouches_ (inEvent, inFunction) { + var touches = Array.prototype.slice.call(inEvent.changedTouches); + var count = touches.length; + function preventDefault() { + inEvent.preventDefault(); + } + for (var i = 0; i < count; ++i) { + var pointer = this.touchToPointer_(inEvent, touches[i]); + // forward touch preventDefaults + pointer.preventDefault = preventDefault; + inFunction.call(this, inEvent, pointer); + } + }; + + /** + * @private + * @param {TouchList} touchList The touch list. + * @param {number} searchId Search identifier. + * @return {boolean} True, if the `Touch` with the given id is in the list. + */ + TouchSource.prototype.findTouch_ = function findTouch_ (touchList, searchId) { + var l = touchList.length; + for (var i = 0; i < l; i++) { + var touch = touchList[i]; + if (touch.identifier === searchId) { + return true; + } + } + return false; + }; + + /** + * In some instances, a touchstart can happen without a touchend. This + * leaves the pointermap in a broken state. + * Therefore, on every touchstart, we remove the touches that did not fire a + * touchend event. + * To keep state globally consistent, we fire a pointercancel for + * this "abandoned" touch + * + * @private + * @param {TouchEvent} inEvent The in event. + */ + TouchSource.prototype.vacuumTouches_ = function vacuumTouches_ (inEvent) { + var touchList = inEvent.touches; + // pointerMap.getCount() should be < touchList.length here, + // as the touchstart has not been processed yet. + var keys = Object.keys(this.pointerMap); + var count = keys.length; + if (count >= touchList.length) { + var d = []; + for (var i = 0; i < count; ++i) { + var key = Number(keys[i]); + var value = this.pointerMap[key]; + // Never remove pointerId == 1, which is mouse. + // Touch identifiers are 2 smaller than their pointerId, which is the + // index in pointermap. + if (key != POINTER_ID && !this.findTouch_(touchList, key - 2)) { + d.push(value.out); + } + } + for (var i$1 = 0; i$1 < d.length; ++i$1) { + this.cancelOut_(inEvent, d[i$1]); + } + } + }; + + /** + * @private + * @param {TouchEvent} browserEvent The event. + * @param {PointerEvent} inPointer The in pointer object. + */ + TouchSource.prototype.overDown_ = function overDown_ (browserEvent, inPointer) { + this.pointerMap[inPointer.pointerId] = { + target: inPointer.target, + out: inPointer, + outTarget: inPointer.target + }; + this.dispatcher.over(inPointer, browserEvent); + this.dispatcher.enter(inPointer, browserEvent); + this.dispatcher.down(inPointer, browserEvent); + }; + + /** + * @private + * @param {TouchEvent} browserEvent The event. + * @param {PointerEvent} inPointer The in pointer. + */ + TouchSource.prototype.moveOverOut_ = function moveOverOut_ (browserEvent, inPointer) { + var event = inPointer; + var pointer = this.pointerMap[event.pointerId]; + // a finger drifted off the screen, ignore it + if (!pointer) { + return; + } + var outEvent = pointer.out; + var outTarget = pointer.outTarget; + this.dispatcher.move(event, browserEvent); + if (outEvent && outTarget !== event.target) { + outEvent.relatedTarget = event.target; + /** @type {Object} */ (event).relatedTarget = outTarget; + // recover from retargeting by shadow + outEvent.target = outTarget; + if (event.target) { + this.dispatcher.leaveOut(outEvent, browserEvent); + this.dispatcher.enterOver(event, browserEvent); + } else { + // clean up case when finger leaves the screen + /** @type {Object} */ (event).target = outTarget; + /** @type {Object} */ (event).relatedTarget = null; + this.cancelOut_(browserEvent, event); + } + } + pointer.out = event; + pointer.outTarget = event.target; + }; + + /** + * @private + * @param {TouchEvent} browserEvent An event. + * @param {PointerEvent} inPointer The inPointer object. + */ + TouchSource.prototype.upOut_ = function upOut_ (browserEvent, inPointer) { + this.dispatcher.up(inPointer, browserEvent); + this.dispatcher.out(inPointer, browserEvent); + this.dispatcher.leave(inPointer, browserEvent); + this.cleanUpPointer_(inPointer); + }; + + /** + * @private + * @param {TouchEvent} browserEvent The event. + * @param {PointerEvent} inPointer The in pointer. + */ + TouchSource.prototype.cancelOut_ = function cancelOut_ (browserEvent, inPointer) { + this.dispatcher.cancel(inPointer, browserEvent); + this.dispatcher.out(inPointer, browserEvent); + this.dispatcher.leave(inPointer, browserEvent); + this.cleanUpPointer_(inPointer); + }; + + /** + * @private + * @param {PointerEvent} inPointer The inPointer object. + */ + TouchSource.prototype.cleanUpPointer_ = function cleanUpPointer_ (inPointer) { + delete this.pointerMap[inPointer.pointerId]; + this.removePrimaryPointer_(inPointer); + }; + + /** + * Prevent synth mouse events from creating pointer events. + * + * @private + * @param {TouchEvent} inEvent The in event. + */ + TouchSource.prototype.dedupSynthMouse_ = function dedupSynthMouse_ (inEvent) { + var lts = this.mouseSource.lastTouches; + var t = inEvent.changedTouches[0]; + // only the primary finger will synth mouse events + if (this.isPrimaryTouch_(t)) { + // remember x/y of last touch + var lt = [t.clientX, t.clientY]; + lts.push(lt); + + setTimeout(function() { + // remove touch after timeout + array_remove(lts, lt); + }, this.dedupTimeout_); + } + }; + + return TouchSource; +}(pointer_EventSource)); + +/* harmony default export */ var pointer_TouchSource = (TouchSource_TouchSource); + +//# sourceMappingURL=TouchSource.js.map +// CONCATENATED MODULE: ./node_modules/ol/pointer/PointerEventHandler.js +/** + * @module ol/pointer/PointerEventHandler + */ + +// Based on https://github.com/Polymer/PointerEvents + +// Copyright (c) 2013 The Polymer Authors. All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + + + + + + + + + + + +/** + * Properties to copy when cloning an event, with default values. + * @type {Array} + */ +var CLONE_PROPS = [ + // MouseEvent + ['bubbles', false], + ['cancelable', false], + ['view', null], + ['detail', null], + ['screenX', 0], + ['screenY', 0], + ['clientX', 0], + ['clientY', 0], + ['ctrlKey', false], + ['altKey', false], + ['shiftKey', false], + ['metaKey', false], + ['button', 0], + ['relatedTarget', null], + // DOM Level 3 + ['buttons', 0], + // PointerEvent + ['pointerId', 0], + ['width', 0], + ['height', 0], + ['pressure', 0], + ['tiltX', 0], + ['tiltY', 0], + ['pointerType', ''], + ['hwTimestamp', 0], + ['isPrimary', false], + // event instance + ['type', ''], + ['target', null], + ['currentTarget', null], + ['which', 0] +]; + + +var PointerEventHandler_PointerEventHandler = /*@__PURE__*/(function (EventTarget) { + function PointerEventHandler(element) { + EventTarget.call(this); + + /** + * @const + * @private + * @type {Element|HTMLDocument} + */ + this.element_ = element; + + /** + * @const + * @type {!Object} + */ + this.pointerMap = {}; + + /** + * @type {Object} + * @private + */ + this.eventMap_ = {}; + + /** + * @type {Array} + * @private + */ + this.eventSourceList_ = []; + + this.registerSources(); + } + + if ( EventTarget ) PointerEventHandler.__proto__ = EventTarget; + PointerEventHandler.prototype = Object.create( EventTarget && EventTarget.prototype ); + PointerEventHandler.prototype.constructor = PointerEventHandler; + + /** + * Set up the event sources (mouse, touch and native pointers) + * that generate pointer events. + */ + PointerEventHandler.prototype.registerSources = function registerSources () { + if (POINTER) { + this.registerSource('native', new pointer_NativeSource(this)); + } else if (MSPOINTER) { + this.registerSource('ms', new pointer_MsSource(this)); + } else { + var mouseSource = new pointer_MouseSource(this); + this.registerSource('mouse', mouseSource); + + if (TOUCH) { + this.registerSource('touch', new pointer_TouchSource(this, mouseSource)); + } + } + + // register events on the viewport element + this.register_(); + }; + + /** + * Add a new event source that will generate pointer events. + * + * @param {string} name A name for the event source + * @param {import("./EventSource.js").default} source The source event. + */ + PointerEventHandler.prototype.registerSource = function registerSource (name, source) { + var s = source; + var newEvents = s.getEvents(); + + if (newEvents) { + newEvents.forEach(function(e) { + var handler = s.getHandlerForEvent(e); + + if (handler) { + this.eventMap_[e] = handler.bind(s); + } + }.bind(this)); + this.eventSourceList_.push(s); + } + }; + + /** + * Set up the events for all registered event sources. + * @private + */ + PointerEventHandler.prototype.register_ = function register_ () { + var l = this.eventSourceList_.length; + for (var i = 0; i < l; i++) { + var eventSource = this.eventSourceList_[i]; + this.addEvents_(eventSource.getEvents()); + } + }; + + /** + * Remove all registered events. + * @private + */ + PointerEventHandler.prototype.unregister_ = function unregister_ () { + var l = this.eventSourceList_.length; + for (var i = 0; i < l; i++) { + var eventSource = this.eventSourceList_[i]; + this.removeEvents_(eventSource.getEvents()); + } + }; + + /** + * Calls the right handler for a new event. + * @private + * @param {Event} inEvent Browser event. + */ + PointerEventHandler.prototype.eventHandler_ = function eventHandler_ (inEvent) { + var type = inEvent.type; + var handler = this.eventMap_[type]; + if (handler) { + handler(inEvent); + } + }; + + /** + * Setup listeners for the given events. + * @private + * @param {Array} events List of events. + */ + PointerEventHandler.prototype.addEvents_ = function addEvents_ (events) { + events.forEach(function(eventName) { + listen(this.element_, eventName, this.eventHandler_, this); + }.bind(this)); + }; + + /** + * Unregister listeners for the given events. + * @private + * @param {Array} events List of events. + */ + PointerEventHandler.prototype.removeEvents_ = function removeEvents_ (events) { + events.forEach(function(e) { + unlisten(this.element_, e, this.eventHandler_, this); + }.bind(this)); + }; + + /** + * Returns a snapshot of inEvent, with writable properties. + * + * @param {Event} event Browser event. + * @param {Event|Touch} inEvent An event that contains + * properties to copy. + * @return {Object} An object containing shallow copies of + * `inEvent`'s properties. + */ + PointerEventHandler.prototype.cloneEvent = function cloneEvent (event, inEvent) { + var eventCopy = {}; + for (var i = 0, ii = CLONE_PROPS.length; i < ii; i++) { + var p = CLONE_PROPS[i][0]; + eventCopy[p] = event[p] || inEvent[p] || CLONE_PROPS[i][1]; + } + + return eventCopy; + }; + + // EVENTS + + + /** + * Triggers a 'pointerdown' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.down = function down (data, event) { + this.fireEvent(pointer_EventType.POINTERDOWN, data, event); + }; + + /** + * Triggers a 'pointermove' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.move = function move (data, event) { + this.fireEvent(pointer_EventType.POINTERMOVE, data, event); + }; + + /** + * Triggers a 'pointerup' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.up = function up (data, event) { + this.fireEvent(pointer_EventType.POINTERUP, data, event); + }; + + /** + * Triggers a 'pointerenter' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.enter = function enter (data, event) { + data.bubbles = false; + this.fireEvent(pointer_EventType.POINTERENTER, data, event); + }; + + /** + * Triggers a 'pointerleave' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.leave = function leave (data, event) { + data.bubbles = false; + this.fireEvent(pointer_EventType.POINTERLEAVE, data, event); + }; + + /** + * Triggers a 'pointerover' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.over = function over (data, event) { + data.bubbles = true; + this.fireEvent(pointer_EventType.POINTEROVER, data, event); + }; + + /** + * Triggers a 'pointerout' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.out = function out (data, event) { + data.bubbles = true; + this.fireEvent(pointer_EventType.POINTEROUT, data, event); + }; + + /** + * Triggers a 'pointercancel' event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.cancel = function cancel (data, event) { + this.fireEvent(pointer_EventType.POINTERCANCEL, data, event); + }; + + /** + * Triggers a combination of 'pointerout' and 'pointerleave' events. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.leaveOut = function leaveOut (data, event) { + this.out(data, event); + if (!this.contains_(data.target, data.relatedTarget)) { + this.leave(data, event); + } + }; + + /** + * Triggers a combination of 'pointerover' and 'pointerevents' events. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.enterOver = function enterOver (data, event) { + this.over(data, event); + if (!this.contains_(data.target, data.relatedTarget)) { + this.enter(data, event); + } + }; + + /** + * @private + * @param {Element} container The container element. + * @param {Element} contained The contained element. + * @return {boolean} Returns true if the container element + * contains the other element. + */ + PointerEventHandler.prototype.contains_ = function contains_ (container, contained) { + if (!container || !contained) { + return false; + } + return container.contains(contained); + }; + + // EVENT CREATION AND TRACKING + /** + * Creates a new Event of type `inType`, based on the information in + * `data`. + * + * @param {string} inType A string representing the type of event to create. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + * @return {PointerEvent} A PointerEvent of type `inType`. + */ + PointerEventHandler.prototype.makeEvent = function makeEvent (inType, data, event) { + return new pointer_PointerEvent(inType, event, data); + }; + + /** + * Make and dispatch an event in one call. + * @param {string} inType A string representing the type of event. + * @param {Object} data Pointer event data. + * @param {Event} event The event. + */ + PointerEventHandler.prototype.fireEvent = function fireEvent (inType, data, event) { + var e = this.makeEvent(inType, data, event); + this.dispatchEvent(e); + }; + + /** + * Creates a pointer event from a native pointer event + * and dispatches this event. + * @param {Event} event A platform event with a target. + */ + PointerEventHandler.prototype.fireNativeEvent = function fireNativeEvent (event) { + var e = this.makeEvent(event.type, event, event); + this.dispatchEvent(e); + }; + + /** + * Wrap a native mouse event into a pointer event. + * This proxy method is required for the legacy IE support. + * @param {string} eventType The pointer event type. + * @param {Event} event The event. + * @return {PointerEvent} The wrapped event. + */ + PointerEventHandler.prototype.wrapMouseEvent = function wrapMouseEvent (eventType, event) { + var pointerEvent = this.makeEvent( + eventType, prepareEvent(event, this), event); + return pointerEvent; + }; + + /** + * @inheritDoc + */ + PointerEventHandler.prototype.disposeInternal = function disposeInternal () { + this.unregister_(); + EventTarget.prototype.disposeInternal.call(this); + }; + + return PointerEventHandler; +}(events_Target)); + +/* harmony default export */ var pointer_PointerEventHandler = (PointerEventHandler_PointerEventHandler); + +//# sourceMappingURL=PointerEventHandler.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapBrowserEventHandler.js +/** + * @module ol/MapBrowserEventHandler + */ + + + + + + + + +var MapBrowserEventHandler_MapBrowserEventHandler = /*@__PURE__*/(function (EventTarget) { + function MapBrowserEventHandler(map, moveTolerance) { + + EventTarget.call(this); + + /** + * This is the element that we will listen to the real events on. + * @type {import("./PluggableMap.js").default} + * @private + */ + this.map_ = map; + + /** + * @type {any} + * @private + */ + this.clickTimeoutId_; + + /** + * @type {boolean} + * @private + */ + this.dragging_ = false; + + /** + * @type {!Array} + * @private + */ + this.dragListenerKeys_ = []; + + /** + * @type {number} + * @private + */ + this.moveTolerance_ = moveTolerance ? + moveTolerance * DEVICE_PIXEL_RATIO : DEVICE_PIXEL_RATIO; + + /** + * The most recent "down" type event (or null if none have occurred). + * Set on pointerdown. + * @type {import("./pointer/PointerEvent.js").default} + * @private + */ + this.down_ = null; + + var element = this.map_.getViewport(); + + /** + * @type {number} + * @private + */ + this.activePointers_ = 0; + + /** + * @type {!Object} + * @private + */ + this.trackedTouches_ = {}; + + /** + * Event handler which generates pointer events for + * the viewport element. + * + * @type {PointerEventHandler} + * @private + */ + this.pointerEventHandler_ = new pointer_PointerEventHandler(element); + + /** + * Event handler which generates pointer events for + * the document (used when dragging). + * + * @type {PointerEventHandler} + * @private + */ + this.documentPointerEventHandler_ = null; + + /** + * @type {?import("./events.js").EventsKey} + * @private + */ + this.pointerdownListenerKey_ = listen(this.pointerEventHandler_, + pointer_EventType.POINTERDOWN, + this.handlePointerDown_, this); + + /** + * @type {?import("./events.js").EventsKey} + * @private + */ + this.relayedListenerKey_ = listen(this.pointerEventHandler_, + pointer_EventType.POINTERMOVE, + this.relayEvent_, this); + + } + + if ( EventTarget ) MapBrowserEventHandler.__proto__ = EventTarget; + MapBrowserEventHandler.prototype = Object.create( EventTarget && EventTarget.prototype ); + MapBrowserEventHandler.prototype.constructor = MapBrowserEventHandler; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.emulateClick_ = function emulateClick_ (pointerEvent) { + var newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.CLICK, this.map_, pointerEvent); + this.dispatchEvent(newEvent); + if (this.clickTimeoutId_ !== undefined) { + // double-click + clearTimeout(this.clickTimeoutId_); + this.clickTimeoutId_ = undefined; + newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.DBLCLICK, this.map_, pointerEvent); + this.dispatchEvent(newEvent); + } else { + // click + this.clickTimeoutId_ = setTimeout(function() { + this.clickTimeoutId_ = undefined; + var newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.SINGLECLICK, this.map_, pointerEvent); + this.dispatchEvent(newEvent); + }.bind(this), 250); + } + }; + + /** + * Keeps track on how many pointers are currently active. + * + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.updateActivePointers_ = function updateActivePointers_ (pointerEvent) { + var event = pointerEvent; + + if (event.type == MapBrowserEventType.POINTERUP || + event.type == MapBrowserEventType.POINTERCANCEL) { + delete this.trackedTouches_[event.pointerId]; + } else if (event.type == MapBrowserEventType.POINTERDOWN) { + this.trackedTouches_[event.pointerId] = true; + } + this.activePointers_ = Object.keys(this.trackedTouches_).length; + }; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.handlePointerUp_ = function handlePointerUp_ (pointerEvent) { + this.updateActivePointers_(pointerEvent); + var newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.POINTERUP, this.map_, pointerEvent); + this.dispatchEvent(newEvent); + + // We emulate click events on left mouse button click, touch contact, and pen + // contact. isMouseActionButton returns true in these cases (evt.button is set + // to 0). + // See http://www.w3.org/TR/pointerevents/#button-states + // We only fire click, singleclick, and doubleclick if nobody has called + // event.stopPropagation() or event.preventDefault(). + if (!newEvent.propagationStopped && !this.dragging_ && this.isMouseActionButton_(pointerEvent)) { + this.emulateClick_(this.down_); + } + + if (this.activePointers_ === 0) { + this.dragListenerKeys_.forEach(unlistenByKey); + this.dragListenerKeys_.length = 0; + this.dragging_ = false; + this.down_ = null; + this.documentPointerEventHandler_.dispose(); + this.documentPointerEventHandler_ = null; + } + }; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @return {boolean} If the left mouse button was pressed. + * @private + */ + MapBrowserEventHandler.prototype.isMouseActionButton_ = function isMouseActionButton_ (pointerEvent) { + return pointerEvent.button === 0; + }; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.handlePointerDown_ = function handlePointerDown_ (pointerEvent) { + this.updateActivePointers_(pointerEvent); + var newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.POINTERDOWN, this.map_, pointerEvent); + this.dispatchEvent(newEvent); + + this.down_ = pointerEvent; + + if (this.dragListenerKeys_.length === 0) { + /* Set up a pointer event handler on the `document`, + * which is required when the pointer is moved outside + * the viewport when dragging. + */ + this.documentPointerEventHandler_ = + new pointer_PointerEventHandler(document); + + this.dragListenerKeys_.push( + listen(this.documentPointerEventHandler_, + MapBrowserEventType.POINTERMOVE, + this.handlePointerMove_, this), + listen(this.documentPointerEventHandler_, + MapBrowserEventType.POINTERUP, + this.handlePointerUp_, this), + /* Note that the listener for `pointercancel is set up on + * `pointerEventHandler_` and not `documentPointerEventHandler_` like + * the `pointerup` and `pointermove` listeners. + * + * The reason for this is the following: `TouchSource.vacuumTouches_()` + * issues `pointercancel` events, when there was no `touchend` for a + * `touchstart`. Now, let's say a first `touchstart` is registered on + * `pointerEventHandler_`. The `documentPointerEventHandler_` is set up. + * But `documentPointerEventHandler_` doesn't know about the first + * `touchstart`. If there is no `touchend` for the `touchstart`, we can + * only receive a `touchcancel` from `pointerEventHandler_`, because it is + * only registered there. + */ + listen(this.pointerEventHandler_, + MapBrowserEventType.POINTERCANCEL, + this.handlePointerUp_, this) + ); + } + }; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.handlePointerMove_ = function handlePointerMove_ (pointerEvent) { + // Between pointerdown and pointerup, pointermove events are triggered. + // To avoid a 'false' touchmove event to be dispatched, we test if the pointer + // moved a significant distance. + if (this.isMoving_(pointerEvent)) { + this.dragging_ = true; + var newEvent = new ol_MapBrowserPointerEvent( + MapBrowserEventType.POINTERDRAG, this.map_, pointerEvent, + this.dragging_); + this.dispatchEvent(newEvent); + } + + // Some native android browser triggers mousemove events during small period + // of time. See: https://code.google.com/p/android/issues/detail?id=5491 or + // https://code.google.com/p/android/issues/detail?id=19827 + // ex: Galaxy Tab P3110 + Android 4.1.1 + pointerEvent.preventDefault(); + }; + + /** + * Wrap and relay a pointer event. Note that this requires that the type + * string for the MapBrowserPointerEvent matches the PointerEvent type. + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @private + */ + MapBrowserEventHandler.prototype.relayEvent_ = function relayEvent_ (pointerEvent) { + var dragging = !!(this.down_ && this.isMoving_(pointerEvent)); + this.dispatchEvent(new ol_MapBrowserPointerEvent( + pointerEvent.type, this.map_, pointerEvent, dragging)); + }; + + /** + * @param {import("./pointer/PointerEvent.js").default} pointerEvent Pointer + * event. + * @return {boolean} Is moving. + * @private + */ + MapBrowserEventHandler.prototype.isMoving_ = function isMoving_ (pointerEvent) { + return this.dragging_ || + Math.abs(pointerEvent.clientX - this.down_.clientX) > this.moveTolerance_ || + Math.abs(pointerEvent.clientY - this.down_.clientY) > this.moveTolerance_; + }; + + /** + * @inheritDoc + */ + MapBrowserEventHandler.prototype.disposeInternal = function disposeInternal () { + if (this.relayedListenerKey_) { + unlistenByKey(this.relayedListenerKey_); + this.relayedListenerKey_ = null; + } + if (this.pointerdownListenerKey_) { + unlistenByKey(this.pointerdownListenerKey_); + this.pointerdownListenerKey_ = null; + } + + this.dragListenerKeys_.forEach(unlistenByKey); + this.dragListenerKeys_.length = 0; + + if (this.documentPointerEventHandler_) { + this.documentPointerEventHandler_.dispose(); + this.documentPointerEventHandler_ = null; + } + if (this.pointerEventHandler_) { + this.pointerEventHandler_.dispose(); + this.pointerEventHandler_ = null; + } + EventTarget.prototype.disposeInternal.call(this); + }; + + return MapBrowserEventHandler; +}(events_Target)); + + +/* harmony default export */ var ol_MapBrowserEventHandler = (MapBrowserEventHandler_MapBrowserEventHandler); + +//# sourceMappingURL=MapBrowserEventHandler.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapEventType.js +/** + * @module ol/MapEventType + */ + +/** + * @enum {string} + */ +/* harmony default export */ var MapEventType = ({ + + /** + * Triggered after a map frame is rendered. + * @event module:ol/MapEvent~MapEvent#postrender + * @api + */ + POSTRENDER: 'postrender', + + /** + * Triggered when the map starts moving. + * @event module:ol/MapEvent~MapEvent#movestart + * @api + */ + MOVESTART: 'movestart', + + /** + * Triggered after the map is moved. + * @event module:ol/MapEvent~MapEvent#moveend + * @api + */ + MOVEEND: 'moveend' + +}); + +//# sourceMappingURL=MapEventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/MapProperty.js +/** + * @module ol/MapProperty + */ + +/** + * @enum {string} + */ +/* harmony default export */ var MapProperty = ({ + LAYERGROUP: 'layergroup', + SIZE: 'size', + TARGET: 'target', + VIEW: 'view' +}); + +//# sourceMappingURL=MapProperty.js.map +// CONCATENATED MODULE: ./node_modules/ol/render/EventType.js +/** + * @module ol/render/EventType + */ + +/** + * @enum {string} + */ +/* harmony default export */ var render_EventType = ({ + /** + * @event module:ol/render/Event~RenderEvent#postcompose + * @api + */ + POSTCOMPOSE: 'postcompose', + /** + * @event module:ol/render/Event~RenderEvent#precompose + * @api + */ + PRECOMPOSE: 'precompose', + /** + * @event module:ol/render/Event~RenderEvent#render + * @api + */ + RENDER: 'render', + /** + * Triggered when rendering is complete, i.e. all sources and tiles have + * finished loading for the current viewport, and all tiles are faded in. + * @event module:ol/render/Event~RenderEvent#rendercomplete + * @api + */ + RENDERCOMPLETE: 'rendercomplete' +}); + +//# sourceMappingURL=EventType.js.map +// CONCATENATED MODULE: ./node_modules/ol/TileState.js +/** + * @module ol/TileState + */ + +/** + * @enum {number} + */ +/* harmony default export */ var TileState = ({ + IDLE: 0, + LOADING: 1, + LOADED: 2, + /** + * Indicates that tile loading failed + * @type {number} + */ + ERROR: 3, + EMPTY: 4, + ABORT: 5 +}); + +//# sourceMappingURL=TileState.js.map +// CONCATENATED MODULE: ./node_modules/ol/asserts.js +/** + * @module ol/asserts + */ + + +/** + * @param {*} assertion Assertion we expected to be truthy. + * @param {number} errorCode Error code. + */ +function assert(assertion, errorCode) { + if (!assertion) { + throw new ol_AssertionError(errorCode); + } +} + +//# sourceMappingURL=asserts.js.map +// CONCATENATED MODULE: ./node_modules/ol/structs/PriorityQueue.js +/** + * @module ol/structs/PriorityQueue + */ + + + + +/** + * @type {number} + */ +var DROP = Infinity; + + +/** + * @classdesc + * Priority queue. + * + * The implementation is inspired from the Closure Library's Heap class and + * Python's heapq module. + * + * See http://closure-library.googlecode.com/svn/docs/closure_goog_structs_heap.js.source.html + * and http://hg.python.org/cpython/file/2.7/Lib/heapq.py. + * + * @template T + */ +var PriorityQueue_PriorityQueue = function PriorityQueue(priorityFunction, keyFunction) { + + /** + * @type {function(T): number} + * @private + */ + this.priorityFunction_ = priorityFunction; + + /** + * @type {function(T): string} + * @private + */ + this.keyFunction_ = keyFunction; + + /** + * @type {Array} + * @private + */ + this.elements_ = []; + + /** + * @type {Array} + * @private + */ + this.priorities_ = []; + + /** + * @type {!Object} + * @private + */ + this.queuedElements_ = {}; + +}; + +/** + * FIXME empty description for jsdoc + */ +PriorityQueue_PriorityQueue.prototype.clear = function clear$1 () { + this.elements_.length = 0; + this.priorities_.length = 0; + obj_clear(this.queuedElements_); +}; + + +/** + * Remove and return the highest-priority element. O(log N). + * @return {T} Element. + */ +PriorityQueue_PriorityQueue.prototype.dequeue = function dequeue () { + var elements = this.elements_; + var priorities = this.priorities_; + var element = elements[0]; + if (elements.length == 1) { + elements.length = 0; + priorities.length = 0; + } else { + elements[0] = elements.pop(); + priorities[0] = priorities.pop(); + this.siftUp_(0); + } + var elementKey = this.keyFunction_(element); + delete this.queuedElements_[elementKey]; + return element; +}; + + +/** + * Enqueue an element. O(log N). + * @param {T} element Element. + * @return {boolean} The element was added to the queue. + */ +PriorityQueue_PriorityQueue.prototype.enqueue = function enqueue (element) { + assert(!(this.keyFunction_(element) in this.queuedElements_), + 31); // Tried to enqueue an `element` that was already added to the queue + var priority = this.priorityFunction_(element); + if (priority != DROP) { + this.elements_.push(element); + this.priorities_.push(priority); + this.queuedElements_[this.keyFunction_(element)] = true; + this.siftDown_(0, this.elements_.length - 1); + return true; + } + return false; +}; + + +/** + * @return {number} Count. + */ +PriorityQueue_PriorityQueue.prototype.getCount = function getCount () { + return this.elements_.length; +}; + + +/** + * Gets the index of the left child of the node at the given index. + * @param {number} index The index of the node to get the left child for. + * @return {number} The index of the left child. + * @private + */ +PriorityQueue_PriorityQueue.prototype.getLeftChildIndex_ = function getLeftChildIndex_ (index) { + return index * 2 + 1; +}; + + +/** + * Gets the index of the right child of the node at the given index. + * @param {number} index The index of the node to get the right child for. + * @return {number} The index of the right child. + * @private + */ +PriorityQueue_PriorityQueue.prototype.getRightChildIndex_ = function getRightChildIndex_ (index) { + return index * 2 + 2; +}; + + +/** + * Gets the index of the parent of the node at the given index. + * @param {number} index The index of the node to get the parent for. + * @return {number} The index of the parent. + * @private + */ +PriorityQueue_PriorityQueue.prototype.getParentIndex_ = function getParentIndex_ (index) { + return (index - 1) >> 1; +}; + + +/** + * Make this a heap. O(N). + * @private + */ +PriorityQueue_PriorityQueue.prototype.heapify_ = function heapify_ () { + var i; + for (i = (this.elements_.length >> 1) - 1; i >= 0; i--) { + this.siftUp_(i); + } +}; + + +/** + * @return {boolean} Is empty. + */ +PriorityQueue_PriorityQueue.prototype.isEmpty = function isEmpty () { + return this.elements_.length === 0; +}; + + +/** + * @param {string} key Key. + * @return {boolean} Is key queued. + */ +PriorityQueue_PriorityQueue.prototype.isKeyQueued = function isKeyQueued (key) { + return key in this.queuedElements_; +}; + + +/** + * @param {T} element Element. + * @return {boolean} Is queued. + */ +PriorityQueue_PriorityQueue.prototype.isQueued = function isQueued (element) { + return this.isKeyQueued(this.keyFunction_(element)); +}; + + +/** + * @param {number} index The index of the node to move down. + * @private + */ +PriorityQueue_PriorityQueue.prototype.siftUp_ = function siftUp_ (index) { + var elements = this.elements_; + var priorities = this.priorities_; + var count = elements.length; + var element = elements[index]; + var priority = priorities[index]; + var startIndex = index; + + while (index < (count >> 1)) { + var lIndex = this.getLeftChildIndex_(index); + var rIndex = this.getRightChildIndex_(index); + + var smallerChildIndex = rIndex < count && + priorities[rIndex] < priorities[lIndex] ? + rIndex : lIndex; + + elements[index] = elements[smallerChildIndex]; + priorities[index] = priorities[smallerChildIndex]; + index = smallerChildIndex; + } + + elements[index] = element; + priorities[index] = priority; + this.siftDown_(startIndex, index); +}; + + +/** + * @param {number} startIndex The index of the root. + * @param {number} index The index of the node to move up. + * @private + */ +PriorityQueue_PriorityQueue.prototype.siftDown_ = function siftDown_ (startIndex, index) { + var elements = this.elements_; + var priorities = this.priorities_; + var element = elements[index]; + var priority = priorities[index]; + + while (index > startIndex) { + var parentIndex = this.getParentIndex_(index); + if (priorities[parentIndex] > priority) { + elements[index] = elements[parentIndex]; + priorities[index] = priorities[parentIndex]; + index = parentIndex; + } else { + break; + } + } + elements[index] = element; + priorities[index] = priority; +}; + + +/** + * FIXME empty description for jsdoc + */ +PriorityQueue_PriorityQueue.prototype.reprioritize = function reprioritize () { + var priorityFunction = this.priorityFunction_; + var elements = this.elements_; + var priorities = this.priorities_; + var index = 0; + var n = elements.length; + var element, i, priority; + for (i = 0; i < n; ++i) { + element = elements[i]; + priority = priorityFunction(element); + if (priority == DROP) { + delete this.queuedElements_[this.keyFunction_(element)]; + } else { + priorities[index] = priority; + elements[index++] = element; + } + } + elements.length = index; + priorities.length = index; + this.heapify_(); +}; + + +/* harmony default export */ var structs_PriorityQueue = (PriorityQueue_PriorityQueue); + +//# sourceMappingURL=PriorityQueue.js.map +// CONCATENATED MODULE: ./node_modules/ol/TileQueue.js +/** + * @module ol/TileQueue + */ + + + + + + +/** + * @typedef {function(import("./Tile.js").default, string, import("./coordinate.js").Coordinate, number): number} PriorityFunction + */ + + +var TileQueue_TileQueue = /*@__PURE__*/(function (PriorityQueue) { + function TileQueue(tilePriorityFunction, tileChangeCallback) { + + PriorityQueue.call( + /** + * @param {Array} element Element. + * @return {number} Priority. + */ + this, function(element) { + return tilePriorityFunction.apply(null, element); + }, + /** + * @param {Array} element Element. + * @return {string} Key. + */ + function(element) { + return (/** @type {import("./Tile.js").default} */ (element[0]).getKey()); + }); + + /** + * @private + * @type {function(): ?} + */ + this.tileChangeCallback_ = tileChangeCallback; + + /** + * @private + * @type {number} + */ + this.tilesLoading_ = 0; + + /** + * @private + * @type {!Object} + */ + this.tilesLoadingKeys_ = {}; + + } + + if ( PriorityQueue ) TileQueue.__proto__ = PriorityQueue; + TileQueue.prototype = Object.create( PriorityQueue && PriorityQueue.prototype ); + TileQueue.prototype.constructor = TileQueue; + + /** + * @inheritDoc + */ + TileQueue.prototype.enqueue = function enqueue (element) { + var added = PriorityQueue.prototype.enqueue.call(this, element); + if (added) { + var tile = element[0]; + listen(tile, EventType.CHANGE, this.handleTileChange, this); + } + return added; + }; + + /** + * @return {number} Number of tiles loading. + */ + TileQueue.prototype.getTilesLoading = function getTilesLoading () { + return this.tilesLoading_; + }; + + /** + * @param {import("./events/Event.js").default} event Event. + * @protected + */ + TileQueue.prototype.handleTileChange = function handleTileChange (event) { + var tile = /** @type {import("./Tile.js").default} */ (event.target); + var state = tile.getState(); + if (state === TileState.LOADED || state === TileState.ERROR || + state === TileState.EMPTY || state === TileState.ABORT) { + unlisten(tile, EventType.CHANGE, this.handleTileChange, this); + var tileKey = tile.getKey(); + if (tileKey in this.tilesLoadingKeys_) { + delete this.tilesLoadingKeys_[tileKey]; + --this.tilesLoading_; + } + this.tileChangeCallback_(); + } + }; + + /** + * @param {number} maxTotalLoading Maximum number tiles to load simultaneously. + * @param {number} maxNewLoads Maximum number of new tiles to load. + */ + TileQueue.prototype.loadMoreTiles = function loadMoreTiles (maxTotalLoading, maxNewLoads) { + var newLoads = 0; + var abortedTiles = false; + var state, tile, tileKey; + while (this.tilesLoading_ < maxTotalLoading && newLoads < maxNewLoads && + this.getCount() > 0) { + tile = /** @type {import("./Tile.js").default} */ (this.dequeue()[0]); + tileKey = tile.getKey(); + state = tile.getState(); + if (state === TileState.ABORT) { + abortedTiles = true; + } else if (state === TileState.IDLE && !(tileKey in this.tilesLoadingKeys_)) { + this.tilesLoadingKeys_[tileKey] = true; + ++this.tilesLoading_; + ++newLoads; + tile.load(); + } + } + if (newLoads === 0 && abortedTiles) { + // Do not stop the render loop when all wanted tiles were aborted due to + // a small, saturated tile cache. + this.tileChangeCallback_(); + } + }; + + return TileQueue; +}(structs_PriorityQueue)); + + +/* harmony default export */ var ol_TileQueue = (TileQueue_TileQueue); + +//# sourceMappingURL=TileQueue.js.map +// CONCATENATED MODULE: ./node_modules/ol/tilegrid/common.js +/** + * @module ol/tilegrid/common + */ + +/** + * Default maximum zoom for default tile grids. + * @type {number} + */ +var DEFAULT_MAX_ZOOM = 42; + +/** + * Default tile size. + * @type {number} + */ +var DEFAULT_TILE_SIZE = 256; + +//# sourceMappingURL=common.js.map +// CONCATENATED MODULE: ./node_modules/ol/math.js +/** + * @module ol/math + */ + + +/** + * Takes a number and clamps it to within the provided bounds. + * @param {number} value The input number. + * @param {number} min The minimum value to return. + * @param {number} max The maximum value to return. + * @return {number} The input number if it is within bounds, or the nearest + * number within the bounds. + */ +function clamp(value, min, max) { + return Math.min(Math.max(value, min), max); +} + + +/** + * Return the hyperbolic cosine of a given number. The method will use the + * native `Math.cosh` function if it is available, otherwise the hyperbolic + * cosine will be calculated via the reference implementation of the Mozilla + * developer network. + * + * @param {number} x X. + * @return {number} Hyperbolic cosine of x. + */ +var cosh = (function() { + // Wrapped in a iife, to save the overhead of checking for the native + // implementation on every invocation. + var cosh; + if ('cosh' in Math) { + // The environment supports the native Math.cosh function, use it… + cosh = Math.cosh; + } else { + // … else, use the reference implementation of MDN: + cosh = function(x) { + var y = /** @type {Math} */ (Math).exp(x); + return (y + 1 / y) / 2; + }; + } + return cosh; +}()); + + +/** + * @param {number} x X. + * @return {number} The smallest power of two greater than or equal to x. + */ +function roundUpToPowerOfTwo(x) { + assert(0 < x, 29); // `x` must be greater than `0` + return Math.pow(2, Math.ceil(Math.log(x) / Math.LN2)); +} + + +/** + * Returns the square of the closest distance between the point (x, y) and the + * line segment (x1, y1) to (x2, y2). + * @param {number} x X. + * @param {number} y Y. + * @param {number} x1 X1. + * @param {number} y1 Y1. + * @param {number} x2 X2. + * @param {number} y2 Y2. + * @return {number} Squared distance. + */ +function squaredSegmentDistance(x, y, x1, y1, x2, y2) { + var dx = x2 - x1; + var dy = y2 - y1; + if (dx !== 0 || dy !== 0) { + var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy); + if (t > 1) { + x1 = x2; + y1 = y2; + } else if (t > 0) { + x1 += dx * t; + y1 += dy * t; + } + } + return math_squaredDistance(x, y, x1, y1); +} + + +/** + * Returns the square of the distance between the points (x1, y1) and (x2, y2). + * @param {number} x1 X1. + * @param {number} y1 Y1. + * @param {number} x2 X2. + * @param {number} y2 Y2. + * @return {number} Squared distance. + */ +function math_squaredDistance(x1, y1, x2, y2) { + var dx = x2 - x1; + var dy = y2 - y1; + return dx * dx + dy * dy; +} + + +/** + * Solves system of linear equations using Gaussian elimination method. + * + * @param {Array>} mat Augmented matrix (n x n + 1 column) + * in row-major order. + * @return {Array} The resulting vector. + */ +function solveLinearSystem(mat) { + var n = mat.length; + + for (var i = 0; i < n; i++) { + // Find max in the i-th column (ignoring i - 1 first rows) + var maxRow = i; + var maxEl = Math.abs(mat[i][i]); + for (var r = i + 1; r < n; r++) { + var absValue = Math.abs(mat[r][i]); + if (absValue > maxEl) { + maxEl = absValue; + maxRow = r; + } + } + + if (maxEl === 0) { + return null; // matrix is singular + } + + // Swap max row with i-th (current) row + var tmp = mat[maxRow]; + mat[maxRow] = mat[i]; + mat[i] = tmp; + + // Subtract the i-th row to make all the remaining rows 0 in the i-th column + for (var j = i + 1; j < n; j++) { + var coef = -mat[j][i] / mat[i][i]; + for (var k = i; k < n + 1; k++) { + if (i == k) { + mat[j][k] = 0; + } else { + mat[j][k] += coef * mat[i][k]; + } + } + } + } + + // Solve Ax=b for upper triangular matrix A (mat) + var x = new Array(n); + for (var l = n - 1; l >= 0; l--) { + x[l] = mat[l][n] / mat[l][l]; + for (var m = l - 1; m >= 0; m--) { + mat[m][n] -= mat[m][l] * x[l]; + } + } + return x; +} + + +/** + * Converts radians to to degrees. + * + * @param {number} angleInRadians Angle in radians. + * @return {number} Angle in degrees. + */ +function toDegrees(angleInRadians) { + return angleInRadians * 180 / Math.PI; +} + + +/** + * Converts degrees to radians. + * + * @param {number} angleInDegrees Angle in degrees. + * @return {number} Angle in radians. + */ +function toRadians(angleInDegrees) { + return angleInDegrees * Math.PI / 180; +} + +/** + * Returns the modulo of a / b, depending on the sign of b. + * + * @param {number} a Dividend. + * @param {number} b Divisor. + * @return {number} Modulo. + */ +function modulo(a, b) { + var r = a % b; + return r * b < 0 ? r + b : r; +} + +/** + * Calculates the linearly interpolated value of x between a and b. + * + * @param {number} a Number + * @param {number} b Number + * @param {number} x Value to be interpolated. + * @return {number} Interpolated value. + */ +function lerp(a, b, x) { + return a + x * (b - a); +} + +//# sourceMappingURL=math.js.map +// CONCATENATED MODULE: ./node_modules/ol/centerconstraint.js +/** + * @module ol/centerconstraint + */ + + + +/** + * @typedef {function((import("./coordinate.js").Coordinate|undefined)): (import("./coordinate.js").Coordinate|undefined)} Type + */ + + +/** + * @param {import("./extent.js").Extent} extent Extent. + * @return {Type} The constraint. + */ +function createExtent(extent) { + return ( + /** + * @param {import("./coordinate.js").Coordinate=} center Center. + * @return {import("./coordinate.js").Coordinate|undefined} Center. + */ + function(center) { + if (center) { + return [ + clamp(center[0], extent[0], extent[2]), + clamp(center[1], extent[1], extent[3]) + ]; + } else { + return undefined; + } + } + ); +} + + +/** + * @param {import("./coordinate.js").Coordinate=} center Center. + * @return {import("./coordinate.js").Coordinate|undefined} Center. + */ +function none(center) { + return center; +} + +//# sourceMappingURL=centerconstraint.js.map +// CONCATENATED MODULE: ./node_modules/ol/resolutionconstraint.js +/** + * @module ol/resolutionconstraint + */ + + + + +/** + * @typedef {function((number|undefined), number, number): (number|undefined)} Type + */ + + +/** + * @param {Array} resolutions Resolutions. + * @return {Type} Zoom function. + */ +function createSnapToResolutions(resolutions) { + return ( + /** + * @param {number|undefined} resolution Resolution. + * @param {number} delta Delta. + * @param {number} direction Direction. + * @return {number|undefined} Resolution. + */ + function(resolution, delta, direction) { + if (resolution !== undefined) { + var z = linearFindNearest(resolutions, resolution, direction); + z = clamp(z + delta, 0, resolutions.length - 1); + var index = Math.floor(z); + if (z != index && index < resolutions.length - 1) { + var power = resolutions[index] / resolutions[index + 1]; + return resolutions[index] / Math.pow(power, z - index); + } else { + return resolutions[index]; + } + } else { + return undefined; + } + } + ); +} + + +/** + * @param {number} power Power. + * @param {number} maxResolution Maximum resolution. + * @param {number=} opt_maxLevel Maximum level. + * @return {Type} Zoom function. + */ +function createSnapToPower(power, maxResolution, opt_maxLevel) { + return ( + /** + * @param {number|undefined} resolution Resolution. + * @param {number} delta Delta. + * @param {number} direction Direction. + * @return {number|undefined} Resolution. + */ + function(resolution, delta, direction) { + if (resolution !== undefined) { + var offset = -direction / 2 + 0.5; + var oldLevel = Math.floor( + Math.log(maxResolution / resolution) / Math.log(power) + offset); + var newLevel = Math.max(oldLevel + delta, 0); + if (opt_maxLevel !== undefined) { + newLevel = Math.min(newLevel, opt_maxLevel); + } + return maxResolution / Math.pow(power, newLevel); + } else { + return undefined; + } + }); +} + +//# sourceMappingURL=resolutionconstraint.js.map +// CONCATENATED MODULE: ./node_modules/ol/rotationconstraint.js +/** + * @module ol/rotationconstraint + */ + + + +/** + * @typedef {function((number|undefined), number): (number|undefined)} Type + */ + + +/** + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + * @return {number|undefined} Rotation. + */ +function disable(rotation, delta) { + if (rotation !== undefined) { + return 0; + } else { + return undefined; + } +} + + +/** + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + * @return {number|undefined} Rotation. + */ +function rotationconstraint_none(rotation, delta) { + if (rotation !== undefined) { + return rotation + delta; + } else { + return undefined; + } +} + + +/** + * @param {number} n N. + * @return {Type} Rotation constraint. + */ +function createSnapToN(n) { + var theta = 2 * Math.PI / n; + return ( + /** + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + * @return {number|undefined} Rotation. + */ + function(rotation, delta) { + if (rotation !== undefined) { + rotation = Math.floor((rotation + delta) / theta + 0.5) * theta; + return rotation; + } else { + return undefined; + } + }); +} + + +/** + * @param {number=} opt_tolerance Tolerance. + * @return {Type} Rotation constraint. + */ +function createSnapToZero(opt_tolerance) { + var tolerance = opt_tolerance || toRadians(5); + return ( + /** + * @param {number|undefined} rotation Rotation. + * @param {number} delta Delta. + * @return {number|undefined} Rotation. + */ + function(rotation, delta) { + if (rotation !== undefined) { + if (Math.abs(rotation + delta) <= tolerance) { + return 0; + } else { + return rotation + delta; + } + } else { + return undefined; + } + }); +} + +//# sourceMappingURL=rotationconstraint.js.map +// CONCATENATED MODULE: ./node_modules/ol/ViewHint.js +/** + * @module ol/ViewHint + */ + +/** + * @enum {number} + */ +/* harmony default export */ var ViewHint = ({ + ANIMATING: 0, + INTERACTING: 1 +}); + +//# sourceMappingURL=ViewHint.js.map +// CONCATENATED MODULE: ./node_modules/ol/ViewProperty.js +/** + * @module ol/ViewProperty + */ + +/** + * @enum {string} + */ +/* harmony default export */ var ViewProperty = ({ + CENTER: 'center', + RESOLUTION: 'resolution', + ROTATION: 'rotation' +}); + +//# sourceMappingURL=ViewProperty.js.map +// CONCATENATED MODULE: ./node_modules/ol/string.js +/** + * @module ol/string + */ + +/** + * @param {number} number Number to be formatted + * @param {number} width The desired width + * @param {number=} opt_precision Precision of the output string (i.e. number of decimal places) + * @returns {string} Formatted string + */ +function padNumber(number, width, opt_precision) { + var numberString = opt_precision !== undefined ? number.toFixed(opt_precision) : '' + number; + var decimal = numberString.indexOf('.'); + decimal = decimal === -1 ? numberString.length : decimal; + return decimal > width ? numberString : new Array(1 + width - decimal).join('0') + numberString; +} + + +/** + * Adapted from https://github.com/omichelsen/compare-versions/blob/master/index.js + * @param {string|number} v1 First version + * @param {string|number} v2 Second version + * @returns {number} Value + */ +function compareVersions(v1, v2) { + var s1 = ('' + v1).split('.'); + var s2 = ('' + v2).split('.'); + + for (var i = 0; i < Math.max(s1.length, s2.length); i++) { + var n1 = parseInt(s1[i] || '0', 10); + var n2 = parseInt(s2[i] || '0', 10); + + if (n1 > n2) { + return 1; + } + if (n2 > n1) { + return -1; + } + } + + return 0; +} + +//# sourceMappingURL=string.js.map +// CONCATENATED MODULE: ./node_modules/ol/coordinate.js +/** + * @module ol/coordinate + */ + + + + +/** + * An array of numbers representing an xy coordinate. Example: `[16, 48]`. + * @typedef {Array} Coordinate + * @api + */ + + +/** + * A function that takes a {@link module:ol/coordinate~Coordinate} and + * transforms it into a `{string}`. + * + * @typedef {function((Coordinate|undefined)): string} CoordinateFormat + * @api + */ + + +/** + * Add `delta` to `coordinate`. `coordinate` is modified in place and returned + * by the function. + * + * Example: + * + * import {add} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * add(coord, [-2, 4]); + * // coord is now [5.85, 51.983333] + * + * @param {Coordinate} coordinate Coordinate. + * @param {Coordinate} delta Delta. + * @return {Coordinate} The input coordinate adjusted by + * the given delta. + * @api + */ +function add(coordinate, delta) { + coordinate[0] += delta[0]; + coordinate[1] += delta[1]; + return coordinate; +} + + +/** + * Calculates the point closest to the passed coordinate on the passed circle. + * + * @param {Coordinate} coordinate The coordinate. + * @param {import("./geom/Circle.js").default} circle The circle. + * @return {Coordinate} Closest point on the circumference. + */ +function closestOnCircle(coordinate, circle) { + var r = circle.getRadius(); + var center = circle.getCenter(); + var x0 = center[0]; + var y0 = center[1]; + var x1 = coordinate[0]; + var y1 = coordinate[1]; + + var dx = x1 - x0; + var dy = y1 - y0; + if (dx === 0 && dy === 0) { + dx = 1; + } + var d = Math.sqrt(dx * dx + dy * dy); + + var x = x0 + r * dx / d; + var y = y0 + r * dy / d; + + return [x, y]; +} + + +/** + * Calculates the point closest to the passed coordinate on the passed segment. + * This is the foot of the perpendicular of the coordinate to the segment when + * the foot is on the segment, or the closest segment coordinate when the foot + * is outside the segment. + * + * @param {Coordinate} coordinate The coordinate. + * @param {Array} segment The two coordinates + * of the segment. + * @return {Coordinate} The foot of the perpendicular of + * the coordinate to the segment. + */ +function closestOnSegment(coordinate, segment) { + var x0 = coordinate[0]; + var y0 = coordinate[1]; + var start = segment[0]; + var end = segment[1]; + var x1 = start[0]; + var y1 = start[1]; + var x2 = end[0]; + var y2 = end[1]; + var dx = x2 - x1; + var dy = y2 - y1; + var along = (dx === 0 && dy === 0) ? 0 : + ((dx * (x0 - x1)) + (dy * (y0 - y1))) / ((dx * dx + dy * dy) || 0); + var x, y; + if (along <= 0) { + x = x1; + y = y1; + } else if (along >= 1) { + x = x2; + y = y2; + } else { + x = x1 + along * dx; + y = y1 + along * dy; + } + return [x, y]; +} + + +/** + * Returns a {@link module:ol/coordinate~CoordinateFormat} function that can be + * used to format + * a {Coordinate} to a string. + * + * Example without specifying the fractional digits: + * + * import {createStringXY} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var stringifyFunc = createStringXY(); + * var out = stringifyFunc(coord); + * // out is now '8, 48' + * + * Example with explicitly specifying 2 fractional digits: + * + * import {createStringXY} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var stringifyFunc = createStringXY(2); + * var out = stringifyFunc(coord); + * // out is now '7.85, 47.98' + * + * @param {number=} opt_fractionDigits The number of digits to include + * after the decimal point. Default is `0`. + * @return {CoordinateFormat} Coordinate format. + * @api + */ +function createStringXY(opt_fractionDigits) { + return ( + /** + * @param {Coordinate} coordinate Coordinate. + * @return {string} String XY. + */ + function(coordinate) { + return toStringXY(coordinate, opt_fractionDigits); + } + ); +} + + +/** + * @param {string} hemispheres Hemispheres. + * @param {number} degrees Degrees. + * @param {number=} opt_fractionDigits The number of digits to include + * after the decimal point. Default is `0`. + * @return {string} String. + */ +function degreesToStringHDMS(hemispheres, degrees, opt_fractionDigits) { + var normalizedDegrees = modulo(degrees + 180, 360) - 180; + var x = Math.abs(3600 * normalizedDegrees); + var dflPrecision = opt_fractionDigits || 0; + var precision = Math.pow(10, dflPrecision); + + var deg = Math.floor(x / 3600); + var min = Math.floor((x - deg * 3600) / 60); + var sec = x - (deg * 3600) - (min * 60); + sec = Math.ceil(sec * precision) / precision; + + if (sec >= 60) { + sec = 0; + min += 1; + } + + if (min >= 60) { + min = 0; + deg += 1; + } + + return deg + '\u00b0 ' + padNumber(min, 2) + '\u2032 ' + + padNumber(sec, 2, dflPrecision) + '\u2033' + + (normalizedDegrees == 0 ? '' : ' ' + hemispheres.charAt(normalizedDegrees < 0 ? 1 : 0)); +} + + +/** + * Transforms the given {@link module:ol/coordinate~Coordinate} to a string + * using the given string template. The strings `{x}` and `{y}` in the template + * will be replaced with the first and second coordinate values respectively. + * + * Example without specifying the fractional digits: + * + * import {format} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var template = 'Coordinate is ({x}|{y}).'; + * var out = format(coord, template); + * // out is now 'Coordinate is (8|48).' + * + * Example explicitly specifying the fractional digits: + * + * import {format} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var template = 'Coordinate is ({x}|{y}).'; + * var out = format(coord, template, 2); + * // out is now 'Coordinate is (7.85|47.98).' + * + * @param {Coordinate} coordinate Coordinate. + * @param {string} template A template string with `{x}` and `{y}` placeholders + * that will be replaced by first and second coordinate values. + * @param {number=} opt_fractionDigits The number of digits to include + * after the decimal point. Default is `0`. + * @return {string} Formatted coordinate. + * @api + */ +function format(coordinate, template, opt_fractionDigits) { + if (coordinate) { + return template + .replace('{x}', coordinate[0].toFixed(opt_fractionDigits)) + .replace('{y}', coordinate[1].toFixed(opt_fractionDigits)); + } else { + return ''; + } +} + + +/** + * @param {Coordinate} coordinate1 First coordinate. + * @param {Coordinate} coordinate2 Second coordinate. + * @return {boolean} The two coordinates are equal. + */ +function coordinate_equals(coordinate1, coordinate2) { + var equals = true; + for (var i = coordinate1.length - 1; i >= 0; --i) { + if (coordinate1[i] != coordinate2[i]) { + equals = false; + break; + } + } + return equals; +} + + +/** + * Rotate `coordinate` by `angle`. `coordinate` is modified in place and + * returned by the function. + * + * Example: + * + * import {rotate} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var rotateRadians = Math.PI / 2; // 90 degrees + * rotate(coord, rotateRadians); + * // coord is now [-47.983333, 7.85] + * + * @param {Coordinate} coordinate Coordinate. + * @param {number} angle Angle in radian. + * @return {Coordinate} Coordinate. + * @api + */ +function coordinate_rotate(coordinate, angle) { + var cosAngle = Math.cos(angle); + var sinAngle = Math.sin(angle); + var x = coordinate[0] * cosAngle - coordinate[1] * sinAngle; + var y = coordinate[1] * cosAngle + coordinate[0] * sinAngle; + coordinate[0] = x; + coordinate[1] = y; + return coordinate; +} + + +/** + * Scale `coordinate` by `scale`. `coordinate` is modified in place and returned + * by the function. + * + * Example: + * + * import {scale as scaleCoordinate} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var scale = 1.2; + * scaleCoordinate(coord, scale); + * // coord is now [9.42, 57.5799996] + * + * @param {Coordinate} coordinate Coordinate. + * @param {number} scale Scale factor. + * @return {Coordinate} Coordinate. + */ +function coordinate_scale(coordinate, scale) { + coordinate[0] *= scale; + coordinate[1] *= scale; + return coordinate; +} + + +/** + * @param {Coordinate} coord1 First coordinate. + * @param {Coordinate} coord2 Second coordinate. + * @return {number} Squared distance between coord1 and coord2. + */ +function coordinate_squaredDistance(coord1, coord2) { + var dx = coord1[0] - coord2[0]; + var dy = coord1[1] - coord2[1]; + return dx * dx + dy * dy; +} + + +/** + * @param {Coordinate} coord1 First coordinate. + * @param {Coordinate} coord2 Second coordinate. + * @return {number} Distance between coord1 and coord2. + */ +function coordinate_distance(coord1, coord2) { + return Math.sqrt(coordinate_squaredDistance(coord1, coord2)); +} + + +/** + * Calculate the squared distance from a coordinate to a line segment. + * + * @param {Coordinate} coordinate Coordinate of the point. + * @param {Array} segment Line segment (2 + * coordinates). + * @return {number} Squared distance from the point to the line segment. + */ +function squaredDistanceToSegment(coordinate, segment) { + return coordinate_squaredDistance(coordinate, + closestOnSegment(coordinate, segment)); +} + + +/** + * Format a geographic coordinate with the hemisphere, degrees, minutes, and + * seconds. + * + * Example without specifying fractional digits: + * + * import {toStringHDMS} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var out = toStringHDMS(coord); + * // out is now '47° 58′ 60″ N 7° 50′ 60″ E' + * + * Example explicitly specifying 1 fractional digit: + * + * import {toStringHDMS} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var out = toStringHDMS(coord, 1); + * // out is now '47° 58′ 60.0″ N 7° 50′ 60.0″ E' + * + * @param {Coordinate} coordinate Coordinate. + * @param {number=} opt_fractionDigits The number of digits to include + * after the decimal point. Default is `0`. + * @return {string} Hemisphere, degrees, minutes and seconds. + * @api + */ +function toStringHDMS(coordinate, opt_fractionDigits) { + if (coordinate) { + return degreesToStringHDMS('NS', coordinate[1], opt_fractionDigits) + ' ' + + degreesToStringHDMS('EW', coordinate[0], opt_fractionDigits); + } else { + return ''; + } +} + + +/** + * Format a coordinate as a comma delimited string. + * + * Example without specifying fractional digits: + * + * import {toStringXY} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var out = toStringXY(coord); + * // out is now '8, 48' + * + * Example explicitly specifying 1 fractional digit: + * + * import {toStringXY} from 'ol/coordinate'; + * + * var coord = [7.85, 47.983333]; + * var out = toStringXY(coord, 1); + * // out is now '7.8, 48.0' + * + * @param {Coordinate} coordinate Coordinate. + * @param {number=} opt_fractionDigits The number of digits to include + * after the decimal point. Default is `0`. + * @return {string} XY. + * @api + */ +function toStringXY(coordinate, opt_fractionDigits) { + return format(coordinate, '{x}, {y}', opt_fractionDigits); +} + +//# sourceMappingURL=coordinate.js.map +// CONCATENATED MODULE: ./node_modules/ol/easing.js +/** + * @module ol/easing + */ + + +/** + * Start slow and speed up. + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + * @api + */ +function easeIn(t) { + return Math.pow(t, 3); +} + + +/** + * Start fast and slow down. + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + * @api + */ +function easeOut(t) { + return 1 - easeIn(1 - t); +} + + +/** + * Start slow, speed up, and then slow down again. + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + * @api + */ +function inAndOut(t) { + return 3 * t * t - 2 * t * t * t; +} + + +/** + * Maintain a constant speed over time. + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + * @api + */ +function linear(t) { + return t; +} + + +/** + * Start slow, speed up, and at the very end slow down again. This has the + * same general behavior as {@link module:ol/easing~inAndOut}, but the final + * slowdown is delayed. + * @param {number} t Input between 0 and 1. + * @return {number} Output between 0 and 1. + * @api + */ +function upAndDown(t) { + if (t < 0.5) { + return inAndOut(2 * t); + } else { + return 1 - inAndOut(2 * (t - 0.5)); + } +} + +//# sourceMappingURL=easing.js.map +// CONCATENATED MODULE: ./node_modules/ol/extent/Corner.js +/** + * @module ol/extent/Corner + */ + +/** + * Extent corner. + * @enum {string} + */ +/* harmony default export */ var Corner = ({ + BOTTOM_LEFT: 'bottom-left', + BOTTOM_RIGHT: 'bottom-right', + TOP_LEFT: 'top-left', + TOP_RIGHT: 'top-right' +}); + +//# sourceMappingURL=Corner.js.map +// CONCATENATED MODULE: ./node_modules/ol/extent/Relationship.js +/** + * @module ol/extent/Relationship + */ + +/** + * Relationship to an extent. + * @enum {number} + */ +/* harmony default export */ var Relationship = ({ + UNKNOWN: 0, + INTERSECTING: 1, + ABOVE: 2, + RIGHT: 4, + BELOW: 8, + LEFT: 16 +}); + +//# sourceMappingURL=Relationship.js.map +// CONCATENATED MODULE: ./node_modules/ol/extent.js +/** + * @module ol/extent + */ + + + + + +/** + * An array of numbers representing an extent: `[minx, miny, maxx, maxy]`. + * @typedef {Array} Extent + * @api + */ + +/** + * Build an extent that includes all given coordinates. + * + * @param {Array} coordinates Coordinates. + * @return {Extent} Bounding extent. + * @api + */ +function boundingExtent(coordinates) { + var extent = createEmpty(); + for (var i = 0, ii = coordinates.length; i < ii; ++i) { + extendCoordinate(extent, coordinates[i]); + } + return extent; +} + + +/** + * @param {Array} xs Xs. + * @param {Array} ys Ys. + * @param {Extent=} opt_extent Destination extent. + * @private + * @return {Extent} Extent. + */ +function _boundingExtentXYs(xs, ys, opt_extent) { + var minX = Math.min.apply(null, xs); + var minY = Math.min.apply(null, ys); + var maxX = Math.max.apply(null, xs); + var maxY = Math.max.apply(null, ys); + return createOrUpdate(minX, minY, maxX, maxY, opt_extent); +} + + +/** + * Return extent increased by the provided value. + * @param {Extent} extent Extent. + * @param {number} value The amount by which the extent should be buffered. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + * @api + */ +function buffer(extent, value, opt_extent) { + if (opt_extent) { + opt_extent[0] = extent[0] - value; + opt_extent[1] = extent[1] - value; + opt_extent[2] = extent[2] + value; + opt_extent[3] = extent[3] + value; + return opt_extent; + } else { + return [ + extent[0] - value, + extent[1] - value, + extent[2] + value, + extent[3] + value + ]; + } +} + + +/** + * Creates a clone of an extent. + * + * @param {Extent} extent Extent to clone. + * @param {Extent=} opt_extent Extent. + * @return {Extent} The clone. + */ +function extent_clone(extent, opt_extent) { + if (opt_extent) { + opt_extent[0] = extent[0]; + opt_extent[1] = extent[1]; + opt_extent[2] = extent[2]; + opt_extent[3] = extent[3]; + return opt_extent; + } else { + return extent.slice(); + } +} + + +/** + * @param {Extent} extent Extent. + * @param {number} x X. + * @param {number} y Y. + * @return {number} Closest squared distance. + */ +function closestSquaredDistanceXY(extent, x, y) { + var dx, dy; + if (x < extent[0]) { + dx = extent[0] - x; + } else if (extent[2] < x) { + dx = x - extent[2]; + } else { + dx = 0; + } + if (y < extent[1]) { + dy = extent[1] - y; + } else if (extent[3] < y) { + dy = y - extent[3]; + } else { + dy = 0; + } + return dx * dx + dy * dy; +} + + +/** + * Check if the passed coordinate is contained or on the edge of the extent. + * + * @param {Extent} extent Extent. + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate. + * @return {boolean} The coordinate is contained in the extent. + * @api + */ +function containsCoordinate(extent, coordinate) { + return extent_containsXY(extent, coordinate[0], coordinate[1]); +} + + +/** + * Check if one extent contains another. + * + * An extent is deemed contained if it lies completely within the other extent, + * including if they share one or more edges. + * + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent 2. + * @return {boolean} The second extent is contained by or on the edge of the + * first. + * @api + */ +function containsExtent(extent1, extent2) { + return extent1[0] <= extent2[0] && extent2[2] <= extent1[2] && + extent1[1] <= extent2[1] && extent2[3] <= extent1[3]; +} + + +/** + * Check if the passed coordinate is contained or on the edge of the extent. + * + * @param {Extent} extent Extent. + * @param {number} x X coordinate. + * @param {number} y Y coordinate. + * @return {boolean} The x, y values are contained in the extent. + * @api + */ +function extent_containsXY(extent, x, y) { + return extent[0] <= x && x <= extent[2] && extent[1] <= y && y <= extent[3]; +} + + +/** + * Get the relationship between a coordinate and extent. + * @param {Extent} extent The extent. + * @param {import("./coordinate.js").Coordinate} coordinate The coordinate. + * @return {Relationship} The relationship (bitwise compare with + * import("./extent/Relationship.js").Relationship). + */ +function coordinateRelationship(extent, coordinate) { + var minX = extent[0]; + var minY = extent[1]; + var maxX = extent[2]; + var maxY = extent[3]; + var x = coordinate[0]; + var y = coordinate[1]; + var relationship = Relationship.UNKNOWN; + if (x < minX) { + relationship = relationship | Relationship.LEFT; + } else if (x > maxX) { + relationship = relationship | Relationship.RIGHT; + } + if (y < minY) { + relationship = relationship | Relationship.BELOW; + } else if (y > maxY) { + relationship = relationship | Relationship.ABOVE; + } + if (relationship === Relationship.UNKNOWN) { + relationship = Relationship.INTERSECTING; + } + return relationship; +} + + +/** + * Create an empty extent. + * @return {Extent} Empty extent. + * @api + */ +function createEmpty() { + return [Infinity, Infinity, -Infinity, -Infinity]; +} + + +/** + * Create a new extent or update the provided extent. + * @param {number} minX Minimum X. + * @param {number} minY Minimum Y. + * @param {number} maxX Maximum X. + * @param {number} maxY Maximum Y. + * @param {Extent=} opt_extent Destination extent. + * @return {Extent} Extent. + */ +function createOrUpdate(minX, minY, maxX, maxY, opt_extent) { + if (opt_extent) { + opt_extent[0] = minX; + opt_extent[1] = minY; + opt_extent[2] = maxX; + opt_extent[3] = maxY; + return opt_extent; + } else { + return [minX, minY, maxX, maxY]; + } +} + + +/** + * Create a new empty extent or make the provided one empty. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function createOrUpdateEmpty(opt_extent) { + return createOrUpdate( + Infinity, Infinity, -Infinity, -Infinity, opt_extent); +} + + +/** + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function createOrUpdateFromCoordinate(coordinate, opt_extent) { + var x = coordinate[0]; + var y = coordinate[1]; + return createOrUpdate(x, y, x, y, opt_extent); +} + + +/** + * @param {Array} coordinates Coordinates. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function createOrUpdateFromCoordinates(coordinates, opt_extent) { + var extent = createOrUpdateEmpty(opt_extent); + return extendCoordinates(extent, coordinates); +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function createOrUpdateFromFlatCoordinates(flatCoordinates, offset, end, stride, opt_extent) { + var extent = createOrUpdateEmpty(opt_extent); + return extendFlatCoordinates(extent, flatCoordinates, offset, end, stride); +} + +/** + * @param {Array>} rings Rings. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function createOrUpdateFromRings(rings, opt_extent) { + var extent = createOrUpdateEmpty(opt_extent); + return extendRings(extent, rings); +} + + +/** + * Determine if two extents are equivalent. + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent 2. + * @return {boolean} The two extents are equivalent. + * @api + */ +function extent_equals(extent1, extent2) { + return extent1[0] == extent2[0] && extent1[2] == extent2[2] && + extent1[1] == extent2[1] && extent1[3] == extent2[3]; +} + + +/** + * Modify an extent to include another extent. + * @param {Extent} extent1 The extent to be modified. + * @param {Extent} extent2 The extent that will be included in the first. + * @return {Extent} A reference to the first (extended) extent. + * @api + */ +function extent_extend(extent1, extent2) { + if (extent2[0] < extent1[0]) { + extent1[0] = extent2[0]; + } + if (extent2[2] > extent1[2]) { + extent1[2] = extent2[2]; + } + if (extent2[1] < extent1[1]) { + extent1[1] = extent2[1]; + } + if (extent2[3] > extent1[3]) { + extent1[3] = extent2[3]; + } + return extent1; +} + + +/** + * @param {Extent} extent Extent. + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate. + */ +function extendCoordinate(extent, coordinate) { + if (coordinate[0] < extent[0]) { + extent[0] = coordinate[0]; + } + if (coordinate[0] > extent[2]) { + extent[2] = coordinate[0]; + } + if (coordinate[1] < extent[1]) { + extent[1] = coordinate[1]; + } + if (coordinate[1] > extent[3]) { + extent[3] = coordinate[1]; + } +} + + +/** + * @param {Extent} extent Extent. + * @param {Array} coordinates Coordinates. + * @return {Extent} Extent. + */ +function extendCoordinates(extent, coordinates) { + for (var i = 0, ii = coordinates.length; i < ii; ++i) { + extendCoordinate(extent, coordinates[i]); + } + return extent; +} + + +/** + * @param {Extent} extent Extent. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @return {Extent} Extent. + */ +function extendFlatCoordinates(extent, flatCoordinates, offset, end, stride) { + for (; offset < end; offset += stride) { + extendXY(extent, flatCoordinates[offset], flatCoordinates[offset + 1]); + } + return extent; +} + + +/** + * @param {Extent} extent Extent. + * @param {Array>} rings Rings. + * @return {Extent} Extent. + */ +function extendRings(extent, rings) { + for (var i = 0, ii = rings.length; i < ii; ++i) { + extendCoordinates(extent, rings[i]); + } + return extent; +} + + +/** + * @param {Extent} extent Extent. + * @param {number} x X. + * @param {number} y Y. + */ +function extendXY(extent, x, y) { + extent[0] = Math.min(extent[0], x); + extent[1] = Math.min(extent[1], y); + extent[2] = Math.max(extent[2], x); + extent[3] = Math.max(extent[3], y); +} + + +/** + * This function calls `callback` for each corner of the extent. If the + * callback returns a truthy value the function returns that value + * immediately. Otherwise the function returns `false`. + * @param {Extent} extent Extent. + * @param {function(this:T, import("./coordinate.js").Coordinate): S} callback Callback. + * @param {T=} opt_this Value to use as `this` when executing `callback`. + * @return {S|boolean} Value. + * @template S, T + */ +function forEachCorner(extent, callback, opt_this) { + var val; + val = callback.call(opt_this, getBottomLeft(extent)); + if (val) { + return val; + } + val = callback.call(opt_this, getBottomRight(extent)); + if (val) { + return val; + } + val = callback.call(opt_this, getTopRight(extent)); + if (val) { + return val; + } + val = callback.call(opt_this, getTopLeft(extent)); + if (val) { + return val; + } + return false; +} + + +/** + * Get the size of an extent. + * @param {Extent} extent Extent. + * @return {number} Area. + * @api + */ +function extent_getArea(extent) { + var area = 0; + if (!extent_isEmpty(extent)) { + area = getWidth(extent) * getHeight(extent); + } + return area; +} + + +/** + * Get the bottom left coordinate of an extent. + * @param {Extent} extent Extent. + * @return {import("./coordinate.js").Coordinate} Bottom left coordinate. + * @api + */ +function getBottomLeft(extent) { + return [extent[0], extent[1]]; +} + + +/** + * Get the bottom right coordinate of an extent. + * @param {Extent} extent Extent. + * @return {import("./coordinate.js").Coordinate} Bottom right coordinate. + * @api + */ +function getBottomRight(extent) { + return [extent[2], extent[1]]; +} + + +/** + * Get the center coordinate of an extent. + * @param {Extent} extent Extent. + * @return {import("./coordinate.js").Coordinate} Center. + * @api + */ +function extent_getCenter(extent) { + return [(extent[0] + extent[2]) / 2, (extent[1] + extent[3]) / 2]; +} + + +/** + * Get a corner coordinate of an extent. + * @param {Extent} extent Extent. + * @param {Corner} corner Corner. + * @return {import("./coordinate.js").Coordinate} Corner coordinate. + */ +function getCorner(extent, corner) { + var coordinate; + if (corner === Corner.BOTTOM_LEFT) { + coordinate = getBottomLeft(extent); + } else if (corner === Corner.BOTTOM_RIGHT) { + coordinate = getBottomRight(extent); + } else if (corner === Corner.TOP_LEFT) { + coordinate = getTopLeft(extent); + } else if (corner === Corner.TOP_RIGHT) { + coordinate = getTopRight(extent); + } else { + assert(false, 13); // Invalid corner + } + return coordinate; +} + + +/** + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent 2. + * @return {number} Enlarged area. + */ +function getEnlargedArea(extent1, extent2) { + var minX = Math.min(extent1[0], extent2[0]); + var minY = Math.min(extent1[1], extent2[1]); + var maxX = Math.max(extent1[2], extent2[2]); + var maxY = Math.max(extent1[3], extent2[3]); + return (maxX - minX) * (maxY - minY); +} + + +/** + * @param {import("./coordinate.js").Coordinate} center Center. + * @param {number} resolution Resolution. + * @param {number} rotation Rotation. + * @param {import("./size.js").Size} size Size. + * @param {Extent=} opt_extent Destination extent. + * @return {Extent} Extent. + */ +function getForViewAndSize(center, resolution, rotation, size, opt_extent) { + var dx = resolution * size[0] / 2; + var dy = resolution * size[1] / 2; + var cosRotation = Math.cos(rotation); + var sinRotation = Math.sin(rotation); + var xCos = dx * cosRotation; + var xSin = dx * sinRotation; + var yCos = dy * cosRotation; + var ySin = dy * sinRotation; + var x = center[0]; + var y = center[1]; + var x0 = x - xCos + ySin; + var x1 = x - xCos - ySin; + var x2 = x + xCos - ySin; + var x3 = x + xCos + ySin; + var y0 = y - xSin - yCos; + var y1 = y - xSin + yCos; + var y2 = y + xSin + yCos; + var y3 = y + xSin - yCos; + return createOrUpdate( + Math.min(x0, x1, x2, x3), Math.min(y0, y1, y2, y3), + Math.max(x0, x1, x2, x3), Math.max(y0, y1, y2, y3), + opt_extent); +} + + +/** + * Get the height of an extent. + * @param {Extent} extent Extent. + * @return {number} Height. + * @api + */ +function getHeight(extent) { + return extent[3] - extent[1]; +} + + +/** + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent 2. + * @return {number} Intersection area. + */ +function getIntersectionArea(extent1, extent2) { + var intersection = getIntersection(extent1, extent2); + return extent_getArea(intersection); +} + + +/** + * Get the intersection of two extents. + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent 2. + * @param {Extent=} opt_extent Optional extent to populate with intersection. + * @return {Extent} Intersecting extent. + * @api + */ +function getIntersection(extent1, extent2, opt_extent) { + var intersection = opt_extent ? opt_extent : createEmpty(); + if (extent_intersects(extent1, extent2)) { + if (extent1[0] > extent2[0]) { + intersection[0] = extent1[0]; + } else { + intersection[0] = extent2[0]; + } + if (extent1[1] > extent2[1]) { + intersection[1] = extent1[1]; + } else { + intersection[1] = extent2[1]; + } + if (extent1[2] < extent2[2]) { + intersection[2] = extent1[2]; + } else { + intersection[2] = extent2[2]; + } + if (extent1[3] < extent2[3]) { + intersection[3] = extent1[3]; + } else { + intersection[3] = extent2[3]; + } + } else { + createOrUpdateEmpty(intersection); + } + return intersection; +} + + +/** + * @param {Extent} extent Extent. + * @return {number} Margin. + */ +function getMargin(extent) { + return getWidth(extent) + getHeight(extent); +} + + +/** + * Get the size (width, height) of an extent. + * @param {Extent} extent The extent. + * @return {import("./size.js").Size} The extent size. + * @api + */ +function extent_getSize(extent) { + return [extent[2] - extent[0], extent[3] - extent[1]]; +} + + +/** + * Get the top left coordinate of an extent. + * @param {Extent} extent Extent. + * @return {import("./coordinate.js").Coordinate} Top left coordinate. + * @api + */ +function getTopLeft(extent) { + return [extent[0], extent[3]]; +} + + +/** + * Get the top right coordinate of an extent. + * @param {Extent} extent Extent. + * @return {import("./coordinate.js").Coordinate} Top right coordinate. + * @api + */ +function getTopRight(extent) { + return [extent[2], extent[3]]; +} + + +/** + * Get the width of an extent. + * @param {Extent} extent Extent. + * @return {number} Width. + * @api + */ +function getWidth(extent) { + return extent[2] - extent[0]; +} + + +/** + * Determine if one extent intersects another. + * @param {Extent} extent1 Extent 1. + * @param {Extent} extent2 Extent. + * @return {boolean} The two extents intersect. + * @api + */ +function extent_intersects(extent1, extent2) { + return extent1[0] <= extent2[2] && + extent1[2] >= extent2[0] && + extent1[1] <= extent2[3] && + extent1[3] >= extent2[1]; +} + + +/** + * Determine if an extent is empty. + * @param {Extent} extent Extent. + * @return {boolean} Is empty. + * @api + */ +function extent_isEmpty(extent) { + return extent[2] < extent[0] || extent[3] < extent[1]; +} + + +/** + * @param {Extent} extent Extent. + * @param {Extent=} opt_extent Extent. + * @return {Extent} Extent. + */ +function returnOrUpdate(extent, opt_extent) { + if (opt_extent) { + opt_extent[0] = extent[0]; + opt_extent[1] = extent[1]; + opt_extent[2] = extent[2]; + opt_extent[3] = extent[3]; + return opt_extent; + } else { + return extent; + } +} + + +/** + * @param {Extent} extent Extent. + * @param {number} value Value. + */ +function scaleFromCenter(extent, value) { + var deltaX = ((extent[2] - extent[0]) / 2) * (value - 1); + var deltaY = ((extent[3] - extent[1]) / 2) * (value - 1); + extent[0] -= deltaX; + extent[2] += deltaX; + extent[1] -= deltaY; + extent[3] += deltaY; +} + + +/** + * Determine if the segment between two coordinates intersects (crosses, + * touches, or is contained by) the provided extent. + * @param {Extent} extent The extent. + * @param {import("./coordinate.js").Coordinate} start Segment start coordinate. + * @param {import("./coordinate.js").Coordinate} end Segment end coordinate. + * @return {boolean} The segment intersects the extent. + */ +function intersectsSegment(extent, start, end) { + var intersects = false; + var startRel = coordinateRelationship(extent, start); + var endRel = coordinateRelationship(extent, end); + if (startRel === Relationship.INTERSECTING || + endRel === Relationship.INTERSECTING) { + intersects = true; + } else { + var minX = extent[0]; + var minY = extent[1]; + var maxX = extent[2]; + var maxY = extent[3]; + var startX = start[0]; + var startY = start[1]; + var endX = end[0]; + var endY = end[1]; + var slope = (endY - startY) / (endX - startX); + var x, y; + if (!!(endRel & Relationship.ABOVE) && + !(startRel & Relationship.ABOVE)) { + // potentially intersects top + x = endX - ((endY - maxY) / slope); + intersects = x >= minX && x <= maxX; + } + if (!intersects && !!(endRel & Relationship.RIGHT) && + !(startRel & Relationship.RIGHT)) { + // potentially intersects right + y = endY - ((endX - maxX) * slope); + intersects = y >= minY && y <= maxY; + } + if (!intersects && !!(endRel & Relationship.BELOW) && + !(startRel & Relationship.BELOW)) { + // potentially intersects bottom + x = endX - ((endY - minY) / slope); + intersects = x >= minX && x <= maxX; + } + if (!intersects && !!(endRel & Relationship.LEFT) && + !(startRel & Relationship.LEFT)) { + // potentially intersects left + y = endY - ((endX - minX) * slope); + intersects = y >= minY && y <= maxY; + } + + } + return intersects; +} + + +/** + * Apply a transform function to the extent. + * @param {Extent} extent Extent. + * @param {import("./proj.js").TransformFunction} transformFn Transform function. + * Called with `[minX, minY, maxX, maxY]` extent coordinates. + * @param {Extent=} opt_extent Destination extent. + * @return {Extent} Extent. + * @api + */ +function extent_applyTransform(extent, transformFn, opt_extent) { + var coordinates = [ + extent[0], extent[1], + extent[0], extent[3], + extent[2], extent[1], + extent[2], extent[3] + ]; + transformFn(coordinates, coordinates, 2); + var xs = [coordinates[0], coordinates[2], coordinates[4], coordinates[6]]; + var ys = [coordinates[1], coordinates[3], coordinates[5], coordinates[7]]; + return _boundingExtentXYs(xs, ys, opt_extent); +} + +//# sourceMappingURL=extent.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/GeometryType.js +/** + * @module ol/geom/GeometryType + */ + +/** + * The geometry type. One of `'Point'`, `'LineString'`, `'LinearRing'`, + * `'Polygon'`, `'MultiPoint'`, `'MultiLineString'`, `'MultiPolygon'`, + * `'GeometryCollection'`, `'Circle'`. + * @enum {string} + */ +/* harmony default export */ var GeometryType = ({ + POINT: 'Point', + LINE_STRING: 'LineString', + LINEAR_RING: 'LinearRing', + POLYGON: 'Polygon', + MULTI_POINT: 'MultiPoint', + MULTI_LINE_STRING: 'MultiLineString', + MULTI_POLYGON: 'MultiPolygon', + GEOMETRY_COLLECTION: 'GeometryCollection', + CIRCLE: 'Circle' +}); + +//# sourceMappingURL=GeometryType.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/GeometryLayout.js +/** + * @module ol/geom/GeometryLayout + */ + +/** + * The coordinate layout for geometries, indicating whether a 3rd or 4th z ('Z') + * or measure ('M') coordinate is available. Supported values are `'XY'`, + * `'XYZ'`, `'XYM'`, `'XYZM'`. + * @enum {string} + */ +/* harmony default export */ var GeometryLayout = ({ + XY: 'XY', + XYZ: 'XYZ', + XYM: 'XYM', + XYZM: 'XYZM' +}); + +//# sourceMappingURL=GeometryLayout.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/transform.js +/** + * @module ol/geom/flat/transform + */ + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {import("../../transform.js").Transform} transform Transform. + * @param {Array=} opt_dest Destination. + * @return {Array} Transformed coordinates. + */ +function transform2D(flatCoordinates, offset, end, stride, transform, opt_dest) { + var dest = opt_dest ? opt_dest : []; + var i = 0; + for (var j = offset; j < end; j += stride) { + var x = flatCoordinates[j]; + var y = flatCoordinates[j + 1]; + dest[i++] = transform[0] * x + transform[2] * y + transform[4]; + dest[i++] = transform[1] * x + transform[3] * y + transform[5]; + } + if (opt_dest && dest.length != i) { + dest.length = i; + } + return dest; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} angle Angle. + * @param {Array} anchor Rotation anchor point. + * @param {Array=} opt_dest Destination. + * @return {Array} Transformed coordinates. + */ +function transform_rotate(flatCoordinates, offset, end, stride, angle, anchor, opt_dest) { + var dest = opt_dest ? opt_dest : []; + var cos = Math.cos(angle); + var sin = Math.sin(angle); + var anchorX = anchor[0]; + var anchorY = anchor[1]; + var i = 0; + for (var j = offset; j < end; j += stride) { + var deltaX = flatCoordinates[j] - anchorX; + var deltaY = flatCoordinates[j + 1] - anchorY; + dest[i++] = anchorX + deltaX * cos - deltaY * sin; + dest[i++] = anchorY + deltaX * sin + deltaY * cos; + for (var k = j + 2; k < j + stride; ++k) { + dest[i++] = flatCoordinates[k]; + } + } + if (opt_dest && dest.length != i) { + dest.length = i; + } + return dest; +} + + +/** + * Scale the coordinates. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} sx Scale factor in the x-direction. + * @param {number} sy Scale factor in the y-direction. + * @param {Array} anchor Scale anchor point. + * @param {Array=} opt_dest Destination. + * @return {Array} Transformed coordinates. + */ +function transform_scale(flatCoordinates, offset, end, stride, sx, sy, anchor, opt_dest) { + var dest = opt_dest ? opt_dest : []; + var anchorX = anchor[0]; + var anchorY = anchor[1]; + var i = 0; + for (var j = offset; j < end; j += stride) { + var deltaX = flatCoordinates[j] - anchorX; + var deltaY = flatCoordinates[j + 1] - anchorY; + dest[i++] = anchorX + sx * deltaX; + dest[i++] = anchorY + sy * deltaY; + for (var k = j + 2; k < j + stride; ++k) { + dest[i++] = flatCoordinates[k]; + } + } + if (opt_dest && dest.length != i) { + dest.length = i; + } + return dest; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} deltaX Delta X. + * @param {number} deltaY Delta Y. + * @param {Array=} opt_dest Destination. + * @return {Array} Transformed coordinates. + */ +function transform_translate(flatCoordinates, offset, end, stride, deltaX, deltaY, opt_dest) { + var dest = opt_dest ? opt_dest : []; + var i = 0; + for (var j = offset; j < end; j += stride) { + dest[i++] = flatCoordinates[j] + deltaX; + dest[i++] = flatCoordinates[j + 1] + deltaY; + for (var k = j + 2; k < j + stride; ++k) { + dest[i++] = flatCoordinates[k]; + } + } + if (opt_dest && dest.length != i) { + dest.length = i; + } + return dest; +} + +//# sourceMappingURL=transform.js.map +// CONCATENATED MODULE: ./node_modules/ol/sphere.js +/** + * @license + * Latitude/longitude spherical geodesy formulae taken from + * http://www.movable-type.co.uk/scripts/latlong.html + * Licensed under CC-BY-3.0. + */ + +/** + * @module ol/sphere + */ + + + + +/** + * Object literal with options for the {@link getLength} or {@link getArea} + * functions. + * @typedef {Object} SphereMetricOptions + * @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] + * Projection of the geometry. By default, the geometry is assumed to be in + * Web Mercator. + * @property {number} [radius=6371008.8] Sphere radius. By default, the radius of the + * earth is used (Clarke 1866 Authalic Sphere). + */ + + +/** + * The mean Earth radius (1/3 * (2a + b)) for the WGS84 ellipsoid. + * https://en.wikipedia.org/wiki/Earth_radius#Mean_radius + * @type {number} + */ +var DEFAULT_RADIUS = 6371008.8; + + +/** + * Get the great circle distance (in meters) between two geographic coordinates. + * @param {Array} c1 Starting coordinate. + * @param {Array} c2 Ending coordinate. + * @param {number=} opt_radius The sphere radius to use. Defaults to the Earth's + * mean radius using the WGS84 ellipsoid. + * @return {number} The great circle distance between the points (in meters). + * @api + */ +function getDistance(c1, c2, opt_radius) { + var radius = opt_radius || DEFAULT_RADIUS; + var lat1 = toRadians(c1[1]); + var lat2 = toRadians(c2[1]); + var deltaLatBy2 = (lat2 - lat1) / 2; + var deltaLonBy2 = toRadians(c2[0] - c1[0]) / 2; + var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) + + Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) * + Math.cos(lat1) * Math.cos(lat2); + return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); +} + + +/** + * Get the cumulative great circle length of linestring coordinates (geographic). + * @param {Array} coordinates Linestring coordinates. + * @param {number} radius The sphere radius to use. + * @return {number} The length (in meters). + */ +function getLengthInternal(coordinates, radius) { + var length = 0; + for (var i = 0, ii = coordinates.length; i < ii - 1; ++i) { + length += getDistance(coordinates[i], coordinates[i + 1], radius); + } + return length; +} + + +/** + * Get the spherical length of a geometry. This length is the sum of the + * great circle distances between coordinates. For polygons, the length is + * the sum of all rings. For points, the length is zero. For multi-part + * geometries, the length is the sum of the length of each part. + * @param {import("./geom/Geometry.js").default} geometry A geometry. + * @param {SphereMetricOptions=} opt_options Options for the + * length calculation. By default, geometries are assumed to be in 'EPSG:3857'. + * You can change this by providing a `projection` option. + * @return {number} The spherical length (in meters). + * @api + */ +function getLength(geometry, opt_options) { + var options = opt_options || {}; + var radius = options.radius || DEFAULT_RADIUS; + var projection = options.projection || 'EPSG:3857'; + var type = geometry.getType(); + if (type !== GeometryType.GEOMETRY_COLLECTION) { + geometry = geometry.clone().transform(projection, 'EPSG:4326'); + } + var length = 0; + var coordinates, coords, i, ii, j, jj; + switch (type) { + case GeometryType.POINT: + case GeometryType.MULTI_POINT: { + break; + } + case GeometryType.LINE_STRING: + case GeometryType.LINEAR_RING: { + coordinates = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometry).getCoordinates(); + length = getLengthInternal(coordinates, radius); + break; + } + case GeometryType.MULTI_LINE_STRING: + case GeometryType.POLYGON: { + coordinates = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometry).getCoordinates(); + for (i = 0, ii = coordinates.length; i < ii; ++i) { + length += getLengthInternal(coordinates[i], radius); + } + break; + } + case GeometryType.MULTI_POLYGON: { + coordinates = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometry).getCoordinates(); + for (i = 0, ii = coordinates.length; i < ii; ++i) { + coords = coordinates[i]; + for (j = 0, jj = coords.length; j < jj; ++j) { + length += getLengthInternal(coords[j], radius); + } + } + break; + } + case GeometryType.GEOMETRY_COLLECTION: { + var geometries = /** @type {import("./geom/GeometryCollection.js").default} */ (geometry).getGeometries(); + for (i = 0, ii = geometries.length; i < ii; ++i) { + length += getLength(geometries[i], opt_options); + } + break; + } + default: { + throw new Error('Unsupported geometry type: ' + type); + } + } + return length; +} + + +/** + * Returns the spherical area for a list of coordinates. + * + * [Reference](https://trs-new.jpl.nasa.gov/handle/2014/40409) + * Robert. G. Chamberlain and William H. Duquette, "Some Algorithms for + * Polygons on a Sphere", JPL Publication 07-03, Jet Propulsion + * Laboratory, Pasadena, CA, June 2007 + * + * @param {Array} coordinates List of coordinates of a linear + * ring. If the ring is oriented clockwise, the area will be positive, + * otherwise it will be negative. + * @param {number} radius The sphere radius. + * @return {number} Area (in square meters). + */ +function getAreaInternal(coordinates, radius) { + var area = 0; + var len = coordinates.length; + var x1 = coordinates[len - 1][0]; + var y1 = coordinates[len - 1][1]; + for (var i = 0; i < len; i++) { + var x2 = coordinates[i][0]; + var y2 = coordinates[i][1]; + area += toRadians(x2 - x1) * + (2 + Math.sin(toRadians(y1)) + + Math.sin(toRadians(y2))); + x1 = x2; + y1 = y2; + } + return area * radius * radius / 2.0; +} + + +/** + * Get the spherical area of a geometry. This is the area (in meters) assuming + * that polygon edges are segments of great circles on a sphere. + * @param {import("./geom/Geometry.js").default} geometry A geometry. + * @param {SphereMetricOptions=} opt_options Options for the area + * calculation. By default, geometries are assumed to be in 'EPSG:3857'. + * You can change this by providing a `projection` option. + * @return {number} The spherical area (in square meters). + * @api + */ +function sphere_getArea(geometry, opt_options) { + var options = opt_options || {}; + var radius = options.radius || DEFAULT_RADIUS; + var projection = options.projection || 'EPSG:3857'; + var type = geometry.getType(); + if (type !== GeometryType.GEOMETRY_COLLECTION) { + geometry = geometry.clone().transform(projection, 'EPSG:4326'); + } + var area = 0; + var coordinates, coords, i, ii, j, jj; + switch (type) { + case GeometryType.POINT: + case GeometryType.MULTI_POINT: + case GeometryType.LINE_STRING: + case GeometryType.MULTI_LINE_STRING: + case GeometryType.LINEAR_RING: { + break; + } + case GeometryType.POLYGON: { + coordinates = /** @type {import("./geom/Polygon.js").default} */ (geometry).getCoordinates(); + area = Math.abs(getAreaInternal(coordinates[0], radius)); + for (i = 1, ii = coordinates.length; i < ii; ++i) { + area -= Math.abs(getAreaInternal(coordinates[i], radius)); + } + break; + } + case GeometryType.MULTI_POLYGON: { + coordinates = /** @type {import("./geom/SimpleGeometry.js").default} */ (geometry).getCoordinates(); + for (i = 0, ii = coordinates.length; i < ii; ++i) { + coords = coordinates[i]; + area += Math.abs(getAreaInternal(coords[0], radius)); + for (j = 1, jj = coords.length; j < jj; ++j) { + area -= Math.abs(getAreaInternal(coords[j], radius)); + } + } + break; + } + case GeometryType.GEOMETRY_COLLECTION: { + var geometries = /** @type {import("./geom/GeometryCollection.js").default} */ (geometry).getGeometries(); + for (i = 0, ii = geometries.length; i < ii; ++i) { + area += sphere_getArea(geometries[i], opt_options); + } + break; + } + default: { + throw new Error('Unsupported geometry type: ' + type); + } + } + return area; +} + + +/** + * Returns the coordinate at the given distance and bearing from `c1`. + * + * @param {import("./coordinate.js").Coordinate} c1 The origin point (`[lon, lat]` in degrees). + * @param {number} distance The great-circle distance between the origin + * point and the target point. + * @param {number} bearing The bearing (in radians). + * @param {number=} opt_radius The sphere radius to use. Defaults to the Earth's + * mean radius using the WGS84 ellipsoid. + * @return {import("./coordinate.js").Coordinate} The target point. + */ +function sphere_offset(c1, distance, bearing, opt_radius) { + var radius = opt_radius || DEFAULT_RADIUS; + var lat1 = toRadians(c1[1]); + var lon1 = toRadians(c1[0]); + var dByR = distance / radius; + var lat = Math.asin( + Math.sin(lat1) * Math.cos(dByR) + + Math.cos(lat1) * Math.sin(dByR) * Math.cos(bearing)); + var lon = lon1 + Math.atan2( + Math.sin(bearing) * Math.sin(dByR) * Math.cos(lat1), + Math.cos(dByR) - Math.sin(lat1) * Math.sin(lat)); + return [toDegrees(lon), toDegrees(lat)]; +} + +//# sourceMappingURL=sphere.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/Units.js +/** + * @module ol/proj/Units + */ + +/** + * Projection units: `'degrees'`, `'ft'`, `'m'`, `'pixels'`, `'tile-pixels'` or + * `'us-ft'`. + * @enum {string} + */ +var Units = { + DEGREES: 'degrees', + FEET: 'ft', + METERS: 'm', + PIXELS: 'pixels', + TILE_PIXELS: 'tile-pixels', + USFEET: 'us-ft' +}; + + +/** + * Meters per unit lookup table. + * @const + * @type {Object} + * @api + */ +var METERS_PER_UNIT = {}; +// use the radius of the Normal sphere +METERS_PER_UNIT[Units.DEGREES] = 2 * Math.PI * 6370997 / 360; +METERS_PER_UNIT[Units.FEET] = 0.3048; +METERS_PER_UNIT[Units.METERS] = 1; +METERS_PER_UNIT[Units.USFEET] = 1200 / 3937; + +/* harmony default export */ var proj_Units = (Units); + +//# sourceMappingURL=Units.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/Projection.js +/** + * @module ol/proj/Projection + */ + + + +/** + * @typedef {Object} Options + * @property {string} code The SRS identifier code, e.g. `EPSG:4326`. + * @property {import("./Units.js").default|string} [units] Units. Required unless a + * proj4 projection is defined for `code`. + * @property {import("../extent.js").Extent} [extent] The validity extent for the SRS. + * @property {string} [axisOrientation='enu'] The axis orientation as specified in Proj4. + * @property {boolean} [global=false] Whether the projection is valid for the whole globe. + * @property {number} [metersPerUnit] The meters per unit for the SRS. + * If not provided, the `units` are used to get the meters per unit from the {@link module:ol/proj/Units~METERS_PER_UNIT} + * lookup table. + * @property {import("../extent.js").Extent} [worldExtent] The world extent for the SRS. + * @property {function(number, import("../coordinate.js").Coordinate):number} [getPointResolution] + * Function to determine resolution at a point. The function is called with a + * `{number}` view resolution and an `{import("../coordinate.js").Coordinate}` as arguments, and returns + * the `{number}` resolution at the passed coordinate. If this is `undefined`, + * the default {@link module:ol/proj#getPointResolution} function will be used. + */ + + +/** + * @classdesc + * Projection definition class. One of these is created for each projection + * supported in the application and stored in the {@link module:ol/proj} namespace. + * You can use these in applications, but this is not required, as API params + * and options use {@link module:ol/proj~ProjectionLike} which means the simple string + * code will suffice. + * + * You can use {@link module:ol/proj~get} to retrieve the object for a particular + * projection. + * + * The library includes definitions for `EPSG:4326` and `EPSG:3857`, together + * with the following aliases: + * * `EPSG:4326`: CRS:84, urn:ogc:def:crs:EPSG:6.6:4326, + * urn:ogc:def:crs:OGC:1.3:CRS84, urn:ogc:def:crs:OGC:2:84, + * http://www.opengis.net/gml/srs/epsg.xml#4326, + * urn:x-ogc:def:crs:EPSG:4326 + * * `EPSG:3857`: EPSG:102100, EPSG:102113, EPSG:900913, + * urn:ogc:def:crs:EPSG:6.18:3:3857, + * http://www.opengis.net/gml/srs/epsg.xml#3857 + * + * If you use [proj4js](https://github.com/proj4js/proj4js), aliases can + * be added using `proj4.defs()`. After all required projection definitions are + * added, call the {@link module:ol/proj/proj4~register} function. + * + * @api + */ +var Projection_Projection = function Projection(options) { + /** + * @private + * @type {string} + */ + this.code_ = options.code; + + /** + * Units of projected coordinates. When set to `TILE_PIXELS`, a + * `this.extent_` and `this.worldExtent_` must be configured properly for each + * tile. + * @private + * @type {import("./Units.js").default} + */ + this.units_ = /** @type {import("./Units.js").default} */ (options.units); + + /** + * Validity extent of the projection in projected coordinates. For projections + * with `TILE_PIXELS` units, this is the extent of the tile in + * tile pixel space. + * @private + * @type {import("../extent.js").Extent} + */ + this.extent_ = options.extent !== undefined ? options.extent : null; + + /** + * Extent of the world in EPSG:4326. For projections with + * `TILE_PIXELS` units, this is the extent of the tile in + * projected coordinate space. + * @private + * @type {import("../extent.js").Extent} + */ + this.worldExtent_ = options.worldExtent !== undefined ? + options.worldExtent : null; + + /** + * @private + * @type {string} + */ + this.axisOrientation_ = options.axisOrientation !== undefined ? + options.axisOrientation : 'enu'; + + /** + * @private + * @type {boolean} + */ + this.global_ = options.global !== undefined ? options.global : false; + + /** + * @private + * @type {boolean} + */ + this.canWrapX_ = !!(this.global_ && this.extent_); + + /** + * @private + * @type {function(number, import("../coordinate.js").Coordinate):number|undefined} + */ + this.getPointResolutionFunc_ = options.getPointResolution; + + /** + * @private + * @type {import("../tilegrid/TileGrid.js").default} + */ + this.defaultTileGrid_ = null; + + /** + * @private + * @type {number|undefined} + */ + this.metersPerUnit_ = options.metersPerUnit; +}; + +/** + * @return {boolean} The projection is suitable for wrapping the x-axis + */ +Projection_Projection.prototype.canWrapX = function canWrapX () { + return this.canWrapX_; +}; + +/** + * Get the code for this projection, e.g. 'EPSG:4326'. + * @return {string} Code. + * @api + */ +Projection_Projection.prototype.getCode = function getCode () { + return this.code_; +}; + +/** + * Get the validity extent for this projection. + * @return {import("../extent.js").Extent} Extent. + * @api + */ +Projection_Projection.prototype.getExtent = function getExtent () { + return this.extent_; +}; + +/** + * Get the units of this projection. + * @return {import("./Units.js").default} Units. + * @api + */ +Projection_Projection.prototype.getUnits = function getUnits () { + return this.units_; +}; + +/** + * Get the amount of meters per unit of this projection.If the projection is + * not configured with `metersPerUnit` or a units identifier, the return is + * `undefined`. + * @return {number|undefined} Meters. + * @api + */ +Projection_Projection.prototype.getMetersPerUnit = function getMetersPerUnit () { + return this.metersPerUnit_ || METERS_PER_UNIT[this.units_]; +}; + +/** + * Get the world extent for this projection. + * @return {import("../extent.js").Extent} Extent. + * @api + */ +Projection_Projection.prototype.getWorldExtent = function getWorldExtent () { + return this.worldExtent_; +}; + +/** + * Get the axis orientation of this projection. + * Example values are: + * enu - the default easting, northing, elevation. + * neu - northing, easting, up - useful for "lat/long" geographic coordinates, + * or south orientated transverse mercator. + * wnu - westing, northing, up - some planetary coordinate systems have + * "west positive" coordinate systems + * @return {string} Axis orientation. + * @api + */ +Projection_Projection.prototype.getAxisOrientation = function getAxisOrientation () { + return this.axisOrientation_; +}; + +/** + * Is this projection a global projection which spans the whole world? + * @return {boolean} Whether the projection is global. + * @api + */ +Projection_Projection.prototype.isGlobal = function isGlobal () { + return this.global_; +}; + +/** + * Set if the projection is a global projection which spans the whole world + * @param {boolean} global Whether the projection is global. + * @api + */ +Projection_Projection.prototype.setGlobal = function setGlobal (global) { + this.global_ = global; + this.canWrapX_ = !!(global && this.extent_); +}; + +/** + * @return {import("../tilegrid/TileGrid.js").default} The default tile grid. + */ +Projection_Projection.prototype.getDefaultTileGrid = function getDefaultTileGrid () { + return this.defaultTileGrid_; +}; + +/** + * @param {import("../tilegrid/TileGrid.js").default} tileGrid The default tile grid. + */ +Projection_Projection.prototype.setDefaultTileGrid = function setDefaultTileGrid (tileGrid) { + this.defaultTileGrid_ = tileGrid; +}; + +/** + * Set the validity extent for this projection. + * @param {import("../extent.js").Extent} extent Extent. + * @api + */ +Projection_Projection.prototype.setExtent = function setExtent (extent) { + this.extent_ = extent; + this.canWrapX_ = !!(this.global_ && extent); +}; + +/** + * Set the world extent for this projection. + * @param {import("../extent.js").Extent} worldExtent World extent + * [minlon, minlat, maxlon, maxlat]. + * @api + */ +Projection_Projection.prototype.setWorldExtent = function setWorldExtent (worldExtent) { + this.worldExtent_ = worldExtent; +}; + +/** + * Set the getPointResolution function (see {@link module:ol/proj~getPointResolution} + * for this projection. + * @param {function(number, import("../coordinate.js").Coordinate):number} func Function + * @api + */ +Projection_Projection.prototype.setGetPointResolution = function setGetPointResolution (func) { + this.getPointResolutionFunc_ = func; +}; + +/** + * Get the custom point resolution function for this projection (if set). + * @return {function(number, import("../coordinate.js").Coordinate):number|undefined} The custom point + * resolution function (if set). + */ +Projection_Projection.prototype.getPointResolutionFunc = function getPointResolutionFunc () { + return this.getPointResolutionFunc_; +}; + +/* harmony default export */ var proj_Projection = (Projection_Projection); + +//# sourceMappingURL=Projection.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/epsg3857.js +/** + * @module ol/proj/epsg3857 + */ + + + + + +/** + * Radius of WGS84 sphere + * + * @const + * @type {number} + */ +var RADIUS = 6378137; + + +/** + * @const + * @type {number} + */ +var HALF_SIZE = Math.PI * RADIUS; + + +/** + * @const + * @type {import("../extent.js").Extent} + */ +var EXTENT = [ + -HALF_SIZE, -HALF_SIZE, + HALF_SIZE, HALF_SIZE +]; + + +/** + * @const + * @type {import("../extent.js").Extent} + */ +var WORLD_EXTENT = [-180, -85, 180, 85]; + + +/** + * @classdesc + * Projection object for web/spherical Mercator (EPSG:3857). + */ +var epsg3857_EPSG3857Projection = /*@__PURE__*/(function (Projection) { + function EPSG3857Projection(code) { + Projection.call(this, { + code: code, + units: proj_Units.METERS, + extent: EXTENT, + global: true, + worldExtent: WORLD_EXTENT, + getPointResolution: function(resolution, point) { + return resolution / cosh(point[1] / RADIUS); + } + }); + + } + + if ( Projection ) EPSG3857Projection.__proto__ = Projection; + EPSG3857Projection.prototype = Object.create( Projection && Projection.prototype ); + EPSG3857Projection.prototype.constructor = EPSG3857Projection; + + return EPSG3857Projection; +}(proj_Projection)); + + +/** + * Projections equal to EPSG:3857. + * + * @const + * @type {Array} + */ +var PROJECTIONS = [ + new epsg3857_EPSG3857Projection('EPSG:3857'), + new epsg3857_EPSG3857Projection('EPSG:102100'), + new epsg3857_EPSG3857Projection('EPSG:102113'), + new epsg3857_EPSG3857Projection('EPSG:900913'), + new epsg3857_EPSG3857Projection('urn:ogc:def:crs:EPSG:6.18:3:3857'), + new epsg3857_EPSG3857Projection('urn:ogc:def:crs:EPSG::3857'), + new epsg3857_EPSG3857Projection('http://www.opengis.net/gml/srs/epsg.xml#3857') +]; + + +/** + * Transformation from EPSG:4326 to EPSG:3857. + * + * @param {Array} input Input array of coordinate values. + * @param {Array=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is `2`). + * @return {Array} Output array of coordinate values. + */ +function fromEPSG4326(input, opt_output, opt_dimension) { + var length = input.length; + var dimension = opt_dimension > 1 ? opt_dimension : 2; + var output = opt_output; + if (output === undefined) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + } + var halfSize = HALF_SIZE; + for (var i = 0; i < length; i += dimension) { + output[i] = halfSize * input[i] / 180; + var y = RADIUS * + Math.log(Math.tan(Math.PI * (input[i + 1] + 90) / 360)); + if (y > halfSize) { + y = halfSize; + } else if (y < -halfSize) { + y = -halfSize; + } + output[i + 1] = y; + } + return output; +} + + +/** + * Transformation from EPSG:3857 to EPSG:4326. + * + * @param {Array} input Input array of coordinate values. + * @param {Array=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension (default is `2`). + * @return {Array} Output array of coordinate values. + */ +function epsg3857_toEPSG4326(input, opt_output, opt_dimension) { + var length = input.length; + var dimension = opt_dimension > 1 ? opt_dimension : 2; + var output = opt_output; + if (output === undefined) { + if (dimension > 2) { + // preserve values beyond second dimension + output = input.slice(); + } else { + output = new Array(length); + } + } + for (var i = 0; i < length; i += dimension) { + output[i] = 180 * input[i] / HALF_SIZE; + output[i + 1] = 360 * Math.atan( + Math.exp(input[i + 1] / RADIUS)) / Math.PI - 90; + } + return output; +} + +//# sourceMappingURL=epsg3857.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/epsg4326.js +/** + * @module ol/proj/epsg4326 + */ + + + + +/** + * Semi-major radius of the WGS84 ellipsoid. + * + * @const + * @type {number} + */ +var epsg4326_RADIUS = 6378137; + + +/** + * Extent of the EPSG:4326 projection which is the whole world. + * + * @const + * @type {import("../extent.js").Extent} + */ +var epsg4326_EXTENT = [-180, -90, 180, 90]; + + +/** + * @const + * @type {number} + */ +var epsg4326_METERS_PER_UNIT = Math.PI * epsg4326_RADIUS / 180; + + +/** + * @classdesc + * Projection object for WGS84 geographic coordinates (EPSG:4326). + * + * Note that OpenLayers does not strictly comply with the EPSG definition. + * The EPSG registry defines 4326 as a CRS for Latitude,Longitude (y,x). + * OpenLayers treats EPSG:4326 as a pseudo-projection, with x,y coordinates. + */ +var epsg4326_EPSG4326Projection = /*@__PURE__*/(function (Projection) { + function EPSG4326Projection(code, opt_axisOrientation) { + Projection.call(this, { + code: code, + units: proj_Units.DEGREES, + extent: epsg4326_EXTENT, + axisOrientation: opt_axisOrientation, + global: true, + metersPerUnit: epsg4326_METERS_PER_UNIT, + worldExtent: epsg4326_EXTENT + }); + + } + + if ( Projection ) EPSG4326Projection.__proto__ = Projection; + EPSG4326Projection.prototype = Object.create( Projection && Projection.prototype ); + EPSG4326Projection.prototype.constructor = EPSG4326Projection; + + return EPSG4326Projection; +}(proj_Projection)); + + +/** + * Projections equal to EPSG:4326. + * + * @const + * @type {Array} + */ +var epsg4326_PROJECTIONS = [ + new epsg4326_EPSG4326Projection('CRS:84'), + new epsg4326_EPSG4326Projection('EPSG:4326', 'neu'), + new epsg4326_EPSG4326Projection('urn:ogc:def:crs:EPSG::4326', 'neu'), + new epsg4326_EPSG4326Projection('urn:ogc:def:crs:EPSG:6.6:4326', 'neu'), + new epsg4326_EPSG4326Projection('urn:ogc:def:crs:OGC:1.3:CRS84'), + new epsg4326_EPSG4326Projection('urn:ogc:def:crs:OGC:2:84'), + new epsg4326_EPSG4326Projection('http://www.opengis.net/gml/srs/epsg.xml#4326', 'neu'), + new epsg4326_EPSG4326Projection('urn:x-ogc:def:crs:EPSG:4326', 'neu') +]; + +//# sourceMappingURL=epsg4326.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/projections.js +/** + * @module ol/proj/projections + */ + + +/** + * @type {Object} + */ +var projections_cache = {}; + + +/** + * Clear the projections cache. + */ +function projections_clear() { + projections_cache = {}; +} + + +/** + * Get a cached projection by code. + * @param {string} code The code for the projection. + * @return {import("./Projection.js").default} The projection (if cached). + */ +function projections_get(code) { + return projections_cache[code] || null; +} + + +/** + * Add a projection to the cache. + * @param {string} code The projection code. + * @param {import("./Projection.js").default} projection The projection to cache. + */ +function projections_add(code, projection) { + projections_cache[code] = projection; +} + +//# sourceMappingURL=projections.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj/transforms.js +/** + * @module ol/proj/transforms + */ + + + +/** + * @private + * @type {!Object>} + */ +var transforms = {}; + + +/** + * Clear the transform cache. + */ +function transforms_clear() { + transforms = {}; +} + + +/** + * Registers a conversion function to convert coordinates from the source + * projection to the destination projection. + * + * @param {import("./Projection.js").default} source Source. + * @param {import("./Projection.js").default} destination Destination. + * @param {import("../proj.js").TransformFunction} transformFn Transform. + */ +function transforms_add(source, destination, transformFn) { + var sourceCode = source.getCode(); + var destinationCode = destination.getCode(); + if (!(sourceCode in transforms)) { + transforms[sourceCode] = {}; + } + transforms[sourceCode][destinationCode] = transformFn; +} + + +/** + * Unregisters the conversion function to convert coordinates from the source + * projection to the destination projection. This method is used to clean up + * cached transforms during testing. + * + * @param {import("./Projection.js").default} source Source projection. + * @param {import("./Projection.js").default} destination Destination projection. + * @return {import("../proj.js").TransformFunction} transformFn The unregistered transform. + */ +function transforms_remove(source, destination) { + var sourceCode = source.getCode(); + var destinationCode = destination.getCode(); + var transform = transforms[sourceCode][destinationCode]; + delete transforms[sourceCode][destinationCode]; + if (obj_isEmpty(transforms[sourceCode])) { + delete transforms[sourceCode]; + } + return transform; +} + + +/** + * Get a transform given a source code and a destination code. + * @param {string} sourceCode The code for the source projection. + * @param {string} destinationCode The code for the destination projection. + * @return {import("../proj.js").TransformFunction|undefined} The transform function (if found). + */ +function transforms_get(sourceCode, destinationCode) { + var transform; + if (sourceCode in transforms && destinationCode in transforms[sourceCode]) { + transform = transforms[sourceCode][destinationCode]; + } + return transform; +} + +//# sourceMappingURL=transforms.js.map +// CONCATENATED MODULE: ./node_modules/ol/proj.js +/** + * @module ol/proj + */ + +/** + * The ol/proj module stores: + * * a list of {@link module:ol/proj/Projection} + * objects, one for each projection supported by the application + * * a list of transform functions needed to convert coordinates in one projection + * into another. + * + * The static functions are the methods used to maintain these. + * Each transform function can handle not only simple coordinate pairs, but also + * large arrays of coordinates such as vector geometries. + * + * When loaded, the library adds projection objects for EPSG:4326 (WGS84 + * geographic coordinates) and EPSG:3857 (Web or Spherical Mercator, as used + * for example by Bing Maps or OpenStreetMap), together with the relevant + * transform functions. + * + * Additional transforms may be added by using the http://proj4js.org/ + * library (version 2.2 or later). You can use the full build supplied by + * Proj4js, or create a custom build to support those projections you need; see + * the Proj4js website for how to do this. You also need the Proj4js definitions + * for the required projections. These definitions can be obtained from + * https://epsg.io/, and are a JS function, so can be loaded in a script + * tag (as in the examples) or pasted into your application. + * + * After all required projection definitions are added to proj4's registry (by + * using `proj4.defs()`), simply call `register(proj4)` from the `ol/proj/proj4` + * package. Existing transforms are not changed by this function. See + * examples/wms-image-custom-proj for an example of this. + * + * Additional projection definitions can be registered with `proj4.defs()` any + * time. Just make sure to call `register(proj4)` again; for example, with user-supplied data where you don't + * know in advance what projections are needed, you can initially load minimal + * support and then load whichever are requested. + * + * Note that Proj4js does not support projection extents. If you want to add + * one for creating default tile grids, you can add it after the Projection + * object has been created with `setExtent`, for example, + * `get('EPSG:1234').setExtent(extent)`. + * + * In addition to Proj4js support, any transform functions can be added with + * {@link module:ol/proj~addCoordinateTransforms}. To use this, you must first create + * a {@link module:ol/proj/Projection} object for the new projection and add it with + * {@link module:ol/proj~addProjection}. You can then add the forward and inverse + * functions with {@link module:ol/proj~addCoordinateTransforms}. See + * examples/wms-custom-proj for an example of this. + * + * Note that if no transforms are needed and you only need to define the + * projection, just add a {@link module:ol/proj/Projection} with + * {@link module:ol/proj~addProjection}. See examples/wms-no-proj for an example of + * this. + */ + + + + + + + + + + + +/** + * A projection as {@link module:ol/proj/Projection}, SRS identifier + * string or undefined. + * @typedef {Projection|string|undefined} ProjectionLike + * @api + */ + + +/** + * A transform function accepts an array of input coordinate values, an optional + * output array, and an optional dimension (default should be 2). The function + * transforms the input coordinate values, populates the output array, and + * returns the output array. + * + * @typedef {function(Array, Array=, number=): Array} TransformFunction + * @api + */ + + + + + + +/** + * @param {Array} input Input coordinate array. + * @param {Array=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension. + * @return {Array} Output coordinate array (new array, same coordinate + * values). + */ +function cloneTransform(input, opt_output, opt_dimension) { + var output; + if (opt_output !== undefined) { + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + output = opt_output; + } else { + output = input.slice(); + } + return output; +} + + +/** + * @param {Array} input Input coordinate array. + * @param {Array=} opt_output Output array of coordinate values. + * @param {number=} opt_dimension Dimension. + * @return {Array} Input coordinate array (same array as input). + */ +function identityTransform(input, opt_output, opt_dimension) { + if (opt_output !== undefined && input !== opt_output) { + for (var i = 0, ii = input.length; i < ii; ++i) { + opt_output[i] = input[i]; + } + input = opt_output; + } + return input; +} + + +/** + * Add a Projection object to the list of supported projections that can be + * looked up by their code. + * + * @param {Projection} projection Projection instance. + * @api + */ +function addProjection(projection) { + projections_add(projection.getCode(), projection); + transforms_add(projection, projection, cloneTransform); +} + + +/** + * @param {Array} projections Projections. + */ +function addProjections(projections) { + projections.forEach(addProjection); +} + + +/** + * Fetches a Projection object for the code specified. + * + * @param {ProjectionLike} projectionLike Either a code string which is + * a combination of authority and identifier such as "EPSG:4326", or an + * existing projection object, or undefined. + * @return {Projection} Projection object, or null if not in list. + * @api + */ +function proj_get(projectionLike) { + return typeof projectionLike === 'string' ? + projections_get(/** @type {string} */ (projectionLike)) : + (/** @type {Projection} */ (projectionLike) || null); +} + + +/** + * Get the resolution of the point in degrees or distance units. + * For projections with degrees as the unit this will simply return the + * provided resolution. For other projections the point resolution is + * by default estimated by transforming the 'point' pixel to EPSG:4326, + * measuring its width and height on the normal sphere, + * and taking the average of the width and height. + * A custom function can be provided for a specific projection, either + * by setting the `getPointResolution` option in the + * {@link module:ol/proj/Projection~Projection} constructor or by using + * {@link module:ol/proj/Projection~Projection#setGetPointResolution} to change an existing + * projection object. + * @param {ProjectionLike} projection The projection. + * @param {number} resolution Nominal resolution in projection units. + * @param {import("./coordinate.js").Coordinate} point Point to find adjusted resolution at. + * @param {Units=} opt_units Units to get the point resolution in. + * Default is the projection's units. + * @return {number} Point resolution. + * @api + */ +function getPointResolution(projection, resolution, point, opt_units) { + projection = proj_get(projection); + var pointResolution; + var getter = projection.getPointResolutionFunc(); + if (getter) { + pointResolution = getter(resolution, point); + } else { + var units = projection.getUnits(); + if (units == proj_Units.DEGREES && !opt_units || opt_units == proj_Units.DEGREES) { + pointResolution = resolution; + } else { + // Estimate point resolution by transforming the center pixel to EPSG:4326, + // measuring its width and height on the normal sphere, and taking the + // average of the width and height. + var toEPSG4326 = getTransformFromProjections(projection, proj_get('EPSG:4326')); + var vertices = [ + point[0] - resolution / 2, point[1], + point[0] + resolution / 2, point[1], + point[0], point[1] - resolution / 2, + point[0], point[1] + resolution / 2 + ]; + vertices = toEPSG4326(vertices, vertices, 2); + var width = getDistance(vertices.slice(0, 2), vertices.slice(2, 4)); + var height = getDistance(vertices.slice(4, 6), vertices.slice(6, 8)); + pointResolution = (width + height) / 2; + var metersPerUnit = opt_units ? + METERS_PER_UNIT[opt_units] : + projection.getMetersPerUnit(); + if (metersPerUnit !== undefined) { + pointResolution /= metersPerUnit; + } + } + } + return pointResolution; +} + + +/** + * Registers transformation functions that don't alter coordinates. Those allow + * to transform between projections with equal meaning. + * + * @param {Array} projections Projections. + * @api + */ +function addEquivalentProjections(projections) { + addProjections(projections); + projections.forEach(function(source) { + projections.forEach(function(destination) { + if (source !== destination) { + transforms_add(source, destination, cloneTransform); + } + }); + }); +} + + +/** + * Registers transformation functions to convert coordinates in any projection + * in projection1 to any projection in projection2. + * + * @param {Array} projections1 Projections with equal + * meaning. + * @param {Array} projections2 Projections with equal + * meaning. + * @param {TransformFunction} forwardTransform Transformation from any + * projection in projection1 to any projection in projection2. + * @param {TransformFunction} inverseTransform Transform from any projection + * in projection2 to any projection in projection1.. + */ +function addEquivalentTransforms(projections1, projections2, forwardTransform, inverseTransform) { + projections1.forEach(function(projection1) { + projections2.forEach(function(projection2) { + transforms_add(projection1, projection2, forwardTransform); + transforms_add(projection2, projection1, inverseTransform); + }); + }); +} + + +/** + * Clear all cached projections and transforms. + */ +function clearAllProjections() { + projections_clear(); + transforms_clear(); +} + + +/** + * @param {Projection|string|undefined} projection Projection. + * @param {string} defaultCode Default code. + * @return {Projection} Projection. + */ +function createProjection(projection, defaultCode) { + if (!projection) { + return proj_get(defaultCode); + } else if (typeof projection === 'string') { + return proj_get(projection); + } else { + return ( + /** @type {Projection} */ (projection) + ); + } +} + + +/** + * Creates a {@link module:ol/proj~TransformFunction} from a simple 2D coordinate transform + * function. + * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} coordTransform Coordinate + * transform. + * @return {TransformFunction} Transform function. + */ +function createTransformFromCoordinateTransform(coordTransform) { + return ( + /** + * @param {Array} input Input. + * @param {Array=} opt_output Output. + * @param {number=} opt_dimension Dimension. + * @return {Array} Output. + */ + function(input, opt_output, opt_dimension) { + var length = input.length; + var dimension = opt_dimension !== undefined ? opt_dimension : 2; + var output = opt_output !== undefined ? opt_output : new Array(length); + for (var i = 0; i < length; i += dimension) { + var point = coordTransform([input[i], input[i + 1]]); + output[i] = point[0]; + output[i + 1] = point[1]; + for (var j = dimension - 1; j >= 2; --j) { + output[i + j] = input[i + j]; + } + } + return output; + }); +} + + +/** + * Registers coordinate transform functions to convert coordinates between the + * source projection and the destination projection. + * The forward and inverse functions convert coordinate pairs; this function + * converts these into the functions used internally which also handle + * extents and coordinate arrays. + * + * @param {ProjectionLike} source Source projection. + * @param {ProjectionLike} destination Destination projection. + * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} forward The forward transform + * function (that is, from the source projection to the destination + * projection) that takes a {@link module:ol/coordinate~Coordinate} as argument and returns + * the transformed {@link module:ol/coordinate~Coordinate}. + * @param {function(import("./coordinate.js").Coordinate): import("./coordinate.js").Coordinate} inverse The inverse transform + * function (that is, from the destination projection to the source + * projection) that takes a {@link module:ol/coordinate~Coordinate} as argument and returns + * the transformed {@link module:ol/coordinate~Coordinate}. + * @api + */ +function addCoordinateTransforms(source, destination, forward, inverse) { + var sourceProj = proj_get(source); + var destProj = proj_get(destination); + transforms_add(sourceProj, destProj, createTransformFromCoordinateTransform(forward)); + transforms_add(destProj, sourceProj, createTransformFromCoordinateTransform(inverse)); +} + + +/** + * Transforms a coordinate from longitude/latitude to a different projection. + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate as longitude and latitude, i.e. + * an array with longitude as 1st and latitude as 2nd element. + * @param {ProjectionLike=} opt_projection Target projection. The + * default is Web Mercator, i.e. 'EPSG:3857'. + * @return {import("./coordinate.js").Coordinate} Coordinate projected to the target projection. + * @api + */ +function fromLonLat(coordinate, opt_projection) { + return proj_transform(coordinate, 'EPSG:4326', + opt_projection !== undefined ? opt_projection : 'EPSG:3857'); +} + + +/** + * Transforms a coordinate to longitude/latitude. + * @param {import("./coordinate.js").Coordinate} coordinate Projected coordinate. + * @param {ProjectionLike=} opt_projection Projection of the coordinate. + * The default is Web Mercator, i.e. 'EPSG:3857'. + * @return {import("./coordinate.js").Coordinate} Coordinate as longitude and latitude, i.e. an array + * with longitude as 1st and latitude as 2nd element. + * @api + */ +function toLonLat(coordinate, opt_projection) { + var lonLat = proj_transform(coordinate, + opt_projection !== undefined ? opt_projection : 'EPSG:3857', 'EPSG:4326'); + var lon = lonLat[0]; + if (lon < -180 || lon > 180) { + lonLat[0] = modulo(lon + 180, 360) - 180; + } + return lonLat; +} + + +/** + * Checks if two projections are the same, that is every coordinate in one + * projection does represent the same geographic point as the same coordinate in + * the other projection. + * + * @param {Projection} projection1 Projection 1. + * @param {Projection} projection2 Projection 2. + * @return {boolean} Equivalent. + * @api + */ +function equivalent(projection1, projection2) { + if (projection1 === projection2) { + return true; + } + var equalUnits = projection1.getUnits() === projection2.getUnits(); + if (projection1.getCode() === projection2.getCode()) { + return equalUnits; + } else { + var transformFunc = getTransformFromProjections(projection1, projection2); + return transformFunc === cloneTransform && equalUnits; + } +} + + +/** + * Searches in the list of transform functions for the function for converting + * coordinates from the source projection to the destination projection. + * + * @param {Projection} sourceProjection Source Projection object. + * @param {Projection} destinationProjection Destination Projection + * object. + * @return {TransformFunction} Transform function. + */ +function getTransformFromProjections(sourceProjection, destinationProjection) { + var sourceCode = sourceProjection.getCode(); + var destinationCode = destinationProjection.getCode(); + var transformFunc = transforms_get(sourceCode, destinationCode); + if (!transformFunc) { + transformFunc = identityTransform; + } + return transformFunc; +} + + +/** + * Given the projection-like objects, searches for a transformation + * function to convert a coordinates array from the source projection to the + * destination projection. + * + * @param {ProjectionLike} source Source. + * @param {ProjectionLike} destination Destination. + * @return {TransformFunction} Transform function. + * @api + */ +function proj_getTransform(source, destination) { + var sourceProjection = proj_get(source); + var destinationProjection = proj_get(destination); + return getTransformFromProjections(sourceProjection, destinationProjection); +} + + +/** + * Transforms a coordinate from source projection to destination projection. + * This returns a new coordinate (and does not modify the original). + * + * See {@link module:ol/proj~transformExtent} for extent transformation. + * See the transform method of {@link module:ol/geom/Geometry~Geometry} and its + * subclasses for geometry transforms. + * + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate. + * @param {ProjectionLike} source Source projection-like. + * @param {ProjectionLike} destination Destination projection-like. + * @return {import("./coordinate.js").Coordinate} Coordinate. + * @api + */ +function proj_transform(coordinate, source, destination) { + var transformFunc = proj_getTransform(source, destination); + return transformFunc(coordinate, undefined, coordinate.length); +} + + +/** + * Transforms an extent from source projection to destination projection. This + * returns a new extent (and does not modify the original). + * + * @param {import("./extent.js").Extent} extent The extent to transform. + * @param {ProjectionLike} source Source projection-like. + * @param {ProjectionLike} destination Destination projection-like. + * @return {import("./extent.js").Extent} The transformed extent. + * @api + */ +function transformExtent(extent, source, destination) { + var transformFunc = proj_getTransform(source, destination); + return extent_applyTransform(extent, transformFunc); +} + + +/** + * Transforms the given point to the destination projection. + * + * @param {import("./coordinate.js").Coordinate} point Point. + * @param {Projection} sourceProjection Source projection. + * @param {Projection} destinationProjection Destination projection. + * @return {import("./coordinate.js").Coordinate} Point. + */ +function transformWithProjections(point, sourceProjection, destinationProjection) { + var transformFunc = getTransformFromProjections(sourceProjection, destinationProjection); + return transformFunc(point); +} + +/** + * Add transforms to and from EPSG:4326 and EPSG:3857. This function is called + * by when this module is executed and should only need to be called again after + * `clearAllProjections()` is called (e.g. in tests). + */ +function addCommon() { + // Add transformations that don't alter coordinates to convert within set of + // projections with equal meaning. + addEquivalentProjections(PROJECTIONS); + addEquivalentProjections(epsg4326_PROJECTIONS); + // Add transformations to convert EPSG:4326 like coordinates to EPSG:3857 like + // coordinates and back. + addEquivalentTransforms(epsg4326_PROJECTIONS, PROJECTIONS, fromEPSG4326, epsg3857_toEPSG4326); +} + +addCommon(); + +//# sourceMappingURL=proj.js.map +// CONCATENATED MODULE: ./node_modules/ol/transform.js +/** + * @module ol/transform + */ + + + +/** + * An array representing an affine 2d transformation for use with + * {@link module:ol/transform} functions. The array has 6 elements. + * @typedef {!Array} Transform + */ + + +/** + * Collection of affine 2d transformation functions. The functions work on an + * array of 6 elements. The element order is compatible with the [SVGMatrix + * interface](https://developer.mozilla.org/en-US/docs/Web/API/SVGMatrix) and is + * a subset (elements a to f) of a 3×3 matrix: + * ``` + * [ a c e ] + * [ b d f ] + * [ 0 0 1 ] + * ``` + */ + + +/** + * @private + * @type {Transform} + */ +var tmp_ = new Array(6); + + +/** + * Create an identity transform. + * @return {!Transform} Identity transform. + */ +function create() { + return [1, 0, 0, 1, 0, 0]; +} + + +/** + * Resets the given transform to an identity transform. + * @param {!Transform} transform Transform. + * @return {!Transform} Transform. + */ +function transform_reset(transform) { + return transform_set(transform, 1, 0, 0, 1, 0, 0); +} + + +/** + * Multiply the underlying matrices of two transforms and return the result in + * the first transform. + * @param {!Transform} transform1 Transform parameters of matrix 1. + * @param {!Transform} transform2 Transform parameters of matrix 2. + * @return {!Transform} transform1 multiplied with transform2. + */ +function multiply(transform1, transform2) { + var a1 = transform1[0]; + var b1 = transform1[1]; + var c1 = transform1[2]; + var d1 = transform1[3]; + var e1 = transform1[4]; + var f1 = transform1[5]; + var a2 = transform2[0]; + var b2 = transform2[1]; + var c2 = transform2[2]; + var d2 = transform2[3]; + var e2 = transform2[4]; + var f2 = transform2[5]; + + transform1[0] = a1 * a2 + c1 * b2; + transform1[1] = b1 * a2 + d1 * b2; + transform1[2] = a1 * c2 + c1 * d2; + transform1[3] = b1 * c2 + d1 * d2; + transform1[4] = a1 * e2 + c1 * f2 + e1; + transform1[5] = b1 * e2 + d1 * f2 + f1; + + return transform1; +} + +/** + * Set the transform components a-f on a given transform. + * @param {!Transform} transform Transform. + * @param {number} a The a component of the transform. + * @param {number} b The b component of the transform. + * @param {number} c The c component of the transform. + * @param {number} d The d component of the transform. + * @param {number} e The e component of the transform. + * @param {number} f The f component of the transform. + * @return {!Transform} Matrix with transform applied. + */ +function transform_set(transform, a, b, c, d, e, f) { + transform[0] = a; + transform[1] = b; + transform[2] = c; + transform[3] = d; + transform[4] = e; + transform[5] = f; + return transform; +} + + +/** + * Set transform on one matrix from another matrix. + * @param {!Transform} transform1 Matrix to set transform to. + * @param {!Transform} transform2 Matrix to set transform from. + * @return {!Transform} transform1 with transform from transform2 applied. + */ +function setFromArray(transform1, transform2) { + transform1[0] = transform2[0]; + transform1[1] = transform2[1]; + transform1[2] = transform2[2]; + transform1[3] = transform2[3]; + transform1[4] = transform2[4]; + transform1[5] = transform2[5]; + return transform1; +} + + +/** + * Transforms the given coordinate with the given transform returning the + * resulting, transformed coordinate. The coordinate will be modified in-place. + * + * @param {Transform} transform The transformation. + * @param {import("./coordinate.js").Coordinate|import("./pixel.js").Pixel} coordinate The coordinate to transform. + * @return {import("./coordinate.js").Coordinate|import("./pixel.js").Pixel} return coordinate so that operations can be + * chained together. + */ +function apply(transform, coordinate) { + var x = coordinate[0]; + var y = coordinate[1]; + coordinate[0] = transform[0] * x + transform[2] * y + transform[4]; + coordinate[1] = transform[1] * x + transform[3] * y + transform[5]; + return coordinate; +} + + +/** + * Applies rotation to the given transform. + * @param {!Transform} transform Transform. + * @param {number} angle Angle in radians. + * @return {!Transform} The rotated transform. + */ +function ol_transform_rotate(transform, angle) { + var cos = Math.cos(angle); + var sin = Math.sin(angle); + return multiply(transform, transform_set(tmp_, cos, sin, -sin, cos, 0, 0)); +} + + +/** + * Applies scale to a given transform. + * @param {!Transform} transform Transform. + * @param {number} x Scale factor x. + * @param {number} y Scale factor y. + * @return {!Transform} The scaled transform. + */ +function ol_transform_scale(transform, x, y) { + return multiply(transform, transform_set(tmp_, x, 0, 0, y, 0, 0)); +} + + +/** + * Applies translation to the given transform. + * @param {!Transform} transform Transform. + * @param {number} dx Translation x. + * @param {number} dy Translation y. + * @return {!Transform} The translated transform. + */ +function ol_transform_translate(transform, dx, dy) { + return multiply(transform, transform_set(tmp_, 1, 0, 0, 1, dx, dy)); +} + + +/** + * Creates a composite transform given an initial translation, scale, rotation, and + * final translation (in that order only, not commutative). + * @param {!Transform} transform The transform (will be modified in place). + * @param {number} dx1 Initial translation x. + * @param {number} dy1 Initial translation y. + * @param {number} sx Scale factor x. + * @param {number} sy Scale factor y. + * @param {number} angle Rotation (in counter-clockwise radians). + * @param {number} dx2 Final translation x. + * @param {number} dy2 Final translation y. + * @return {!Transform} The composite transform. + */ +function transform_compose(transform, dx1, dy1, sx, sy, angle, dx2, dy2) { + var sin = Math.sin(angle); + var cos = Math.cos(angle); + transform[0] = sx * cos; + transform[1] = sy * sin; + transform[2] = -sx * sin; + transform[3] = sy * cos; + transform[4] = dx2 * sx * cos - dy2 * sx * sin + dx1; + transform[5] = dx2 * sy * sin + dy2 * sy * cos + dy1; + return transform; +} + + +/** + * Invert the given transform. + * @param {!Transform} transform Transform. + * @return {!Transform} Inverse of the transform. + */ +function invert(transform) { + var det = determinant(transform); + assert(det !== 0, 32); // Transformation matrix cannot be inverted + + var a = transform[0]; + var b = transform[1]; + var c = transform[2]; + var d = transform[3]; + var e = transform[4]; + var f = transform[5]; + + transform[0] = d / det; + transform[1] = -b / det; + transform[2] = -c / det; + transform[3] = a / det; + transform[4] = (c * f - d * e) / det; + transform[5] = -(a * f - b * e) / det; + + return transform; +} + + +/** + * Returns the determinant of the given matrix. + * @param {!Transform} mat Matrix. + * @return {number} Determinant. + */ +function determinant(mat) { + return mat[0] * mat[3] - mat[1] * mat[2]; +} + +//# sourceMappingURL=transform.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/Geometry.js +/** + * @module ol/geom/Geometry + */ + + + + + + + + + +/** + * @type {import("../transform.js").Transform} + */ +var tmpTransform = create(); + + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * Base class for vector geometries. + * + * To get notified of changes to the geometry, register a listener for the + * generic `change` event on your geometry instance. + * + * @abstract + * @api + */ +var Geometry_Geometry = /*@__PURE__*/(function (BaseObject) { + function Geometry() { + + BaseObject.call(this); + + /** + * @private + * @type {import("../extent.js").Extent} + */ + this.extent_ = createEmpty(); + + /** + * @private + * @type {number} + */ + this.extentRevision_ = -1; + + /** + * @protected + * @type {Object} + */ + this.simplifiedGeometryCache = {}; + + /** + * @protected + * @type {number} + */ + this.simplifiedGeometryMaxMinSquaredTolerance = 0; + + /** + * @protected + * @type {number} + */ + this.simplifiedGeometryRevision = 0; + + } + + if ( BaseObject ) Geometry.__proto__ = BaseObject; + Geometry.prototype = Object.create( BaseObject && BaseObject.prototype ); + Geometry.prototype.constructor = Geometry; + + /** + * Make a complete copy of the geometry. + * @abstract + * @return {!Geometry} Clone. + */ + Geometry.prototype.clone = function clone () { + return util_abstract(); + }; + + /** + * @abstract + * @param {number} x X. + * @param {number} y Y. + * @param {import("../coordinate.js").Coordinate} closestPoint Closest point. + * @param {number} minSquaredDistance Minimum squared distance. + * @return {number} Minimum squared distance. + */ + Geometry.prototype.closestPointXY = function closestPointXY (x, y, closestPoint, minSquaredDistance) { + return util_abstract(); + }; + + /** + * @param {number} x X. + * @param {number} y Y. + * @return {boolean} Contains (x, y). + */ + Geometry.prototype.containsXY = function containsXY (x, y) { + return false; + }; + + /** + * Return the closest point of the geometry to the passed point as + * {@link module:ol/coordinate~Coordinate coordinate}. + * @param {import("../coordinate.js").Coordinate} point Point. + * @param {import("../coordinate.js").Coordinate=} opt_closestPoint Closest point. + * @return {import("../coordinate.js").Coordinate} Closest point. + * @api + */ + Geometry.prototype.getClosestPoint = function getClosestPoint (point, opt_closestPoint) { + var closestPoint = opt_closestPoint ? opt_closestPoint : [NaN, NaN]; + this.closestPointXY(point[0], point[1], closestPoint, Infinity); + return closestPoint; + }; + + /** + * Returns true if this geometry includes the specified coordinate. If the + * coordinate is on the boundary of the geometry, returns false. + * @param {import("../coordinate.js").Coordinate} coordinate Coordinate. + * @return {boolean} Contains coordinate. + * @api + */ + Geometry.prototype.intersectsCoordinate = function intersectsCoordinate (coordinate) { + return this.containsXY(coordinate[0], coordinate[1]); + }; + + /** + * @abstract + * @param {import("../extent.js").Extent} extent Extent. + * @protected + * @return {import("../extent.js").Extent} extent Extent. + */ + Geometry.prototype.computeExtent = function computeExtent (extent) { + return util_abstract(); + }; + + /** + * Get the extent of the geometry. + * @param {import("../extent.js").Extent=} opt_extent Extent. + * @return {import("../extent.js").Extent} extent Extent. + * @api + */ + Geometry.prototype.getExtent = function getExtent (opt_extent) { + if (this.extentRevision_ != this.getRevision()) { + this.extent_ = this.computeExtent(this.extent_); + this.extentRevision_ = this.getRevision(); + } + return returnOrUpdate(this.extent_, opt_extent); + }; + + /** + * Rotate the geometry around a given coordinate. This modifies the geometry + * coordinates in place. + * @abstract + * @param {number} angle Rotation angle in radians. + * @param {import("../coordinate.js").Coordinate} anchor The rotation center. + * @api + */ + Geometry.prototype.rotate = function rotate (angle, anchor) { + util_abstract(); + }; + + /** + * Scale the geometry (with an optional origin). This modifies the geometry + * coordinates in place. + * @abstract + * @param {number} sx The scaling factor in the x-direction. + * @param {number=} opt_sy The scaling factor in the y-direction (defaults to + * sx). + * @param {import("../coordinate.js").Coordinate=} opt_anchor The scale origin (defaults to the center + * of the geometry extent). + * @api + */ + Geometry.prototype.scale = function scale (sx, opt_sy, opt_anchor) { + util_abstract(); + }; + + /** + * Create a simplified version of this geometry. For linestrings, this uses + * the the {@link + * https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm + * Douglas Peucker} algorithm. For polygons, a quantization-based + * simplification is used to preserve topology. + * @param {number} tolerance The tolerance distance for simplification. + * @return {Geometry} A new, simplified version of the original geometry. + * @api + */ + Geometry.prototype.simplify = function simplify (tolerance) { + return this.getSimplifiedGeometry(tolerance * tolerance); + }; + + /** + * Create a simplified version of this geometry using the Douglas Peucker + * algorithm. + * See https://en.wikipedia.org/wiki/Ramer-Douglas-Peucker_algorithm. + * @abstract + * @param {number} squaredTolerance Squared tolerance. + * @return {Geometry} Simplified geometry. + */ + Geometry.prototype.getSimplifiedGeometry = function getSimplifiedGeometry (squaredTolerance) { + return util_abstract(); + }; + + /** + * Get the type of this geometry. + * @abstract + * @return {import("./GeometryType.js").default} Geometry type. + */ + Geometry.prototype.getType = function getType () { + return util_abstract(); + }; + + /** + * Apply a transform function to each coordinate of the geometry. + * The geometry is modified in place. + * If you do not want the geometry modified in place, first `clone()` it and + * then use this function on the clone. + * @abstract + * @param {import("../proj.js").TransformFunction} transformFn Transform. + */ + Geometry.prototype.applyTransform = function applyTransform (transformFn) { + util_abstract(); + }; + + /** + * Test if the geometry and the passed extent intersect. + * @abstract + * @param {import("../extent.js").Extent} extent Extent. + * @return {boolean} `true` if the geometry and the extent intersect. + */ + Geometry.prototype.intersectsExtent = function intersectsExtent (extent) { + return util_abstract(); + }; + + /** + * Translate the geometry. This modifies the geometry coordinates in place. If + * instead you want a new geometry, first `clone()` this geometry. + * @abstract + * @param {number} deltaX Delta X. + * @param {number} deltaY Delta Y. + * @api + */ + Geometry.prototype.translate = function translate (deltaX, deltaY) { + util_abstract(); + }; + + /** + * Transform each coordinate of the geometry from one coordinate reference + * system to another. The geometry is modified in place. + * For example, a line will be transformed to a line and a circle to a circle. + * If you do not want the geometry modified in place, first `clone()` it and + * then use this function on the clone. + * + * @param {import("../proj.js").ProjectionLike} source The current projection. Can be a + * string identifier or a {@link module:ol/proj/Projection~Projection} object. + * @param {import("../proj.js").ProjectionLike} destination The desired projection. Can be a + * string identifier or a {@link module:ol/proj/Projection~Projection} object. + * @return {Geometry} This geometry. Note that original geometry is + * modified in place. + * @api + */ + Geometry.prototype.transform = function transform (source, destination) { + /** @type {import("../proj/Projection.js").default} */ + var sourceProj = proj_get(source); + var transformFn = sourceProj.getUnits() == proj_Units.TILE_PIXELS ? + function(inCoordinates, outCoordinates, stride) { + var pixelExtent = sourceProj.getExtent(); + var projectedExtent = sourceProj.getWorldExtent(); + var scale = getHeight(projectedExtent) / getHeight(pixelExtent); + transform_compose(tmpTransform, + projectedExtent[0], projectedExtent[3], + scale, -scale, 0, + 0, 0); + transform2D(inCoordinates, 0, inCoordinates.length, stride, + tmpTransform, outCoordinates); + return proj_getTransform(sourceProj, destination)(inCoordinates, outCoordinates, stride); + } : + proj_getTransform(sourceProj, destination); + this.applyTransform(transformFn); + return this; + }; + + return Geometry; +}(ol_Object)); + + +/* harmony default export */ var geom_Geometry = (Geometry_Geometry); + +//# sourceMappingURL=Geometry.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/SimpleGeometry.js +/** + * @module ol/geom/SimpleGeometry + */ + + + + + + + +/** + * @classdesc + * Abstract base class; only used for creating subclasses; do not instantiate + * in apps, as cannot be rendered. + * + * @abstract + * @api + */ +var SimpleGeometry_SimpleGeometry = /*@__PURE__*/(function (Geometry) { + function SimpleGeometry() { + + Geometry.call(this); + + /** + * @protected + * @type {GeometryLayout} + */ + this.layout = GeometryLayout.XY; + + /** + * @protected + * @type {number} + */ + this.stride = 2; + + /** + * @protected + * @type {Array} + */ + this.flatCoordinates = null; + + } + + if ( Geometry ) SimpleGeometry.__proto__ = Geometry; + SimpleGeometry.prototype = Object.create( Geometry && Geometry.prototype ); + SimpleGeometry.prototype.constructor = SimpleGeometry; + + /** + * @inheritDoc + */ + SimpleGeometry.prototype.computeExtent = function computeExtent (extent) { + return createOrUpdateFromFlatCoordinates(this.flatCoordinates, + 0, this.flatCoordinates.length, this.stride, extent); + }; + + /** + * @abstract + * @return {Array} Coordinates. + */ + SimpleGeometry.prototype.getCoordinates = function getCoordinates () { + return util_abstract(); + }; + + /** + * Return the first coordinate of the geometry. + * @return {import("../coordinate.js").Coordinate} First coordinate. + * @api + */ + SimpleGeometry.prototype.getFirstCoordinate = function getFirstCoordinate () { + return this.flatCoordinates.slice(0, this.stride); + }; + + /** + * @return {Array} Flat coordinates. + */ + SimpleGeometry.prototype.getFlatCoordinates = function getFlatCoordinates () { + return this.flatCoordinates; + }; + + /** + * Return the last coordinate of the geometry. + * @return {import("../coordinate.js").Coordinate} Last point. + * @api + */ + SimpleGeometry.prototype.getLastCoordinate = function getLastCoordinate () { + return this.flatCoordinates.slice(this.flatCoordinates.length - this.stride); + }; + + /** + * Return the {@link module:ol/geom/GeometryLayout layout} of the geometry. + * @return {GeometryLayout} Layout. + * @api + */ + SimpleGeometry.prototype.getLayout = function getLayout () { + return this.layout; + }; + + /** + * @inheritDoc + */ + SimpleGeometry.prototype.getSimplifiedGeometry = function getSimplifiedGeometry (squaredTolerance) { + if (this.simplifiedGeometryRevision != this.getRevision()) { + obj_clear(this.simplifiedGeometryCache); + this.simplifiedGeometryMaxMinSquaredTolerance = 0; + this.simplifiedGeometryRevision = this.getRevision(); + } + // If squaredTolerance is negative or if we know that simplification will not + // have any effect then just return this. + if (squaredTolerance < 0 || + (this.simplifiedGeometryMaxMinSquaredTolerance !== 0 && + squaredTolerance <= this.simplifiedGeometryMaxMinSquaredTolerance)) { + return this; + } + var key = squaredTolerance.toString(); + if (this.simplifiedGeometryCache.hasOwnProperty(key)) { + return this.simplifiedGeometryCache[key]; + } else { + var simplifiedGeometry = + this.getSimplifiedGeometryInternal(squaredTolerance); + var simplifiedFlatCoordinates = simplifiedGeometry.getFlatCoordinates(); + if (simplifiedFlatCoordinates.length < this.flatCoordinates.length) { + this.simplifiedGeometryCache[key] = simplifiedGeometry; + return simplifiedGeometry; + } else { + // Simplification did not actually remove any coordinates. We now know + // that any calls to getSimplifiedGeometry with a squaredTolerance less + // than or equal to the current squaredTolerance will also not have any + // effect. This allows us to short circuit simplification (saving CPU + // cycles) and prevents the cache of simplified geometries from filling + // up with useless identical copies of this geometry (saving memory). + this.simplifiedGeometryMaxMinSquaredTolerance = squaredTolerance; + return this; + } + } + }; + + /** + * @param {number} squaredTolerance Squared tolerance. + * @return {SimpleGeometry} Simplified geometry. + * @protected + */ + SimpleGeometry.prototype.getSimplifiedGeometryInternal = function getSimplifiedGeometryInternal (squaredTolerance) { + return this; + }; + + /** + * @return {number} Stride. + */ + SimpleGeometry.prototype.getStride = function getStride () { + return this.stride; + }; + + /** + * @param {GeometryLayout} layout Layout. + * @param {Array} flatCoordinates Flat coordinates. + */ + SimpleGeometry.prototype.setFlatCoordinates = function setFlatCoordinates (layout, flatCoordinates) { + this.stride = getStrideForLayout(layout); + this.layout = layout; + this.flatCoordinates = flatCoordinates; + }; + + /** + * @abstract + * @param {!Array} coordinates Coordinates. + * @param {GeometryLayout=} opt_layout Layout. + */ + SimpleGeometry.prototype.setCoordinates = function setCoordinates (coordinates, opt_layout) { + util_abstract(); + }; + + /** + * @param {GeometryLayout|undefined} layout Layout. + * @param {Array} coordinates Coordinates. + * @param {number} nesting Nesting. + * @protected + */ + SimpleGeometry.prototype.setLayout = function setLayout (layout, coordinates, nesting) { + /** @type {number} */ + var stride; + if (layout) { + stride = getStrideForLayout(layout); + } else { + for (var i = 0; i < nesting; ++i) { + if (coordinates.length === 0) { + this.layout = GeometryLayout.XY; + this.stride = 2; + return; + } else { + coordinates = /** @type {Array} */ (coordinates[0]); + } + } + stride = coordinates.length; + layout = getLayoutForStride(stride); + } + this.layout = layout; + this.stride = stride; + }; + + /** + * @inheritDoc + * @api + */ + SimpleGeometry.prototype.applyTransform = function applyTransform (transformFn) { + if (this.flatCoordinates) { + transformFn(this.flatCoordinates, this.flatCoordinates, this.stride); + this.changed(); + } + }; + + /** + * @inheritDoc + * @api + */ + SimpleGeometry.prototype.rotate = function rotate$1 (angle, anchor) { + var flatCoordinates = this.getFlatCoordinates(); + if (flatCoordinates) { + var stride = this.getStride(); + transform_rotate( + flatCoordinates, 0, flatCoordinates.length, + stride, angle, anchor, flatCoordinates); + this.changed(); + } + }; + + /** + * @inheritDoc + * @api + */ + SimpleGeometry.prototype.scale = function scale$1 (sx, opt_sy, opt_anchor) { + var sy = opt_sy; + if (sy === undefined) { + sy = sx; + } + var anchor = opt_anchor; + if (!anchor) { + anchor = extent_getCenter(this.getExtent()); + } + var flatCoordinates = this.getFlatCoordinates(); + if (flatCoordinates) { + var stride = this.getStride(); + transform_scale( + flatCoordinates, 0, flatCoordinates.length, + stride, sx, sy, anchor, flatCoordinates); + this.changed(); + } + }; + + /** + * @inheritDoc + * @api + */ + SimpleGeometry.prototype.translate = function translate$1 (deltaX, deltaY) { + var flatCoordinates = this.getFlatCoordinates(); + if (flatCoordinates) { + var stride = this.getStride(); + transform_translate( + flatCoordinates, 0, flatCoordinates.length, stride, + deltaX, deltaY, flatCoordinates); + this.changed(); + } + }; + + return SimpleGeometry; +}(geom_Geometry)); + + +/** + * @param {number} stride Stride. + * @return {GeometryLayout} layout Layout. + */ +function getLayoutForStride(stride) { + var layout; + if (stride == 2) { + layout = GeometryLayout.XY; + } else if (stride == 3) { + layout = GeometryLayout.XYZ; + } else if (stride == 4) { + layout = GeometryLayout.XYZM; + } + return ( + /** @type {GeometryLayout} */ (layout) + ); +} + + +/** + * @param {GeometryLayout} layout Layout. + * @return {number} Stride. + */ +function getStrideForLayout(layout) { + var stride; + if (layout == GeometryLayout.XY) { + stride = 2; + } else if (layout == GeometryLayout.XYZ || layout == GeometryLayout.XYM) { + stride = 3; + } else if (layout == GeometryLayout.XYZM) { + stride = 4; + } + return /** @type {number} */ (stride); +} + + +/** + * @param {SimpleGeometry} simpleGeometry Simple geometry. + * @param {import("../transform.js").Transform} transform Transform. + * @param {Array=} opt_dest Destination. + * @return {Array} Transformed flat coordinates. + */ +function transformGeom2D(simpleGeometry, transform, opt_dest) { + var flatCoordinates = simpleGeometry.getFlatCoordinates(); + if (!flatCoordinates) { + return null; + } else { + var stride = simpleGeometry.getStride(); + return transform2D( + flatCoordinates, 0, flatCoordinates.length, stride, + transform, opt_dest); + } +} + +/* harmony default export */ var geom_SimpleGeometry = (SimpleGeometry_SimpleGeometry); + +//# sourceMappingURL=SimpleGeometry.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/area.js +/** + * @module ol/geom/flat/area + */ + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @return {number} Area. + */ +function area_linearRing(flatCoordinates, offset, end, stride) { + var twiceArea = 0; + var x1 = flatCoordinates[end - stride]; + var y1 = flatCoordinates[end - stride + 1]; + for (; offset < end; offset += stride) { + var x2 = flatCoordinates[offset]; + var y2 = flatCoordinates[offset + 1]; + twiceArea += y1 * x2 - x1 * y2; + x1 = x2; + y1 = y2; + } + return twiceArea / 2; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @return {number} Area. + */ +function area_linearRings(flatCoordinates, offset, ends, stride) { + var area = 0; + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + area += area_linearRing(flatCoordinates, offset, end, stride); + offset = end; + } + return area; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @return {number} Area. + */ +function linearRingss(flatCoordinates, offset, endss, stride) { + var area = 0; + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + area += area_linearRings(flatCoordinates, offset, ends, stride); + offset = ends[ends.length - 1]; + } + return area; +} + +//# sourceMappingURL=area.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/closest.js +/** + * @module ol/geom/flat/closest + */ + + + +/** + * Returns the point on the 2D line segment flatCoordinates[offset1] to + * flatCoordinates[offset2] that is closest to the point (x, y). Extra + * dimensions are linearly interpolated. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset1 Offset 1. + * @param {number} offset2 Offset 2. + * @param {number} stride Stride. + * @param {number} x X. + * @param {number} y Y. + * @param {Array} closestPoint Closest point. + */ +function assignClosest(flatCoordinates, offset1, offset2, stride, x, y, closestPoint) { + var x1 = flatCoordinates[offset1]; + var y1 = flatCoordinates[offset1 + 1]; + var dx = flatCoordinates[offset2] - x1; + var dy = flatCoordinates[offset2 + 1] - y1; + var offset; + if (dx === 0 && dy === 0) { + offset = offset1; + } else { + var t = ((x - x1) * dx + (y - y1) * dy) / (dx * dx + dy * dy); + if (t > 1) { + offset = offset2; + } else if (t > 0) { + for (var i = 0; i < stride; ++i) { + closestPoint[i] = lerp(flatCoordinates[offset1 + i], + flatCoordinates[offset2 + i], t); + } + closestPoint.length = stride; + return; + } else { + offset = offset1; + } + } + for (var i$1 = 0; i$1 < stride; ++i$1) { + closestPoint[i$1] = flatCoordinates[offset + i$1]; + } + closestPoint.length = stride; +} + + +/** + * Return the squared of the largest distance between any pair of consecutive + * coordinates. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} max Max squared delta. + * @return {number} Max squared delta. + */ +function maxSquaredDelta(flatCoordinates, offset, end, stride, max) { + var x1 = flatCoordinates[offset]; + var y1 = flatCoordinates[offset + 1]; + for (offset += stride; offset < end; offset += stride) { + var x2 = flatCoordinates[offset]; + var y2 = flatCoordinates[offset + 1]; + var squaredDelta = math_squaredDistance(x1, y1, x2, y2); + if (squaredDelta > max) { + max = squaredDelta; + } + x1 = x2; + y1 = y2; + } + return max; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {number} max Max squared delta. + * @return {number} Max squared delta. + */ +function arrayMaxSquaredDelta(flatCoordinates, offset, ends, stride, max) { + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + max = maxSquaredDelta( + flatCoordinates, offset, end, stride, max); + offset = end; + } + return max; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {number} max Max squared delta. + * @return {number} Max squared delta. + */ +function multiArrayMaxSquaredDelta(flatCoordinates, offset, endss, stride, max) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + max = arrayMaxSquaredDelta( + flatCoordinates, offset, ends, stride, max); + offset = ends[ends.length - 1]; + } + return max; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} maxDelta Max delta. + * @param {boolean} isRing Is ring. + * @param {number} x X. + * @param {number} y Y. + * @param {Array} closestPoint Closest point. + * @param {number} minSquaredDistance Minimum squared distance. + * @param {Array=} opt_tmpPoint Temporary point object. + * @return {number} Minimum squared distance. + */ +function assignClosestPoint(flatCoordinates, offset, end, + stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, + opt_tmpPoint) { + if (offset == end) { + return minSquaredDistance; + } + var i, squaredDistance; + if (maxDelta === 0) { + // All points are identical, so just test the first point. + squaredDistance = math_squaredDistance( + x, y, flatCoordinates[offset], flatCoordinates[offset + 1]); + if (squaredDistance < minSquaredDistance) { + for (i = 0; i < stride; ++i) { + closestPoint[i] = flatCoordinates[offset + i]; + } + closestPoint.length = stride; + return squaredDistance; + } else { + return minSquaredDistance; + } + } + var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN]; + var index = offset + stride; + while (index < end) { + assignClosest( + flatCoordinates, index - stride, index, stride, x, y, tmpPoint); + squaredDistance = math_squaredDistance(x, y, tmpPoint[0], tmpPoint[1]); + if (squaredDistance < minSquaredDistance) { + minSquaredDistance = squaredDistance; + for (i = 0; i < stride; ++i) { + closestPoint[i] = tmpPoint[i]; + } + closestPoint.length = stride; + index += stride; + } else { + // Skip ahead multiple points, because we know that all the skipped + // points cannot be any closer than the closest point we have found so + // far. We know this because we know how close the current point is, how + // close the closest point we have found so far is, and the maximum + // distance between consecutive points. For example, if we're currently + // at distance 10, the best we've found so far is 3, and that the maximum + // distance between consecutive points is 2, then we'll need to skip at + // least (10 - 3) / 2 == 3 (rounded down) points to have any chance of + // finding a closer point. We use Math.max(..., 1) to ensure that we + // always advance at least one point, to avoid an infinite loop. + index += stride * Math.max( + ((Math.sqrt(squaredDistance) - + Math.sqrt(minSquaredDistance)) / maxDelta) | 0, 1); + } + } + if (isRing) { + // Check the closing segment. + assignClosest( + flatCoordinates, end - stride, offset, stride, x, y, tmpPoint); + squaredDistance = math_squaredDistance(x, y, tmpPoint[0], tmpPoint[1]); + if (squaredDistance < minSquaredDistance) { + minSquaredDistance = squaredDistance; + for (i = 0; i < stride; ++i) { + closestPoint[i] = tmpPoint[i]; + } + closestPoint.length = stride; + } + } + return minSquaredDistance; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {number} maxDelta Max delta. + * @param {boolean} isRing Is ring. + * @param {number} x X. + * @param {number} y Y. + * @param {Array} closestPoint Closest point. + * @param {number} minSquaredDistance Minimum squared distance. + * @param {Array=} opt_tmpPoint Temporary point object. + * @return {number} Minimum squared distance. + */ +function assignClosestArrayPoint(flatCoordinates, offset, ends, + stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, + opt_tmpPoint) { + var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN]; + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + minSquaredDistance = assignClosestPoint( + flatCoordinates, offset, end, stride, + maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint); + offset = end; + } + return minSquaredDistance; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {number} maxDelta Max delta. + * @param {boolean} isRing Is ring. + * @param {number} x X. + * @param {number} y Y. + * @param {Array} closestPoint Closest point. + * @param {number} minSquaredDistance Minimum squared distance. + * @param {Array=} opt_tmpPoint Temporary point object. + * @return {number} Minimum squared distance. + */ +function assignClosestMultiArrayPoint(flatCoordinates, offset, + endss, stride, maxDelta, isRing, x, y, closestPoint, minSquaredDistance, + opt_tmpPoint) { + var tmpPoint = opt_tmpPoint ? opt_tmpPoint : [NaN, NaN]; + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + minSquaredDistance = assignClosestArrayPoint( + flatCoordinates, offset, ends, stride, + maxDelta, isRing, x, y, closestPoint, minSquaredDistance, tmpPoint); + offset = ends[ends.length - 1]; + } + return minSquaredDistance; +} + +//# sourceMappingURL=closest.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/deflate.js +/** + * @module ol/geom/flat/deflate + */ + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. + * @param {number} stride Stride. + * @return {number} offset Offset. + */ +function deflateCoordinate(flatCoordinates, offset, coordinate, stride) { + for (var i = 0, ii = coordinate.length; i < ii; ++i) { + flatCoordinates[offset++] = coordinate[i]; + } + return offset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} coordinates Coordinates. + * @param {number} stride Stride. + * @return {number} offset Offset. + */ +function deflateCoordinates(flatCoordinates, offset, coordinates, stride) { + for (var i = 0, ii = coordinates.length; i < ii; ++i) { + var coordinate = coordinates[i]; + for (var j = 0; j < stride; ++j) { + flatCoordinates[offset++] = coordinate[j]; + } + } + return offset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} coordinatess Coordinatess. + * @param {number} stride Stride. + * @param {Array=} opt_ends Ends. + * @return {Array} Ends. + */ +function deflateCoordinatesArray(flatCoordinates, offset, coordinatess, stride, opt_ends) { + var ends = opt_ends ? opt_ends : []; + var i = 0; + for (var j = 0, jj = coordinatess.length; j < jj; ++j) { + var end = deflateCoordinates( + flatCoordinates, offset, coordinatess[j], stride); + ends[i++] = end; + offset = end; + } + ends.length = i; + return ends; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>>} coordinatesss Coordinatesss. + * @param {number} stride Stride. + * @param {Array>=} opt_endss Endss. + * @return {Array>} Endss. + */ +function deflateMultiCoordinatesArray(flatCoordinates, offset, coordinatesss, stride, opt_endss) { + var endss = opt_endss ? opt_endss : []; + var i = 0; + for (var j = 0, jj = coordinatesss.length; j < jj; ++j) { + var ends = deflateCoordinatesArray( + flatCoordinates, offset, coordinatesss[j], stride, endss[i]); + endss[i++] = ends; + offset = ends[ends.length - 1]; + } + endss.length = i; + return endss; +} + +//# sourceMappingURL=deflate.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/inflate.js +/** + * @module ol/geom/flat/inflate + */ + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {Array=} opt_coordinates Coordinates. + * @return {Array} Coordinates. + */ +function inflateCoordinates(flatCoordinates, offset, end, stride, opt_coordinates) { + var coordinates = opt_coordinates !== undefined ? opt_coordinates : []; + var i = 0; + for (var j = offset; j < end; j += stride) { + coordinates[i++] = flatCoordinates.slice(j, j + stride); + } + coordinates.length = i; + return coordinates; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {Array>=} opt_coordinatess Coordinatess. + * @return {Array>} Coordinatess. + */ +function inflateCoordinatesArray(flatCoordinates, offset, ends, stride, opt_coordinatess) { + var coordinatess = opt_coordinatess !== undefined ? opt_coordinatess : []; + var i = 0; + for (var j = 0, jj = ends.length; j < jj; ++j) { + var end = ends[j]; + coordinatess[i++] = inflateCoordinates( + flatCoordinates, offset, end, stride, coordinatess[i]); + offset = end; + } + coordinatess.length = i; + return coordinatess; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {Array>>=} opt_coordinatesss + * Coordinatesss. + * @return {Array>>} Coordinatesss. + */ +function inflateMultiCoordinatesArray(flatCoordinates, offset, endss, stride, opt_coordinatesss) { + var coordinatesss = opt_coordinatesss !== undefined ? opt_coordinatesss : []; + var i = 0; + for (var j = 0, jj = endss.length; j < jj; ++j) { + var ends = endss[j]; + coordinatesss[i++] = inflateCoordinatesArray( + flatCoordinates, offset, ends, stride, coordinatesss[i]); + offset = ends[ends.length - 1]; + } + coordinatesss.length = i; + return coordinatesss; +} + +//# sourceMappingURL=inflate.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/simplify.js +/** + * @module ol/geom/flat/simplify + */ +// Based on simplify-js https://github.com/mourner/simplify-js +// Copyright (c) 2012, Vladimir Agafonkin +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +// POSSIBILITY OF SUCH DAMAGE. + + + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} squaredTolerance Squared tolerance. + * @param {boolean} highQuality Highest quality. + * @param {Array=} opt_simplifiedFlatCoordinates Simplified flat + * coordinates. + * @return {Array} Simplified line string. + */ +function simplifyLineString(flatCoordinates, offset, end, + stride, squaredTolerance, highQuality, opt_simplifiedFlatCoordinates) { + var simplifiedFlatCoordinates = opt_simplifiedFlatCoordinates !== undefined ? + opt_simplifiedFlatCoordinates : []; + if (!highQuality) { + end = radialDistance(flatCoordinates, offset, end, + stride, squaredTolerance, + simplifiedFlatCoordinates, 0); + flatCoordinates = simplifiedFlatCoordinates; + offset = 0; + stride = 2; + } + simplifiedFlatCoordinates.length = douglasPeucker( + flatCoordinates, offset, end, stride, squaredTolerance, + simplifiedFlatCoordinates, 0); + return simplifiedFlatCoordinates; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} squaredTolerance Squared tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @return {number} Simplified offset. + */ +function douglasPeucker(flatCoordinates, offset, end, + stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) { + var n = (end - offset) / stride; + if (n < 3) { + for (; offset < end; offset += stride) { + simplifiedFlatCoordinates[simplifiedOffset++] = + flatCoordinates[offset]; + simplifiedFlatCoordinates[simplifiedOffset++] = + flatCoordinates[offset + 1]; + } + return simplifiedOffset; + } + /** @type {Array} */ + var markers = new Array(n); + markers[0] = 1; + markers[n - 1] = 1; + /** @type {Array} */ + var stack = [offset, end - stride]; + var index = 0; + while (stack.length > 0) { + var last = stack.pop(); + var first = stack.pop(); + var maxSquaredDistance = 0; + var x1 = flatCoordinates[first]; + var y1 = flatCoordinates[first + 1]; + var x2 = flatCoordinates[last]; + var y2 = flatCoordinates[last + 1]; + for (var i = first + stride; i < last; i += stride) { + var x = flatCoordinates[i]; + var y = flatCoordinates[i + 1]; + var squaredDistance = squaredSegmentDistance( + x, y, x1, y1, x2, y2); + if (squaredDistance > maxSquaredDistance) { + index = i; + maxSquaredDistance = squaredDistance; + } + } + if (maxSquaredDistance > squaredTolerance) { + markers[(index - offset) / stride] = 1; + if (first + stride < index) { + stack.push(first, index); + } + if (index + stride < last) { + stack.push(index, last); + } + } + } + for (var i$1 = 0; i$1 < n; ++i$1) { + if (markers[i$1]) { + simplifiedFlatCoordinates[simplifiedOffset++] = + flatCoordinates[offset + i$1 * stride]; + simplifiedFlatCoordinates[simplifiedOffset++] = + flatCoordinates[offset + i$1 * stride + 1]; + } + } + return simplifiedOffset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {number} squaredTolerance Squared tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @param {Array} simplifiedEnds Simplified ends. + * @return {number} Simplified offset. + */ +function douglasPeuckerArray(flatCoordinates, offset, + ends, stride, squaredTolerance, simplifiedFlatCoordinates, + simplifiedOffset, simplifiedEnds) { + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + simplifiedOffset = douglasPeucker( + flatCoordinates, offset, end, stride, squaredTolerance, + simplifiedFlatCoordinates, simplifiedOffset); + simplifiedEnds.push(simplifiedOffset); + offset = end; + } + return simplifiedOffset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {number} squaredTolerance Squared tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @param {Array>} simplifiedEndss Simplified endss. + * @return {number} Simplified offset. + */ +function douglasPeuckerMultiArray( + flatCoordinates, offset, endss, stride, squaredTolerance, + simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + var simplifiedEnds = []; + simplifiedOffset = douglasPeuckerArray( + flatCoordinates, offset, ends, stride, squaredTolerance, + simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds); + simplifiedEndss.push(simplifiedEnds); + offset = ends[ends.length - 1]; + } + return simplifiedOffset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} squaredTolerance Squared tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @return {number} Simplified offset. + */ +function radialDistance(flatCoordinates, offset, end, + stride, squaredTolerance, simplifiedFlatCoordinates, simplifiedOffset) { + if (end <= offset + stride) { + // zero or one point, no simplification possible, so copy and return + for (; offset < end; offset += stride) { + simplifiedFlatCoordinates[simplifiedOffset++] = flatCoordinates[offset]; + simplifiedFlatCoordinates[simplifiedOffset++] = + flatCoordinates[offset + 1]; + } + return simplifiedOffset; + } + var x1 = flatCoordinates[offset]; + var y1 = flatCoordinates[offset + 1]; + // copy first point + simplifiedFlatCoordinates[simplifiedOffset++] = x1; + simplifiedFlatCoordinates[simplifiedOffset++] = y1; + var x2 = x1; + var y2 = y1; + for (offset += stride; offset < end; offset += stride) { + x2 = flatCoordinates[offset]; + y2 = flatCoordinates[offset + 1]; + if (math_squaredDistance(x1, y1, x2, y2) > squaredTolerance) { + // copy point at offset + simplifiedFlatCoordinates[simplifiedOffset++] = x2; + simplifiedFlatCoordinates[simplifiedOffset++] = y2; + x1 = x2; + y1 = y2; + } + } + if (x2 != x1 || y2 != y1) { + // copy last point + simplifiedFlatCoordinates[simplifiedOffset++] = x2; + simplifiedFlatCoordinates[simplifiedOffset++] = y2; + } + return simplifiedOffset; +} + + +/** + * @param {number} value Value. + * @param {number} tolerance Tolerance. + * @return {number} Rounded value. + */ +function snap(value, tolerance) { + return tolerance * Math.round(value / tolerance); +} + + +/** + * Simplifies a line string using an algorithm designed by Tim Schaub. + * Coordinates are snapped to the nearest value in a virtual grid and + * consecutive duplicate coordinates are discarded. This effectively preserves + * topology as the simplification of any subsection of a line string is + * independent of the rest of the line string. This means that, for examples, + * the common edge between two polygons will be simplified to the same line + * string independently in both polygons. This implementation uses a single + * pass over the coordinates and eliminates intermediate collinear points. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} tolerance Tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @return {number} Simplified offset. + */ +function quantize(flatCoordinates, offset, end, stride, + tolerance, simplifiedFlatCoordinates, simplifiedOffset) { + // do nothing if the line is empty + if (offset == end) { + return simplifiedOffset; + } + // snap the first coordinate (P1) + var x1 = snap(flatCoordinates[offset], tolerance); + var y1 = snap(flatCoordinates[offset + 1], tolerance); + offset += stride; + // add the first coordinate to the output + simplifiedFlatCoordinates[simplifiedOffset++] = x1; + simplifiedFlatCoordinates[simplifiedOffset++] = y1; + // find the next coordinate that does not snap to the same value as the first + // coordinate (P2) + var x2, y2; + do { + x2 = snap(flatCoordinates[offset], tolerance); + y2 = snap(flatCoordinates[offset + 1], tolerance); + offset += stride; + if (offset == end) { + // all coordinates snap to the same value, the line collapses to a point + // push the last snapped value anyway to ensure that the output contains + // at least two points + // FIXME should we really return at least two points anyway? + simplifiedFlatCoordinates[simplifiedOffset++] = x2; + simplifiedFlatCoordinates[simplifiedOffset++] = y2; + return simplifiedOffset; + } + } while (x2 == x1 && y2 == y1); + while (offset < end) { + // snap the next coordinate (P3) + var x3 = snap(flatCoordinates[offset], tolerance); + var y3 = snap(flatCoordinates[offset + 1], tolerance); + offset += stride; + // skip P3 if it is equal to P2 + if (x3 == x2 && y3 == y2) { + continue; + } + // calculate the delta between P1 and P2 + var dx1 = x2 - x1; + var dy1 = y2 - y1; + // calculate the delta between P3 and P1 + var dx2 = x3 - x1; + var dy2 = y3 - y1; + // if P1, P2, and P3 are colinear and P3 is further from P1 than P2 is from + // P1 in the same direction then P2 is on the straight line between P1 and + // P3 + if ((dx1 * dy2 == dy1 * dx2) && + ((dx1 < 0 && dx2 < dx1) || dx1 == dx2 || (dx1 > 0 && dx2 > dx1)) && + ((dy1 < 0 && dy2 < dy1) || dy1 == dy2 || (dy1 > 0 && dy2 > dy1))) { + // discard P2 and set P2 = P3 + x2 = x3; + y2 = y3; + continue; + } + // either P1, P2, and P3 are not colinear, or they are colinear but P3 is + // between P3 and P1 or on the opposite half of the line to P2. add P2, + // and continue with P1 = P2 and P2 = P3 + simplifiedFlatCoordinates[simplifiedOffset++] = x2; + simplifiedFlatCoordinates[simplifiedOffset++] = y2; + x1 = x2; + y1 = y2; + x2 = x3; + y2 = y3; + } + // add the last point (P2) + simplifiedFlatCoordinates[simplifiedOffset++] = x2; + simplifiedFlatCoordinates[simplifiedOffset++] = y2; + return simplifiedOffset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {number} tolerance Tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @param {Array} simplifiedEnds Simplified ends. + * @return {number} Simplified offset. + */ +function quantizeArray( + flatCoordinates, offset, ends, stride, + tolerance, + simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds) { + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + simplifiedOffset = quantize( + flatCoordinates, offset, end, stride, + tolerance, + simplifiedFlatCoordinates, simplifiedOffset); + simplifiedEnds.push(simplifiedOffset); + offset = end; + } + return simplifiedOffset; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {number} tolerance Tolerance. + * @param {Array} simplifiedFlatCoordinates Simplified flat + * coordinates. + * @param {number} simplifiedOffset Simplified offset. + * @param {Array>} simplifiedEndss Simplified endss. + * @return {number} Simplified offset. + */ +function quantizeMultiArray( + flatCoordinates, offset, endss, stride, + tolerance, + simplifiedFlatCoordinates, simplifiedOffset, simplifiedEndss) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + var simplifiedEnds = []; + simplifiedOffset = quantizeArray( + flatCoordinates, offset, ends, stride, + tolerance, + simplifiedFlatCoordinates, simplifiedOffset, simplifiedEnds); + simplifiedEndss.push(simplifiedEnds); + offset = ends[ends.length - 1]; + } + return simplifiedOffset; +} + +//# sourceMappingURL=simplify.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/LinearRing.js +/** + * @module ol/geom/LinearRing + */ + + + + + + + + + + +/** + * @classdesc + * Linear ring geometry. Only used as part of polygon; cannot be rendered + * on its own. + * + * @api + */ +var LinearRing_LinearRing = /*@__PURE__*/(function (SimpleGeometry) { + function LinearRing(coordinates, opt_layout) { + + SimpleGeometry.call(this); + + /** + * @private + * @type {number} + */ + this.maxDelta_ = -1; + + /** + * @private + * @type {number} + */ + this.maxDeltaRevision_ = -1; + + if (opt_layout !== undefined && !Array.isArray(coordinates[0])) { + this.setFlatCoordinates(opt_layout, /** @type {Array} */ (coordinates)); + } else { + this.setCoordinates(/** @type {Array} */ (coordinates), opt_layout); + } + + } + + if ( SimpleGeometry ) LinearRing.__proto__ = SimpleGeometry; + LinearRing.prototype = Object.create( SimpleGeometry && SimpleGeometry.prototype ); + LinearRing.prototype.constructor = LinearRing; + + /** + * Make a complete copy of the geometry. + * @return {!LinearRing} Clone. + * @override + * @api + */ + LinearRing.prototype.clone = function clone () { + return new LinearRing(this.flatCoordinates.slice(), this.layout); + }; + + /** + * @inheritDoc + */ + LinearRing.prototype.closestPointXY = function closestPointXY (x, y, closestPoint, minSquaredDistance) { + if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { + return minSquaredDistance; + } + if (this.maxDeltaRevision_ != this.getRevision()) { + this.maxDelta_ = Math.sqrt(maxSquaredDelta( + this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, 0)); + this.maxDeltaRevision_ = this.getRevision(); + } + return assignClosestPoint( + this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, + this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); + }; + + /** + * Return the area of the linear ring on projected plane. + * @return {number} Area (on projected plane). + * @api + */ + LinearRing.prototype.getArea = function getArea () { + return area_linearRing(this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); + }; + + /** + * Return the coordinates of the linear ring. + * @return {Array} Coordinates. + * @override + * @api + */ + LinearRing.prototype.getCoordinates = function getCoordinates () { + return inflateCoordinates( + this.flatCoordinates, 0, this.flatCoordinates.length, this.stride); + }; + + /** + * @inheritDoc + */ + LinearRing.prototype.getSimplifiedGeometryInternal = function getSimplifiedGeometryInternal (squaredTolerance) { + var simplifiedFlatCoordinates = []; + simplifiedFlatCoordinates.length = douglasPeucker( + this.flatCoordinates, 0, this.flatCoordinates.length, this.stride, + squaredTolerance, simplifiedFlatCoordinates, 0); + return new LinearRing(simplifiedFlatCoordinates, GeometryLayout.XY); + }; + + /** + * @inheritDoc + * @api + */ + LinearRing.prototype.getType = function getType () { + return GeometryType.LINEAR_RING; + }; + + /** + * @inheritDoc + */ + LinearRing.prototype.intersectsExtent = function intersectsExtent (extent) { + return false; + }; + + /** + * Set the coordinates of the linear ring. + * @param {!Array} coordinates Coordinates. + * @param {GeometryLayout=} opt_layout Layout. + * @override + * @api + */ + LinearRing.prototype.setCoordinates = function setCoordinates (coordinates, opt_layout) { + this.setLayout(opt_layout, coordinates, 1); + if (!this.flatCoordinates) { + this.flatCoordinates = []; + } + this.flatCoordinates.length = deflateCoordinates( + this.flatCoordinates, 0, coordinates, this.stride); + this.changed(); + }; + + return LinearRing; +}(geom_SimpleGeometry)); + + +/* harmony default export */ var geom_LinearRing = (LinearRing_LinearRing); + +//# sourceMappingURL=LinearRing.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/Point.js +/** + * @module ol/geom/Point + */ + + + + + + +/** + * @classdesc + * Point geometry. + * + * @api + */ +var Point_Point = /*@__PURE__*/(function (SimpleGeometry) { + function Point(coordinates, opt_layout) { + SimpleGeometry.call(this); + this.setCoordinates(coordinates, opt_layout); + } + + if ( SimpleGeometry ) Point.__proto__ = SimpleGeometry; + Point.prototype = Object.create( SimpleGeometry && SimpleGeometry.prototype ); + Point.prototype.constructor = Point; + + /** + * Make a complete copy of the geometry. + * @return {!Point} Clone. + * @override + * @api + */ + Point.prototype.clone = function clone () { + var point = new Point(this.flatCoordinates.slice(), this.layout); + return point; + }; + + /** + * @inheritDoc + */ + Point.prototype.closestPointXY = function closestPointXY (x, y, closestPoint, minSquaredDistance) { + var flatCoordinates = this.flatCoordinates; + var squaredDistance = math_squaredDistance(x, y, flatCoordinates[0], flatCoordinates[1]); + if (squaredDistance < minSquaredDistance) { + var stride = this.stride; + for (var i = 0; i < stride; ++i) { + closestPoint[i] = flatCoordinates[i]; + } + closestPoint.length = stride; + return squaredDistance; + } else { + return minSquaredDistance; + } + }; + + /** + * Return the coordinate of the point. + * @return {import("../coordinate.js").Coordinate} Coordinates. + * @override + * @api + */ + Point.prototype.getCoordinates = function getCoordinates () { + return !this.flatCoordinates ? [] : this.flatCoordinates.slice(); + }; + + /** + * @inheritDoc + */ + Point.prototype.computeExtent = function computeExtent (extent) { + return createOrUpdateFromCoordinate(this.flatCoordinates, extent); + }; + + /** + * @inheritDoc + * @api + */ + Point.prototype.getType = function getType () { + return GeometryType.POINT; + }; + + /** + * @inheritDoc + * @api + */ + Point.prototype.intersectsExtent = function intersectsExtent (extent) { + return extent_containsXY(extent, this.flatCoordinates[0], this.flatCoordinates[1]); + }; + + /** + * @inheritDoc + * @api + */ + Point.prototype.setCoordinates = function setCoordinates (coordinates, opt_layout) { + this.setLayout(opt_layout, coordinates, 0); + if (!this.flatCoordinates) { + this.flatCoordinates = []; + } + this.flatCoordinates.length = deflateCoordinate( + this.flatCoordinates, 0, coordinates, this.stride); + this.changed(); + }; + + return Point; +}(geom_SimpleGeometry)); + + +/* harmony default export */ var geom_Point = (Point_Point); + +//# sourceMappingURL=Point.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/contains.js +/** + * @module ol/geom/flat/contains + */ + + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} Contains extent. + */ +function linearRingContainsExtent(flatCoordinates, offset, end, stride, extent) { + var outside = forEachCorner(extent, + /** + * @param {import("../../coordinate.js").Coordinate} coordinate Coordinate. + * @return {boolean} Contains (x, y). + */ + function(coordinate) { + return !linearRingContainsXY(flatCoordinates, offset, end, stride, coordinate[0], coordinate[1]); + }); + return !outside; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {number} x X. + * @param {number} y Y. + * @return {boolean} Contains (x, y). + */ +function linearRingContainsXY(flatCoordinates, offset, end, stride, x, y) { + // http://geomalgorithms.com/a03-_inclusion.html + // Copyright 2000 softSurfer, 2012 Dan Sunday + // This code may be freely used and modified for any purpose + // providing that this copyright notice is included with it. + // SoftSurfer makes no warranty for this code, and cannot be held + // liable for any real or imagined damage resulting from its use. + // Users of this code must verify correctness for their application. + var wn = 0; + var x1 = flatCoordinates[end - stride]; + var y1 = flatCoordinates[end - stride + 1]; + for (; offset < end; offset += stride) { + var x2 = flatCoordinates[offset]; + var y2 = flatCoordinates[offset + 1]; + if (y1 <= y) { + if (y2 > y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) > 0) { + wn++; + } + } else if (y2 <= y && ((x2 - x1) * (y - y1)) - ((x - x1) * (y2 - y1)) < 0) { + wn--; + } + x1 = x2; + y1 = y2; + } + return wn !== 0; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {number} x X. + * @param {number} y Y. + * @return {boolean} Contains (x, y). + */ +function linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y) { + if (ends.length === 0) { + return false; + } + if (!linearRingContainsXY(flatCoordinates, offset, ends[0], stride, x, y)) { + return false; + } + for (var i = 1, ii = ends.length; i < ii; ++i) { + if (linearRingContainsXY(flatCoordinates, ends[i - 1], ends[i], stride, x, y)) { + return false; + } + } + return true; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {number} x X. + * @param {number} y Y. + * @return {boolean} Contains (x, y). + */ +function linearRingssContainsXY(flatCoordinates, offset, endss, stride, x, y) { + if (endss.length === 0) { + return false; + } + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + if (linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y)) { + return true; + } + offset = ends[ends.length - 1]; + } + return false; +} + +//# sourceMappingURL=contains.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/interiorpoint.js +/** + * @module ol/geom/flat/interiorpoint + */ + + + + +/** + * Calculates a point that is likely to lie in the interior of the linear rings. + * Inspired by JTS's com.vividsolutions.jts.geom.Geometry#getInteriorPoint. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {Array} flatCenters Flat centers. + * @param {number} flatCentersOffset Flat center offset. + * @param {Array=} opt_dest Destination. + * @return {Array} Destination point as XYM coordinate, where M is the + * length of the horizontal intersection that the point belongs to. + */ +function getInteriorPointOfArray(flatCoordinates, offset, + ends, stride, flatCenters, flatCentersOffset, opt_dest) { + var i, ii, x, x1, x2, y1, y2; + var y = flatCenters[flatCentersOffset + 1]; + /** @type {Array} */ + var intersections = []; + // Calculate intersections with the horizontal line + for (var r = 0, rr = ends.length; r < rr; ++r) { + var end = ends[r]; + x1 = flatCoordinates[end - stride]; + y1 = flatCoordinates[end - stride + 1]; + for (i = offset; i < end; i += stride) { + x2 = flatCoordinates[i]; + y2 = flatCoordinates[i + 1]; + if ((y <= y1 && y2 <= y) || (y1 <= y && y <= y2)) { + x = (y - y1) / (y2 - y1) * (x2 - x1) + x1; + intersections.push(x); + } + x1 = x2; + y1 = y2; + } + } + // Find the longest segment of the horizontal line that has its center point + // inside the linear ring. + var pointX = NaN; + var maxSegmentLength = -Infinity; + intersections.sort(numberSafeCompareFunction); + x1 = intersections[0]; + for (i = 1, ii = intersections.length; i < ii; ++i) { + x2 = intersections[i]; + var segmentLength = Math.abs(x2 - x1); + if (segmentLength > maxSegmentLength) { + x = (x1 + x2) / 2; + if (linearRingsContainsXY(flatCoordinates, offset, ends, stride, x, y)) { + pointX = x; + maxSegmentLength = segmentLength; + } + } + x1 = x2; + } + if (isNaN(pointX)) { + // There is no horizontal line that has its center point inside the linear + // ring. Use the center of the the linear ring's extent. + pointX = flatCenters[flatCentersOffset]; + } + if (opt_dest) { + opt_dest.push(pointX, y, maxSegmentLength); + return opt_dest; + } else { + return [pointX, y, maxSegmentLength]; + } +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {Array} flatCenters Flat centers. + * @return {Array} Interior points as XYM coordinates, where M is the + * length of the horizontal intersection that the point belongs to. + */ +function getInteriorPointsOfMultiArray(flatCoordinates, offset, endss, stride, flatCenters) { + var interiorPoints = []; + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + interiorPoints = getInteriorPointOfArray(flatCoordinates, + offset, ends, stride, flatCenters, 2 * i, interiorPoints); + offset = ends[ends.length - 1]; + } + return interiorPoints; +} + +//# sourceMappingURL=interiorpoint.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/segments.js +/** + * @module ol/geom/flat/segments + */ + + +/** + * This function calls `callback` for each segment of the flat coordinates + * array. If the callback returns a truthy value the function returns that + * value immediately. Otherwise the function returns `false`. + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {function(this: S, import("../../coordinate.js").Coordinate, import("../../coordinate.js").Coordinate): T} callback Function + * called for each segment. + * @param {S=} opt_this The object to be used as the value of 'this' + * within callback. + * @return {T|boolean} Value. + * @template T,S + */ +function forEach(flatCoordinates, offset, end, stride, callback, opt_this) { + var point1 = [flatCoordinates[offset], flatCoordinates[offset + 1]]; + var point2 = []; + var ret; + for (; (offset + stride) < end; offset += stride) { + point2[0] = flatCoordinates[offset + stride]; + point2[1] = flatCoordinates[offset + stride + 1]; + ret = callback.call(opt_this, point1, point2); + if (ret) { + return ret; + } + point1[0] = point2[0]; + point1[1] = point2[1]; + } + return false; +} + +//# sourceMappingURL=segments.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/intersectsextent.js +/** + * @module ol/geom/flat/intersectsextent + */ + + + + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +function intersectsLineString(flatCoordinates, offset, end, stride, extent) { + var coordinatesExtent = extendFlatCoordinates( + createEmpty(), flatCoordinates, offset, end, stride); + if (!extent_intersects(extent, coordinatesExtent)) { + return false; + } + if (containsExtent(extent, coordinatesExtent)) { + return true; + } + if (coordinatesExtent[0] >= extent[0] && + coordinatesExtent[2] <= extent[2]) { + return true; + } + if (coordinatesExtent[1] >= extent[1] && + coordinatesExtent[3] <= extent[3]) { + return true; + } + return forEach(flatCoordinates, offset, end, stride, + /** + * @param {import("../../coordinate.js").Coordinate} point1 Start point. + * @param {import("../../coordinate.js").Coordinate} point2 End point. + * @return {boolean} `true` if the segment and the extent intersect, + * `false` otherwise. + */ + function(point1, point2) { + return intersectsSegment(extent, point1, point2); + }); +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +function intersectsLineStringArray(flatCoordinates, offset, ends, stride, extent) { + for (var i = 0, ii = ends.length; i < ii; ++i) { + if (intersectsLineString( + flatCoordinates, offset, ends[i], stride, extent)) { + return true; + } + offset = ends[i]; + } + return false; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +function intersectsLinearRing(flatCoordinates, offset, end, stride, extent) { + if (intersectsLineString( + flatCoordinates, offset, end, stride, extent)) { + return true; + } + if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[0], extent[1])) { + return true; + } + if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[0], extent[3])) { + return true; + } + if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[2], extent[1])) { + return true; + } + if (linearRingContainsXY(flatCoordinates, offset, end, stride, extent[2], extent[3])) { + return true; + } + return false; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +function intersectsLinearRingArray(flatCoordinates, offset, ends, stride, extent) { + if (!intersectsLinearRing( + flatCoordinates, offset, ends[0], stride, extent)) { + return false; + } + if (ends.length === 1) { + return true; + } + for (var i = 1, ii = ends.length; i < ii; ++i) { + if (linearRingContainsExtent(flatCoordinates, ends[i - 1], ends[i], stride, extent)) { + if (!intersectsLineString(flatCoordinates, ends[i - 1], ends[i], stride, extent)) { + return false; + } + } + } + return true; +} + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Endss. + * @param {number} stride Stride. + * @param {import("../../extent.js").Extent} extent Extent. + * @return {boolean} True if the geometry and the extent intersect. + */ +function intersectsLinearRingMultiArray(flatCoordinates, offset, endss, stride, extent) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + var ends = endss[i]; + if (intersectsLinearRingArray( + flatCoordinates, offset, ends, stride, extent)) { + return true; + } + offset = ends[ends.length - 1]; + } + return false; +} + +//# sourceMappingURL=intersectsextent.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/reverse.js +/** + * @module ol/geom/flat/reverse + */ + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + */ +function reverse_coordinates(flatCoordinates, offset, end, stride) { + while (offset < end - stride) { + for (var i = 0; i < stride; ++i) { + var tmp = flatCoordinates[offset + i]; + flatCoordinates[offset + i] = flatCoordinates[end - stride + i]; + flatCoordinates[end - stride + i] = tmp; + } + offset += stride; + end -= stride; + } +} + +//# sourceMappingURL=reverse.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/flat/orient.js +/** + * @module ol/geom/flat/orient + */ + + + +/** + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {number} end End. + * @param {number} stride Stride. + * @return {boolean} Is clockwise. + */ +function linearRingIsClockwise(flatCoordinates, offset, end, stride) { + // http://tinyurl.com/clockwise-method + // https://github.com/OSGeo/gdal/blob/trunk/gdal/ogr/ogrlinearring.cpp + var edge = 0; + var x1 = flatCoordinates[end - stride]; + var y1 = flatCoordinates[end - stride + 1]; + for (; offset < end; offset += stride) { + var x2 = flatCoordinates[offset]; + var y2 = flatCoordinates[offset + 1]; + edge += (x2 - x1) * (y2 + y1); + x1 = x2; + y1 = y2; + } + return edge > 0; +} + + +/** + * Determines if linear rings are oriented. By default, left-hand orientation + * is tested (first ring must be clockwise, remaining rings counter-clockwise). + * To test for right-hand orientation, use the `opt_right` argument. + * + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Array of end indexes. + * @param {number} stride Stride. + * @param {boolean=} opt_right Test for right-hand orientation + * (counter-clockwise exterior ring and clockwise interior rings). + * @return {boolean} Rings are correctly oriented. + */ +function linearRingIsOriented(flatCoordinates, offset, ends, stride, opt_right) { + var right = opt_right !== undefined ? opt_right : false; + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + var isClockwise = linearRingIsClockwise( + flatCoordinates, offset, end, stride); + if (i === 0) { + if ((right && isClockwise) || (!right && !isClockwise)) { + return false; + } + } else { + if ((right && !isClockwise) || (!right && isClockwise)) { + return false; + } + } + offset = end; + } + return true; +} + + +/** + * Determines if linear rings are oriented. By default, left-hand orientation + * is tested (first ring must be clockwise, remaining rings counter-clockwise). + * To test for right-hand orientation, use the `opt_right` argument. + * + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Array of array of end indexes. + * @param {number} stride Stride. + * @param {boolean=} opt_right Test for right-hand orientation + * (counter-clockwise exterior ring and clockwise interior rings). + * @return {boolean} Rings are correctly oriented. + */ +function linearRingsAreOriented(flatCoordinates, offset, endss, stride, opt_right) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + if (!linearRingIsOriented( + flatCoordinates, offset, endss[i], stride, opt_right)) { + return false; + } + } + return true; +} + + +/** + * Orient coordinates in a flat array of linear rings. By default, rings + * are oriented following the left-hand rule (clockwise for exterior and + * counter-clockwise for interior rings). To orient according to the + * right-hand rule, use the `opt_right` argument. + * + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array} ends Ends. + * @param {number} stride Stride. + * @param {boolean=} opt_right Follow the right-hand rule for orientation. + * @return {number} End. + */ +function orientLinearRings(flatCoordinates, offset, ends, stride, opt_right) { + var right = opt_right !== undefined ? opt_right : false; + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + var isClockwise = linearRingIsClockwise( + flatCoordinates, offset, end, stride); + var reverse = i === 0 ? + (right && isClockwise) || (!right && !isClockwise) : + (right && !isClockwise) || (!right && isClockwise); + if (reverse) { + reverse_coordinates(flatCoordinates, offset, end, stride); + } + offset = end; + } + return offset; +} + + +/** + * Orient coordinates in a flat array of linear rings. By default, rings + * are oriented following the left-hand rule (clockwise for exterior and + * counter-clockwise for interior rings). To orient according to the + * right-hand rule, use the `opt_right` argument. + * + * @param {Array} flatCoordinates Flat coordinates. + * @param {number} offset Offset. + * @param {Array>} endss Array of array of end indexes. + * @param {number} stride Stride. + * @param {boolean=} opt_right Follow the right-hand rule for orientation. + * @return {number} End. + */ +function orientLinearRingsArray(flatCoordinates, offset, endss, stride, opt_right) { + for (var i = 0, ii = endss.length; i < ii; ++i) { + offset = orientLinearRings( + flatCoordinates, offset, endss[i], stride, opt_right); + } + return offset; +} + +//# sourceMappingURL=orient.js.map +// CONCATENATED MODULE: ./node_modules/ol/geom/Polygon.js +/** + * @module ol/geom/Polygon + */ + + + + + + + + + + + + + + + + + + + +/** + * @classdesc + * Polygon geometry. + * + * @api + */ +var Polygon_Polygon = /*@__PURE__*/(function (SimpleGeometry) { + function Polygon(coordinates, opt_layout, opt_ends) { + + SimpleGeometry.call(this); + + /** + * @type {Array} + * @private + */ + this.ends_ = []; + + /** + * @private + * @type {number} + */ + this.flatInteriorPointRevision_ = -1; + + /** + * @private + * @type {import("../coordinate.js").Coordinate} + */ + this.flatInteriorPoint_ = null; + + /** + * @private + * @type {number} + */ + this.maxDelta_ = -1; + + /** + * @private + * @type {number} + */ + this.maxDeltaRevision_ = -1; + + /** + * @private + * @type {number} + */ + this.orientedRevision_ = -1; + + /** + * @private + * @type {Array} + */ + this.orientedFlatCoordinates_ = null; + + if (opt_layout !== undefined && opt_ends) { + this.setFlatCoordinates(opt_layout, /** @type {Array} */ (coordinates)); + this.ends_ = opt_ends; + } else { + this.setCoordinates(/** @type {Array>} */ (coordinates), opt_layout); + } + + } + + if ( SimpleGeometry ) Polygon.__proto__ = SimpleGeometry; + Polygon.prototype = Object.create( SimpleGeometry && SimpleGeometry.prototype ); + Polygon.prototype.constructor = Polygon; + + /** + * Append the passed linear ring to this polygon. + * @param {LinearRing} linearRing Linear ring. + * @api + */ + Polygon.prototype.appendLinearRing = function appendLinearRing (linearRing) { + if (!this.flatCoordinates) { + this.flatCoordinates = linearRing.getFlatCoordinates().slice(); + } else { + extend(this.flatCoordinates, linearRing.getFlatCoordinates()); + } + this.ends_.push(this.flatCoordinates.length); + this.changed(); + }; + + /** + * Make a complete copy of the geometry. + * @return {!Polygon} Clone. + * @override + * @api + */ + Polygon.prototype.clone = function clone () { + return new Polygon(this.flatCoordinates.slice(), this.layout, this.ends_.slice()); + }; + + /** + * @inheritDoc + */ + Polygon.prototype.closestPointXY = function closestPointXY (x, y, closestPoint, minSquaredDistance) { + if (minSquaredDistance < closestSquaredDistanceXY(this.getExtent(), x, y)) { + return minSquaredDistance; + } + if (this.maxDeltaRevision_ != this.getRevision()) { + this.maxDelta_ = Math.sqrt(arrayMaxSquaredDelta( + this.flatCoordinates, 0, this.ends_, this.stride, 0)); + this.maxDeltaRevision_ = this.getRevision(); + } + return assignClosestArrayPoint( + this.flatCoordinates, 0, this.ends_, this.stride, + this.maxDelta_, true, x, y, closestPoint, minSquaredDistance); + }; + + /** + * @inheritDoc + */ + Polygon.prototype.containsXY = function containsXY (x, y) { + return linearRingsContainsXY(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, x, y); + }; + + /** + * Return the area of the polygon on projected plane. + * @return {number} Area (on projected plane). + * @api + */ + Polygon.prototype.getArea = function getArea () { + return area_linearRings(this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride); + }; + + /** + * Get the coordinate array for this geometry. This array has the structure + * of a GeoJSON coordinate array for polygons. + * + * @param {boolean=} opt_right Orient coordinates according to the right-hand + * rule (counter-clockwise for exterior and clockwise for interior rings). + * If `false`, coordinates will be oriented according to the left-hand rule + * (clockwise for exterior and counter-clockwise for interior rings). + * By default, coordinate orientation will depend on how the geometry was + * constructed. + * @return {Array>} Coordinates. + * @override + * @api + */ + Polygon.prototype.getCoordinates = function getCoordinates (opt_right) { + var flatCoordinates; + if (opt_right !== undefined) { + flatCoordinates = this.getOrientedFlatCoordinates().slice(); + orientLinearRings( + flatCoordinates, 0, this.ends_, this.stride, opt_right); + } else { + flatCoordinates = this.flatCoordinates; + } + + return inflateCoordinatesArray( + flatCoordinates, 0, this.ends_, this.stride); + }; + + /** + * @return {Array} Ends. + */ + Polygon.prototype.getEnds = function getEnds () { + return this.ends_; + }; + + /** + * @return {Array} Interior point. + */ + Polygon.prototype.getFlatInteriorPoint = function getFlatInteriorPoint () { + if (this.flatInteriorPointRevision_ != this.getRevision()) { + var flatCenter = extent_getCenter(this.getExtent()); + this.flatInteriorPoint_ = getInteriorPointOfArray( + this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, + flatCenter, 0); + this.flatInteriorPointRevision_ = this.getRevision(); + } + return this.flatInteriorPoint_; + }; + + /** + * Return an interior point of the polygon. + * @return {Point} Interior point as XYM coordinate, where M is the + * length of the horizontal intersection that the point belongs to. + * @api + */ + Polygon.prototype.getInteriorPoint = function getInteriorPoint () { + return new geom_Point(this.getFlatInteriorPoint(), GeometryLayout.XYM); + }; + + /** + * Return the number of rings of the polygon, this includes the exterior + * ring and any interior rings. + * + * @return {number} Number of rings. + * @api + */ + Polygon.prototype.getLinearRingCount = function getLinearRingCount () { + return this.ends_.length; + }; + + /** + * Return the Nth linear ring of the polygon geometry. Return `null` if the + * given index is out of range. + * The exterior linear ring is available at index `0` and the interior rings + * at index `1` and beyond. + * + * @param {number} index Index. + * @return {LinearRing} Linear ring. + * @api + */ + Polygon.prototype.getLinearRing = function getLinearRing (index) { + if (index < 0 || this.ends_.length <= index) { + return null; + } + return new geom_LinearRing(this.flatCoordinates.slice( + index === 0 ? 0 : this.ends_[index - 1], this.ends_[index]), this.layout); + }; + + /** + * Return the linear rings of the polygon. + * @return {Array} Linear rings. + * @api + */ + Polygon.prototype.getLinearRings = function getLinearRings () { + var layout = this.layout; + var flatCoordinates = this.flatCoordinates; + var ends = this.ends_; + var linearRings = []; + var offset = 0; + for (var i = 0, ii = ends.length; i < ii; ++i) { + var end = ends[i]; + var linearRing = new geom_LinearRing(flatCoordinates.slice(offset, end), layout); + linearRings.push(linearRing); + offset = end; + } + return linearRings; + }; + + /** + * @return {Array} Oriented flat coordinates. + */ + Polygon.prototype.getOrientedFlatCoordinates = function getOrientedFlatCoordinates () { + if (this.orientedRevision_ != this.getRevision()) { + var flatCoordinates = this.flatCoordinates; + if (linearRingIsOriented( + flatCoordinates, 0, this.ends_, this.stride)) { + this.orientedFlatCoordinates_ = flatCoordinates; + } else { + this.orientedFlatCoordinates_ = flatCoordinates.slice(); + this.orientedFlatCoordinates_.length = + orientLinearRings( + this.orientedFlatCoordinates_, 0, this.ends_, this.stride); + } + this.orientedRevision_ = this.getRevision(); + } + return this.orientedFlatCoordinates_; + }; + + /** + * @inheritDoc + */ + Polygon.prototype.getSimplifiedGeometryInternal = function getSimplifiedGeometryInternal (squaredTolerance) { + var simplifiedFlatCoordinates = []; + var simplifiedEnds = []; + simplifiedFlatCoordinates.length = quantizeArray( + this.flatCoordinates, 0, this.ends_, this.stride, + Math.sqrt(squaredTolerance), + simplifiedFlatCoordinates, 0, simplifiedEnds); + return new Polygon(simplifiedFlatCoordinates, GeometryLayout.XY, simplifiedEnds); + }; + + /** + * @inheritDoc + * @api + */ + Polygon.prototype.getType = function getType () { + return GeometryType.POLYGON; + }; + + /** + * @inheritDoc + * @api + */ + Polygon.prototype.intersectsExtent = function intersectsExtent (extent) { + return intersectsLinearRingArray( + this.getOrientedFlatCoordinates(), 0, this.ends_, this.stride, extent); + }; + + /** + * Set the coordinates of the polygon. + * @param {!Array>} coordinates Coordinates. + * @param {GeometryLayout=} opt_layout Layout. + * @override + * @api + */ + Polygon.prototype.setCoordinates = function setCoordinates (coordinates, opt_layout) { + this.setLayout(opt_layout, coordinates, 2); + if (!this.flatCoordinates) { + this.flatCoordinates = []; + } + var ends = deflateCoordinatesArray( + this.flatCoordinates, 0, coordinates, this.stride, this.ends_); + this.flatCoordinates.length = ends.length === 0 ? 0 : ends[ends.length - 1]; + this.changed(); + }; + + return Polygon; +}(geom_SimpleGeometry)); + + +/* harmony default export */ var geom_Polygon = (Polygon_Polygon); + + +/** + * Create an approximation of a circle on the surface of a sphere. + * @param {import("../coordinate.js").Coordinate} center Center (`[lon, lat]` in degrees). + * @param {number} radius The great-circle distance from the center to + * the polygon vertices. + * @param {number=} opt_n Optional number of vertices for the resulting + * polygon. Default is `32`. + * @param {number=} opt_sphereRadius Optional radius for the sphere (defaults to + * the Earth's mean radius using the WGS84 ellipsoid). + * @return {Polygon} The "circular" polygon. + * @api + */ +function circular(center, radius, opt_n, opt_sphereRadius) { + var n = opt_n ? opt_n : 32; + /** @type {Array} */ + var flatCoordinates = []; + for (var i = 0; i < n; ++i) { + extend(flatCoordinates, sphere_offset(center, radius, 2 * Math.PI * i / n, opt_sphereRadius)); + } + flatCoordinates.push(flatCoordinates[0], flatCoordinates[1]); + return new Polygon_Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]); +} + + +/** + * Create a polygon from an extent. The layout used is `XY`. + * @param {import("../extent.js").Extent} extent The extent. + * @return {Polygon} The polygon. + * @api + */ +function fromExtent(extent) { + var minX = extent[0]; + var minY = extent[1]; + var maxX = extent[2]; + var maxY = extent[3]; + var flatCoordinates = + [minX, minY, minX, maxY, maxX, maxY, maxX, minY, minX, minY]; + return new Polygon_Polygon(flatCoordinates, GeometryLayout.XY, [flatCoordinates.length]); +} + + +/** + * Create a regular polygon from a circle. + * @param {import("./Circle.js").default} circle Circle geometry. + * @param {number=} opt_sides Number of sides of the polygon. Default is 32. + * @param {number=} opt_angle Start angle for the first vertex of the polygon in + * radians. Default is 0. + * @return {Polygon} Polygon geometry. + * @api + */ +function fromCircle(circle, opt_sides, opt_angle) { + var sides = opt_sides ? opt_sides : 32; + var stride = circle.getStride(); + var layout = circle.getLayout(); + var center = circle.getCenter(); + var arrayLength = stride * (sides + 1); + var flatCoordinates = new Array(arrayLength); + for (var i = 0; i < arrayLength; i += stride) { + flatCoordinates[i] = 0; + flatCoordinates[i + 1] = 0; + for (var j = 2; j < stride; j++) { + flatCoordinates[i + j] = center[j]; + } + } + var ends = [flatCoordinates.length]; + var polygon = new Polygon_Polygon(flatCoordinates, layout, ends); + makeRegular(polygon, center, circle.getRadius(), opt_angle); + return polygon; +} + + +/** + * Modify the coordinates of a polygon to make it a regular polygon. + * @param {Polygon} polygon Polygon geometry. + * @param {import("../coordinate.js").Coordinate} center Center of the regular polygon. + * @param {number} radius Radius of the regular polygon. + * @param {number=} opt_angle Start angle for the first vertex of the polygon in + * radians. Default is 0. + */ +function makeRegular(polygon, center, radius, opt_angle) { + var flatCoordinates = polygon.getFlatCoordinates(); + var stride = polygon.getStride(); + var sides = flatCoordinates.length / stride - 1; + var startAngle = opt_angle ? opt_angle : 0; + for (var i = 0; i <= sides; ++i) { + var offset = i * stride; + var angle = startAngle + (modulo(i, sides) * 2 * Math.PI / sides); + flatCoordinates[offset] = center[0] + (radius * Math.cos(angle)); + flatCoordinates[offset + 1] = center[1] + (radius * Math.sin(angle)); + } + polygon.changed(); +} + +//# sourceMappingURL=Polygon.js.map +// CONCATENATED MODULE: ./node_modules/ol/View.js +/** + * @module ol/View + */ + + + + + + + + + + + + + + + + + + + + + + +/** + * An animation configuration + * + * @typedef {Object} Animation + * @property {import("./coordinate.js").Coordinate} [sourceCenter] + * @property {import("./coordinate.js").Coordinate} [targetCenter] + * @property {number} [sourceResolution] + * @property {number} [targetResolution] + * @property {number} [sourceRotation] + * @property {number} [targetRotation] + * @property {import("./coordinate.js").Coordinate} [anchor] + * @property {number} start + * @property {number} duration + * @property {boolean} complete + * @property {function(number):number} easing + * @property {function(boolean)} callback + */ + + +/** + * @typedef {Object} Constraints + * @property {import("./centerconstraint.js").Type} center + * @property {import("./resolutionconstraint.js").Type} resolution + * @property {import("./rotationconstraint.js").Type} rotation + */ + + +/** + * @typedef {Object} FitOptions + * @property {import("./size.js").Size} [size] The size in pixels of the box to fit + * the extent into. Default is the current size of the first map in the DOM that + * uses this view, or `[100, 100]` if no such map is found. + * @property {!Array} [padding=[0, 0, 0, 0]] Padding (in pixels) to be + * cleared inside the view. Values in the array are top, right, bottom and left + * padding. + * @property {boolean} [constrainResolution=true] Constrain the resolution. + * @property {boolean} [nearest=false] If `constrainResolution` is `true`, get + * the nearest extent instead of the closest that actually fits the view. + * @property {number} [minResolution=0] Minimum resolution that we zoom to. + * @property {number} [maxZoom] Maximum zoom level that we zoom to. If + * `minResolution` is given, this property is ignored. + * @property {number} [duration] The duration of the animation in milliseconds. + * By default, there is no animation to the target extent. + * @property {function(number):number} [easing] The easing function used during + * the animation (defaults to {@link module:ol/easing~inAndOut}). + * The function will be called for each frame with a number representing a + * fraction of the animation's duration. The function should return a number + * between 0 and 1 representing the progress toward the destination state. + * @property {function(boolean)} [callback] Function called when the view is in + * its final position. The callback will be called with `true` if the animation + * series completed on its own or `false` if it was cancelled. + */ + + +/** + * @typedef {Object} ViewOptions + * @property {import("./coordinate.js").Coordinate} [center] The initial center for + * the view. The coordinate system for the center is specified with the + * `projection` option. Layer sources will not be fetched if this is not set, + * but the center can be set later with {@link #setCenter}. + * @property {boolean|number} [constrainRotation=true] Rotation constraint. + * `false` means no constraint. `true` means no constraint, but snap to zero + * near zero. A number constrains the rotation to that number of values. For + * example, `4` will constrain the rotation to 0, 90, 180, and 270 degrees. + * @property {boolean} [enableRotation=true] Enable rotation. + * If `false`, a rotation constraint that always sets the rotation to zero is + * used. The `constrainRotation` option has no effect if `enableRotation` is + * `false`. + * @property {import("./extent.js").Extent} [extent] The extent that constrains the + * center, in other words, center cannot be set outside this extent. + * @property {number} [maxResolution] The maximum resolution used to determine + * the resolution constraint. It is used together with `minResolution` (or + * `maxZoom`) and `zoomFactor`. If unspecified it is calculated in such a way + * that the projection's validity extent fits in a 256x256 px tile. If the + * projection is Spherical Mercator (the default) then `maxResolution` defaults + * to `40075016.68557849 / 256 = 156543.03392804097`. + * @property {number} [minResolution] The minimum resolution used to determine + * the resolution constraint. It is used together with `maxResolution` (or + * `minZoom`) and `zoomFactor`. If unspecified it is calculated assuming 29 + * zoom levels (with a factor of 2). If the projection is Spherical Mercator + * (the default) then `minResolution` defaults to + * `40075016.68557849 / 256 / Math.pow(2, 28) = 0.0005831682455839253`. + * @property {number} [maxZoom=28] The maximum zoom level used to determine the + * resolution constraint. It is used together with `minZoom` (or + * `maxResolution`) and `zoomFactor`. Note that if `minResolution` is also + * provided, it is given precedence over `maxZoom`. + * @property {number} [minZoom=0] The minimum zoom level used to determine the + * resolution constraint. It is used together with `maxZoom` (or + * `minResolution`) and `zoomFactor`. Note that if `maxResolution` is also + * provided, it is given precedence over `minZoom`. + * @property {import("./proj.js").ProjectionLike} [projection='EPSG:3857'] The + * projection. The default is Spherical Mercator. + * @property {number} [resolution] The initial resolution for the view. The + * units are `projection` units per pixel (e.g. meters per pixel). An + * alternative to setting this is to set `zoom`. Layer sources will not be + * fetched if neither this nor `zoom` are defined, but they can be set later + * with {@link #setZoom} or {@link #setResolution}. + * @property {Array} [resolutions] Resolutions to determine the + * resolution constraint. If set the `maxResolution`, `minResolution`, + * `minZoom`, `maxZoom`, and `zoomFactor` options are ignored. + * @property {number} [rotation=0] The initial rotation for the view in radians + * (positive rotation clockwise, 0 means North). + * @property {number} [zoom] Only used if `resolution` is not defined. Zoom + * level used to calculate the initial resolution for the view. The initial + * resolution is determined using the {@link #constrainResolution} method. + * @property {number} [zoomFactor=2] The zoom factor used to determine the + * resolution constraint. + */ + + +/** + * @typedef {Object} AnimationOptions + * @property {import("./coordinate.js").Coordinate} [center] The center of the view at the end of + * the animation. + * @property {number} [zoom] The zoom level of the view at the end of the + * animation. This takes precedence over `resolution`. + * @property {number} [resolution] The resolution of the view at the end + * of the animation. If `zoom` is also provided, this option will be ignored. + * @property {number} [rotation] The rotation of the view at the end of + * the animation. + * @property {import("./coordinate.js").Coordinate} [anchor] Optional anchor to remained fixed + * during a rotation or resolution animation. + * @property {number} [duration=1000] The duration of the animation in milliseconds. + * @property {function(number):number} [easing] The easing function used + * during the animation (defaults to {@link module:ol/easing~inAndOut}). + * The function will be called for each frame with a number representing a + * fraction of the animation's duration. The function should return a number + * between 0 and 1 representing the progress toward the destination state. + */ + + +/** + * @typedef {Object} State + * @property {import("./coordinate.js").Coordinate} center + * @property {import("./proj/Projection.js").default} projection + * @property {number} resolution + * @property {number} rotation + * @property {number} zoom + */ + + +/** + * Default min zoom level for the map view. + * @type {number} + */ +var DEFAULT_MIN_ZOOM = 0; + + +/** + * @classdesc + * A View object represents a simple 2D view of the map. + * + * This is the object to act upon to change the center, resolution, + * and rotation of the map. + * + * ### The view states + * + * An View is determined by three states: `center`, `resolution`, + * and `rotation`. Each state has a corresponding getter and setter, e.g. + * `getCenter` and `setCenter` for the `center` state. + * + * An View has a `projection`. The projection determines the + * coordinate system of the center, and its units determine the units of the + * resolution (projection units per pixel). The default projection is + * Spherical Mercator (EPSG:3857). + * + * ### The constraints + * + * `setCenter`, `setResolution` and `setRotation` can be used to change the + * states of the view. Any value can be passed to the setters. And the value + * that is passed to a setter will effectively be the value set in the view, + * and returned by the corresponding getter. + * + * But a View object also has a *resolution constraint*, a + * *rotation constraint* and a *center constraint*. + * + * As said above, no constraints are applied when the setters are used to set + * new states for the view. Applying constraints is done explicitly through + * the use of the `constrain*` functions (`constrainResolution` and + * `constrainRotation` and `constrainCenter`). + * + * The main users of the constraints are the interactions and the + * controls. For example, double-clicking on the map changes the view to + * the "next" resolution. And releasing the fingers after pinch-zooming + * snaps to the closest resolution (with an animation). + * + * The *resolution constraint* snaps to specific resolutions. It is + * determined by the following options: `resolutions`, `maxResolution`, + * `maxZoom`, and `zoomFactor`. If `resolutions` is set, the other three + * options are ignored. See documentation for each option for more + * information. + * + * The *rotation constraint* snaps to specific angles. It is determined + * by the following options: `enableRotation` and `constrainRotation`. + * By default the rotation value is snapped to zero when approaching the + * horizontal. + * + * The *center constraint* is determined by the `extent` option. By + * default the center is not constrained at all. + * + * @api + */ +var View_View = /*@__PURE__*/(function (BaseObject) { + function View(opt_options) { + BaseObject.call(this); + + var options = obj_assign({}, opt_options); + + /** + * @private + * @type {Array} + */ + this.hints_ = [0, 0]; + + /** + * @private + * @type {Array>} + */ + this.animations_ = []; + + /** + * @private + * @type {number|undefined} + */ + this.updateAnimationKey_; + + this.updateAnimations_ = this.updateAnimations_.bind(this); + + /** + * @private + * @const + * @type {import("./proj/Projection.js").default} + */ + this.projection_ = createProjection(options.projection, 'EPSG:3857'); + + this.applyOptions_(options); + } + + if ( BaseObject ) View.__proto__ = BaseObject; + View.prototype = Object.create( BaseObject && BaseObject.prototype ); + View.prototype.constructor = View; + + /** + * Set up the view with the given options. + * @param {ViewOptions} options View options. + */ + View.prototype.applyOptions_ = function applyOptions_ (options) { + + /** + * @type {Object} + */ + var properties = {}; + properties[ViewProperty.CENTER] = options.center !== undefined ? + options.center : null; + + var resolutionConstraintInfo = createResolutionConstraint(options); + + /** + * @private + * @type {number} + */ + this.maxResolution_ = resolutionConstraintInfo.maxResolution; + + /** + * @private + * @type {number} + */ + this.minResolution_ = resolutionConstraintInfo.minResolution; + + /** + * @private + * @type {number} + */ + this.zoomFactor_ = resolutionConstraintInfo.zoomFactor; + + /** + * @private + * @type {Array|undefined} + */ + this.resolutions_ = options.resolutions; + + /** + * @private + * @type {number} + */ + this.minZoom_ = resolutionConstraintInfo.minZoom; + + var centerConstraint = createCenterConstraint(options); + var resolutionConstraint = resolutionConstraintInfo.constraint; + var rotationConstraint = createRotationConstraint(options); + + /** + * @private + * @type {Constraints} + */ + this.constraints_ = { + center: centerConstraint, + resolution: resolutionConstraint, + rotation: rotationConstraint + }; + + if (options.resolution !== undefined) { + properties[ViewProperty.RESOLUTION] = options.resolution; + } else if (options.zoom !== undefined) { + properties[ViewProperty.RESOLUTION] = this.constrainResolution( + this.maxResolution_, options.zoom - this.minZoom_); + + if (this.resolutions_) { // in case map zoom is out of min/max zoom range + properties[ViewProperty.RESOLUTION] = clamp( + Number(this.getResolution() || properties[ViewProperty.RESOLUTION]), + this.minResolution_, this.maxResolution_); + } + } + properties[ViewProperty.ROTATION] = options.rotation !== undefined ? options.rotation : 0; + this.setProperties(properties); + + /** + * @private + * @type {ViewOptions} + */ + this.options_ = options; + + }; + + /** + * Get an updated version of the view options used to construct the view. The + * current resolution (or zoom), center, and rotation are applied to any stored + * options. The provided options can be used to apply new min/max zoom or + * resolution limits. + * @param {ViewOptions} newOptions New options to be applied. + * @return {ViewOptions} New options updated with the current view state. + */ + View.prototype.getUpdatedOptions_ = function getUpdatedOptions_ (newOptions) { + var options = obj_assign({}, this.options_); + + // preserve resolution (or zoom) + if (options.resolution !== undefined) { + options.resolution = this.getResolution(); + } else { + options.zoom = this.getZoom(); + } + + // preserve center + options.center = this.getCenter(); + + // preserve rotation + options.rotation = this.getRotation(); + + return obj_assign({}, options, newOptions); + }; + + /** + * Animate the view. The view's center, zoom (or resolution), and rotation + * can be animated for smooth transitions between view states. For example, + * to animate the view to a new zoom level: + * + * view.animate({zoom: view.getZoom() + 1}); + * + * By default, the animation lasts one second and uses in-and-out easing. You + * can customize this behavior by including `duration` (in milliseconds) and + * `easing` options (see {@link module:ol/easing}). + * + * To chain together multiple animations, call the method with multiple + * animation objects. For example, to first zoom and then pan: + * + * view.animate({zoom: 10}, {center: [0, 0]}); + * + * If you provide a function as the last argument to the animate method, it + * will get called at the end of an animation series. The callback will be + * called with `true` if the animation series completed on its own or `false` + * if it was cancelled. + * + * Animations are cancelled by user interactions (e.g. dragging the map) or by + * calling `view.setCenter()`, `view.setResolution()`, or `view.setRotation()` + * (or another method that calls one of these). + * + * @param {...(AnimationOptions|function(boolean))} var_args Animation + * options. Multiple animations can be run in series by passing multiple + * options objects. To run multiple animations in parallel, call the method + * multiple times. An optional callback can be provided as a final + * argument. The callback will be called with a boolean indicating whether + * the animation completed without being cancelled. + * @api + */ + View.prototype.animate = function animate (var_args) { + var arguments$1 = arguments; + + var animationCount = arguments.length; + var callback; + if (animationCount > 1 && typeof arguments[animationCount - 1] === 'function') { + callback = arguments[animationCount - 1]; + --animationCount; + } + if (!this.isDef()) { + // if view properties are not yet set, shortcut to the final state + var state = arguments[animationCount - 1]; + if (state.center) { + this.setCenter(state.center); + } + if (state.zoom !== undefined) { + this.setZoom(state.zoom); + } + if (state.rotation !== undefined) { + this.setRotation(state.rotation); + } + if (callback) { + animationCallback(callback, true); + } + return; + } + var start = Date.now(); + var center = this.getCenter().slice(); + var resolution = this.getResolution(); + var rotation = this.getRotation(); + var series = []; + for (var i = 0; i < animationCount; ++i) { + var options = /** @type {AnimationOptions} */ (arguments$1[i]); + + var animation = /** @type {Animation} */ ({ + start: start, + complete: false, + anchor: options.anchor, + duration: options.duration !== undefined ? options.duration : 1000, + easing: options.easing || inAndOut + }); + + if (options.center) { + animation.sourceCenter = center; + animation.targetCenter = options.center; + center = animation.targetCenter; + } + + if (options.zoom !== undefined) { + animation.sourceResolution = resolution; + animation.targetResolution = this.constrainResolution( + this.maxResolution_, options.zoom - this.minZoom_, 0); + resolution = animation.targetResolution; + } else if (options.resolution) { + animation.sourceResolution = resolution; + animation.targetResolution = options.resolution; + resolution = animation.targetResolution; + } + + if (options.rotation !== undefined) { + animation.sourceRotation = rotation; + var delta = modulo(options.rotation - rotation + Math.PI, 2 * Math.PI) - Math.PI; + animation.targetRotation = rotation + delta; + rotation = animation.targetRotation; + } + + animation.callback = callback; + + // check if animation is a no-op + if (isNoopAnimation(animation)) { + animation.complete = true; + // we still push it onto the series for callback handling + } else { + start += animation.duration; + } + series.push(animation); + } + this.animations_.push(series); + this.setHint(ViewHint.ANIMATING, 1); + this.updateAnimations_(); + }; + + /** + * Determine if the view is being animated. + * @return {boolean} The view is being animated. + * @api + */ + View.prototype.getAnimating = function getAnimating () { + return this.hints_[ViewHint.ANIMATING] > 0; + }; + + /** + * Determine if the user is interacting with the view, such as panning or zooming. + * @return {boolean} The view is being interacted with. + * @api + */ + View.prototype.getInteracting = function getInteracting () { + return this.hints_[ViewHint.INTERACTING] > 0; + }; + + /** + * Cancel any ongoing animations. + * @api + */ + View.prototype.cancelAnimations = function cancelAnimations () { + this.setHint(ViewHint.ANIMATING, -this.hints_[ViewHint.ANIMATING]); + for (var i = 0, ii = this.animations_.length; i < ii; ++i) { + var series = this.animations_[i]; + if (series[0].callback) { + animationCallback(series[0].callback, false); + } + } + this.animations_.length = 0; + }; + + /** + * Update all animations. + */ + View.prototype.updateAnimations_ = function updateAnimations_ () { + if (this.updateAnimationKey_ !== undefined) { + cancelAnimationFrame(this.updateAnimationKey_); + this.updateAnimationKey_ = undefined; + } + if (!this.getAnimating()) { + return; + } + var now = Date.now(); + var more = false; + for (var i = this.animations_.length - 1; i >= 0; --i) { + var series = this.animations_[i]; + var seriesComplete = true; + for (var j = 0, jj = series.length; j < jj; ++j) { + var animation = series[j]; + if (animation.complete) { + continue; + } + var elapsed = now - animation.start; + var fraction = animation.duration > 0 ? elapsed / animation.duration : 1; + if (fraction >= 1) { + animation.complete = true; + fraction = 1; + } else { + seriesComplete = false; + } + var progress = animation.easing(fraction); + if (animation.sourceCenter) { + var x0 = animation.sourceCenter[0]; + var y0 = animation.sourceCenter[1]; + var x1 = animation.targetCenter[0]; + var y1 = animation.targetCenter[1]; + var x = x0 + progress * (x1 - x0); + var y = y0 + progress * (y1 - y0); + this.set(ViewProperty.CENTER, [x, y]); + } + if (animation.sourceResolution && animation.targetResolution) { + var resolution = progress === 1 ? + animation.targetResolution : + animation.sourceResolution + progress * (animation.targetResolution - animation.sourceResolution); + if (animation.anchor) { + this.set(ViewProperty.CENTER, + this.calculateCenterZoom(resolution, animation.anchor)); + } + this.set(ViewProperty.RESOLUTION, resolution); + } + if (animation.sourceRotation !== undefined && animation.targetRotation !== undefined) { + var rotation = progress === 1 ? + modulo(animation.targetRotation + Math.PI, 2 * Math.PI) - Math.PI : + animation.sourceRotation + progress * (animation.targetRotation - animation.sourceRotation); + if (animation.anchor) { + this.set(ViewProperty.CENTER, + this.calculateCenterRotate(rotation, animation.anchor)); + } + this.set(ViewProperty.ROTATION, rotation); + } + more = true; + if (!animation.complete) { + break; + } + } + if (seriesComplete) { + this.animations_[i] = null; + this.setHint(ViewHint.ANIMATING, -1); + var callback = series[0].callback; + if (callback) { + animationCallback(callback, true); + } + } + } + // prune completed series + this.animations_ = this.animations_.filter(Boolean); + if (more && this.updateAnimationKey_ === undefined) { + this.updateAnimationKey_ = requestAnimationFrame(this.updateAnimations_); + } + }; + + /** + * @param {number} rotation Target rotation. + * @param {import("./coordinate.js").Coordinate} anchor Rotation anchor. + * @return {import("./coordinate.js").Coordinate|undefined} Center for rotation and anchor. + */ + View.prototype.calculateCenterRotate = function calculateCenterRotate (rotation, anchor) { + var center; + var currentCenter = this.getCenter(); + if (currentCenter !== undefined) { + center = [currentCenter[0] - anchor[0], currentCenter[1] - anchor[1]]; + coordinate_rotate(center, rotation - this.getRotation()); + add(center, anchor); + } + return center; + }; + + /** + * @param {number} resolution Target resolution. + * @param {import("./coordinate.js").Coordinate} anchor Zoom anchor. + * @return {import("./coordinate.js").Coordinate|undefined} Center for resolution and anchor. + */ + View.prototype.calculateCenterZoom = function calculateCenterZoom (resolution, anchor) { + var center; + var currentCenter = this.getCenter(); + var currentResolution = this.getResolution(); + if (currentCenter !== undefined && currentResolution !== undefined) { + var x = anchor[0] - resolution * (anchor[0] - currentCenter[0]) / currentResolution; + var y = anchor[1] - resolution * (anchor[1] - currentCenter[1]) / currentResolution; + center = [x, y]; + } + return center; + }; + + /** + * @private + * @return {import("./size.js").Size} Viewport size or `[100, 100]` when no viewport is found. + */ + View.prototype.getSizeFromViewport_ = function getSizeFromViewport_ () { + var size = [100, 100]; + var selector = '.ol-viewport[data-view="' + getUid(this) + '"]'; + var element = document.querySelector(selector); + if (element) { + var metrics = getComputedStyle(element); + size[0] = parseInt(metrics.width, 10); + size[1] = parseInt(metrics.height, 10); + } + return size; + }; + + /** + * Get the constrained center of this view. + * @param {import("./coordinate.js").Coordinate|undefined} center Center. + * @return {import("./coordinate.js").Coordinate|undefined} Constrained center. + * @api + */ + View.prototype.constrainCenter = function constrainCenter (center) { + return this.constraints_.center(center); + }; + + /** + * Get the constrained resolution of this view. + * @param {number|undefined} resolution Resolution. + * @param {number=} opt_delta Delta. Default is `0`. + * @param {number=} opt_direction Direction. Default is `0`. + * @return {number|undefined} Constrained resolution. + * @api + */ + View.prototype.constrainResolution = function constrainResolution (resolution, opt_delta, opt_direction) { + var delta = opt_delta || 0; + var direction = opt_direction || 0; + return this.constraints_.resolution(resolution, delta, direction); + }; + + /** + * Get the constrained rotation of this view. + * @param {number|undefined} rotation Rotation. + * @param {number=} opt_delta Delta. Default is `0`. + * @return {number|undefined} Constrained rotation. + * @api + */ + View.prototype.constrainRotation = function constrainRotation (rotation, opt_delta) { + var delta = opt_delta || 0; + return this.constraints_.rotation(rotation, delta); + }; + + /** + * Get the view center. + * @return {import("./coordinate.js").Coordinate|undefined} The center of the view. + * @observable + * @api + */ + View.prototype.getCenter = function getCenter () { + return ( + /** @type {import("./coordinate.js").Coordinate|undefined} */ (this.get(ViewProperty.CENTER)) + ); + }; + + /** + * @return {Constraints} Constraints. + */ + View.prototype.getConstraints = function getConstraints () { + return this.constraints_; + }; + + /** + * @param {Array=} opt_hints Destination array. + * @return {Array} Hint. + */ + View.prototype.getHints = function getHints (opt_hints) { + if (opt_hints !== undefined) { + opt_hints[0] = this.hints_[0]; + opt_hints[1] = this.hints_[1]; + return opt_hints; + } else { + return this.hints_.slice(); + } + }; + + /** + * Calculate the extent for the current view state and the passed size. + * The size is the pixel dimensions of the box into which the calculated extent + * should fit. In most cases you want to get the extent of the entire map, + * that is `map.getSize()`. + * @param {import("./size.js").Size=} opt_size Box pixel size. If not provided, the size of the + * first map that uses this view will be used. + * @return {import("./extent.js").Extent} Extent. + * @api + */ + View.prototype.calculateExtent = function calculateExtent (opt_size) { + var size = opt_size || this.getSizeFromViewport_(); + var center = /** @type {!import("./coordinate.js").Coordinate} */ (this.getCenter()); + assert(center, 1); // The view center is not defined + var resolution = /** @type {!number} */ (this.getResolution()); + assert(resolution !== undefined, 2); // The view resolution is not defined + var rotation = /** @type {!number} */ (this.getRotation()); + assert(rotation !== undefined, 3); // The view rotation is not defined + + return getForViewAndSize(center, resolution, rotation, size); + }; + + /** + * Get the maximum resolution of the view. + * @return {number} The maximum resolution of the view. + * @api + */ + View.prototype.getMaxResolution = function getMaxResolution () { + return this.maxResolution_; + }; + + /** + * Get the minimum resolution of the view. + * @return {number} The minimum resolution of the view. + * @api + */ + View.prototype.getMinResolution = function getMinResolution () { + return this.minResolution_; + }; + + /** + * Get the maximum zoom level for the view. + * @return {number} The maximum zoom level. + * @api + */ + View.prototype.getMaxZoom = function getMaxZoom () { + return /** @type {number} */ (this.getZoomForResolution(this.minResolution_)); + }; + + /** + * Set a new maximum zoom level for the view. + * @param {number} zoom The maximum zoom level. + * @api + */ + View.prototype.setMaxZoom = function setMaxZoom (zoom) { + this.applyOptions_(this.getUpdatedOptions_({maxZoom: zoom})); + }; + + /** + * Get the minimum zoom level for the view. + * @return {number} The minimum zoom level. + * @api + */ + View.prototype.getMinZoom = function getMinZoom () { + return /** @type {number} */ (this.getZoomForResolution(this.maxResolution_)); + }; + + /** + * Set a new minimum zoom level for the view. + * @param {number} zoom The minimum zoom level. + * @api + */ + View.prototype.setMinZoom = function setMinZoom (zoom) { + this.applyOptions_(this.getUpdatedOptions_({minZoom: zoom})); + }; + + /** + * Get the view projection. + * @return {import("./proj/Projection.js").default} The projection of the view. + * @api + */ + View.prototype.getProjection = function getProjection () { + return this.projection_; + }; + + /** + * Get the view resolution. + * @return {number|undefined} The resolution of the view. + * @observable + * @api + */ + View.prototype.getResolution = function getResolution () { + return /** @type {number|undefined} */ (this.get(ViewProperty.RESOLUTION)); + }; + + /** + * Get the resolutions for the view. This returns the array of resolutions + * passed to the constructor of the View, or undefined if none were given. + * @return {Array|undefined} The resolutions of the view. + * @api + */ + View.prototype.getResolutions = function getResolutions () { + return this.resolutions_; + }; + + /** + * Get the resolution for a provided extent (in map units) and size (in pixels). + * @param {import("./extent.js").Extent} extent Extent. + * @param {import("./size.js").Size=} opt_size Box pixel size. + * @return {number} The resolution at which the provided extent will render at + * the given size. + * @api + */ + View.prototype.getResolutionForExtent = function getResolutionForExtent (extent, opt_size) { + var size = opt_size || this.getSizeFromViewport_(); + var xResolution = getWidth(extent) / size[0]; + var yResolution = getHeight(extent) / size[1]; + return Math.max(xResolution, yResolution); + }; + + /** + * Return a function that returns a value between 0 and 1 for a + * resolution. Exponential scaling is assumed. + * @param {number=} opt_power Power. + * @return {function(number): number} Resolution for value function. + */ + View.prototype.getResolutionForValueFunction = function getResolutionForValueFunction (opt_power) { + var power = opt_power || 2; + var maxResolution = this.maxResolution_; + var minResolution = this.minResolution_; + var max = Math.log(maxResolution / minResolution) / Math.log(power); + return ( + /** + * @param {number} value Value. + * @return {number} Resolution. + */ + function(value) { + var resolution = maxResolution / Math.pow(power, value * max); + return resolution; + }); + }; + + /** + * Get the view rotation. + * @return {number} The rotation of the view in radians. + * @observable + * @api + */ + View.prototype.getRotation = function getRotation () { + return /** @type {number} */ (this.get(ViewProperty.ROTATION)); + }; + + /** + * Return a function that returns a resolution for a value between + * 0 and 1. Exponential scaling is assumed. + * @param {number=} opt_power Power. + * @return {function(number): number} Value for resolution function. + */ + View.prototype.getValueForResolutionFunction = function getValueForResolutionFunction (opt_power) { + var power = opt_power || 2; + var maxResolution = this.maxResolution_; + var minResolution = this.minResolution_; + var max = Math.log(maxResolution / minResolution) / Math.log(power); + return ( + /** + * @param {number} resolution Resolution. + * @return {number} Value. + */ + function(resolution) { + var value = (Math.log(maxResolution / resolution) / Math.log(power)) / max; + return value; + }); + }; + + /** + * @param {number} pixelRatio Pixel ratio for center rounding. + * @return {State} View state. + */ + View.prototype.getState = function getState (pixelRatio) { + var center = /** @type {import("./coordinate.js").Coordinate} */ (this.getCenter()); + var projection = this.getProjection(); + var resolution = /** @type {number} */ (this.getResolution()); + var pixelResolution = resolution / pixelRatio; + var rotation = this.getRotation(); + return ( + /** @type {State} */ ({ + center: [ + Math.round(center[0] / pixelResolution) * pixelResolution, + Math.round(center[1] / pixelResolution) * pixelResolution + ], + projection: projection !== undefined ? projection : null, + resolution: resolution, + rotation: rotation, + zoom: this.getZoom() + }) + ); + }; + + /** + * Get the current zoom level. If you configured your view with a resolutions + * array (this is rare), this method may return non-integer zoom levels (so + * the zoom level is not safe to use as an index into a resolutions array). + * @return {number|undefined} Zoom. + * @api + */ + View.prototype.getZoom = function getZoom () { + var zoom; + var resolution = this.getResolution(); + if (resolution !== undefined) { + zoom = this.getZoomForResolution(resolution); + } + return zoom; + }; + + /** + * Get the zoom level for a resolution. + * @param {number} resolution The resolution. + * @return {number|undefined} The zoom level for the provided resolution. + * @api + */ + View.prototype.getZoomForResolution = function getZoomForResolution (resolution) { + var offset = this.minZoom_ || 0; + var max, zoomFactor; + if (this.resolutions_) { + var nearest = linearFindNearest(this.resolutions_, resolution, 1); + offset = nearest; + max = this.resolutions_[nearest]; + if (nearest == this.resolutions_.length - 1) { + zoomFactor = 2; + } else { + zoomFactor = max / this.resolutions_[nearest + 1]; + } + } else { + max = this.maxResolution_; + zoomFactor = this.zoomFactor_; + } + return offset + Math.log(max / resolution) / Math.log(zoomFactor); + }; + + /** + * Get the resolution for a zoom level. + * @param {number} zoom Zoom level. + * @return {number} The view resolution for the provided zoom level. + * @api + */ + View.prototype.getResolutionForZoom = function getResolutionForZoom (zoom) { + return /** @type {number} */ (this.constrainResolution( + this.maxResolution_, zoom - this.minZoom_, 0)); + }; + + /** + * Fit the given geometry or extent based on the given map size and border. + * The size is pixel dimensions of the box to fit the extent into. + * In most cases you will want to use the map size, that is `map.getSize()`. + * Takes care of the map angle. + * @param {import("./geom/SimpleGeometry.js").default|import("./extent.js").Extent} geometryOrExtent The geometry or + * extent to fit the view to. + * @param {FitOptions=} opt_options Options. + * @api + */ + View.prototype.fit = function fit (geometryOrExtent, opt_options) { + var options = opt_options || {}; + var size = options.size; + if (!size) { + size = this.getSizeFromViewport_(); + } + /** @type {import("./geom/SimpleGeometry.js").default} */ + var geometry; + assert(Array.isArray(geometryOrExtent) || typeof /** @type {?} */ (geometryOrExtent).getSimplifiedGeometry === 'function', + 24); // Invalid extent or geometry provided as `geometry` + if (Array.isArray(geometryOrExtent)) { + assert(!extent_isEmpty(geometryOrExtent), + 25); // Cannot fit empty extent provided as `geometry` + geometry = fromExtent(geometryOrExtent); + } else if (geometryOrExtent.getType() === GeometryType.CIRCLE) { + geometryOrExtent = geometryOrExtent.getExtent(); + geometry = fromExtent(geometryOrExtent); + geometry.rotate(this.getRotation(), extent_getCenter(geometryOrExtent)); + } else { + geometry = geometryOrExtent; + } + + var padding = options.padding !== undefined ? options.padding : [0, 0, 0, 0]; + var constrainResolution = options.constrainResolution !== undefined ? + options.constrainResolution : true; + var nearest = options.nearest !== undefined ? options.nearest : false; + var minResolution; + if (options.minResolution !== undefined) { + minResolution = options.minResolution; + } else if (options.maxZoom !== undefined) { + minResolution = this.constrainResolution( + this.maxResolution_, options.maxZoom - this.minZoom_, 0); + } else { + minResolution = 0; + } + var coords = geometry.getFlatCoordinates(); + + // calculate rotated extent + var rotation = this.getRotation(); + var cosAngle = Math.cos(-rotation); + var sinAngle = Math.sin(-rotation); + var minRotX = +Infinity; + var minRotY = +Infinity; + var maxRotX = -Infinity; + var maxRotY = -Infinity; + var stride = geometry.getStride(); + for (var i = 0, ii = coords.length; i < ii; i += stride) { + var rotX = coords[i] * cosAngle - coords[i + 1] * sinAngle; + var rotY = coords[i] * sinAngle + coords[i + 1] * cosAngle; + minRotX = Math.min(minRotX, rotX); + minRotY = Math.min(minRotY, rotY); + maxRotX = Math.max(maxRotX, rotX); + maxRotY = Math.max(maxRotY, rotY); + } + + // calculate resolution + var resolution = this.getResolutionForExtent( + [minRotX, minRotY, maxRotX, maxRotY], + [size[0] - padding[1] - padding[3], size[1] - padding[0] - padding[2]]); + resolution = isNaN(resolution) ? minResolution : + Math.max(resolution, minResolution); + if (constrainResolution) { + var constrainedResolution = this.constrainResolution(resolution, 0, 0); + if (!nearest && constrainedResolution < resolution) { + constrainedResolution = this.constrainResolution( + constrainedResolution, -1, 0); + } + resolution = constrainedResolution; + } + + // calculate center + sinAngle = -sinAngle; // go back to original rotation + var centerRotX = (minRotX + maxRotX) / 2; + var centerRotY = (minRotY + maxRotY) / 2; + centerRotX += (padding[1] - padding[3]) / 2 * resolution; + centerRotY += (padding[0] - padding[2]) / 2 * resolution; + var centerX = centerRotX * cosAngle - centerRotY * sinAngle; + var centerY = centerRotY * cosAngle + centerRotX * sinAngle; + var center = [centerX, centerY]; + var callback = options.callback ? options.callback : VOID; + + if (options.duration !== undefined) { + this.animate({ + resolution: resolution, + center: center, + duration: options.duration, + easing: options.easing + }, callback); + } else { + this.setResolution(resolution); + this.setCenter(center); + animationCallback(callback, true); + } + }; + + /** + * Center on coordinate and view position. + * @param {import("./coordinate.js").Coordinate} coordinate Coordinate. + * @param {import("./size.js").Size} size Box pixel size. + * @param {import("./pixel.js").Pixel} position Position on the view to center on. + * @api + */ + View.prototype.centerOn = function centerOn (coordinate, size, position) { + // calculate rotated position + var rotation = this.getRotation(); + var cosAngle = Math.cos(-rotation); + var sinAngle = Math.sin(-rotation); + var rotX = coordinate[0] * cosAngle - coordinate[1] * sinAngle; + var rotY = coordinate[1] * cosAngle + coordinate[0] * sinAngle; + var resolution = this.getResolution(); + rotX += (size[0] / 2 - position[0]) * resolution; + rotY += (position[1] - size[1] / 2) * resolution; + + // go back to original angle + sinAngle = -sinAngle; // go back to original rotation + var centerX = rotX * cosAngle - rotY * sinAngle; + var centerY = rotY * cosAngle + rotX * sinAngle; + + this.setCenter([centerX, centerY]); + }; + + /** + * @return {boolean} Is defined. + */ + View.prototype.isDef = function isDef () { + return !!this.getCenter() && this.getResolution() !== undefined; + }; + + /** + * Rotate the view around a given coordinate. + * @param {number} rotation New rotation value for the view. + * @param {import("./coordinate.js").Coordinate=} opt_anchor The rotation center. + * @api + */ + View.prototype.rotate = function rotate (rotation, opt_anchor) { + if (opt_anchor !== undefined) { + var center = this.calculateCenterRotate(rotation, opt_anchor); + this.setCenter(center); + } + this.setRotation(rotation); + }; + + /** + * Set the center of the current view. + * @param {import("./coordinate.js").Coordinate|undefined} center The center of the view. + * @observable + * @api + */ + View.prototype.setCenter = function setCenter (center) { + this.set(ViewProperty.CENTER, center); + if (this.getAnimating()) { + this.cancelAnimations(); + } + }; + + /** + * @param {ViewHint} hint Hint. + * @param {number} delta Delta. + * @return {number} New value. + */ + View.prototype.setHint = function setHint (hint, delta) { + this.hints_[hint] += delta; + this.changed(); + return this.hints_[hint]; + }; + + /** + * Set the resolution for this view. + * @param {number|undefined} resolution The resolution of the view. + * @observable + * @api + */ + View.prototype.setResolution = function setResolution (resolution) { + this.set(ViewProperty.RESOLUTION, resolution); + if (this.getAnimating()) { + this.cancelAnimations(); + } + }; + + /** + * Set the rotation for this view. + * @param {number} rotation The rotation of the view in radians. + * @observable + * @api + */ + View.prototype.setRotation = function setRotation (rotation) { + this.set(ViewProperty.ROTATION, rotation); + if (this.getAnimating()) { + this.cancelAnimations(); + } + }; + + /** + * Zoom to a specific zoom level. + * @param {number} zoom Zoom level. + * @api + */ + View.prototype.setZoom = function setZoom (zoom) { + this.setResolution(this.getResolutionForZoom(zoom)); + }; + + return View; +}(ol_Object)); + + +/** + * @param {Function} callback Callback. + * @param {*} returnValue Return value. + */ +function animationCallback(callback, returnValue) { + setTimeout(function() { + callback(returnValue); + }, 0); +} + + +/** + * @param {ViewOptions} options View options. + * @return {import("./centerconstraint.js").Type} The constraint. + */ +function createCenterConstraint(options) { + if (options.extent !== undefined) { + return createExtent(options.extent); + } else { + return none; + } +} + + +/** + * @param {ViewOptions} options View options. + * @return {{constraint: import("./resolutionconstraint.js").Type, maxResolution: number, + * minResolution: number, minZoom: number, zoomFactor: number}} The constraint. + */ +function createResolutionConstraint(options) { + var resolutionConstraint; + var maxResolution; + var minResolution; + + // TODO: move these to be ol constants + // see https://github.com/openlayers/openlayers/issues/2076 + var defaultMaxZoom = 28; + var defaultZoomFactor = 2; + + var minZoom = options.minZoom !== undefined ? + options.minZoom : DEFAULT_MIN_ZOOM; + + var maxZoom = options.maxZoom !== undefined ? + options.maxZoom : defaultMaxZoom; + + var zoomFactor = options.zoomFactor !== undefined ? + options.zoomFactor : defaultZoomFactor; + + if (options.resolutions !== undefined) { + var resolutions = options.resolutions; + maxResolution = resolutions[minZoom]; + minResolution = resolutions[maxZoom] !== undefined ? + resolutions[maxZoom] : resolutions[resolutions.length - 1]; + resolutionConstraint = createSnapToResolutions( + resolutions); + } else { + // calculate the default min and max resolution + var projection = createProjection(options.projection, 'EPSG:3857'); + var extent = projection.getExtent(); + var size = !extent ? + // use an extent that can fit the whole world if need be + 360 * METERS_PER_UNIT[proj_Units.DEGREES] / + projection.getMetersPerUnit() : + Math.max(getWidth(extent), getHeight(extent)); + + var defaultMaxResolution = size / DEFAULT_TILE_SIZE / Math.pow( + defaultZoomFactor, DEFAULT_MIN_ZOOM); + + var defaultMinResolution = defaultMaxResolution / Math.pow( + defaultZoomFactor, defaultMaxZoom - DEFAULT_MIN_ZOOM); + + // user provided maxResolution takes precedence + maxResolution = options.maxResolution; + if (maxResolution !== undefined) { + minZoom = 0; + } else { + maxResolution = defaultMaxResolution / Math.pow(zoomFactor, minZoom); + } + + // user provided minResolution takes precedence + minResolution = options.minResolution; + if (minResolution === undefined) { + if (options.maxZoom !== undefined) { + if (options.maxResolution !== undefined) { + minResolution = maxResolution / Math.pow(zoomFactor, maxZoom); + } else { + minResolution = defaultMaxResolution / Math.pow(zoomFactor, maxZoom); + } + } else { + minResolution = defaultMinResolution; + } + } + + // given discrete zoom levels, minResolution may be different than provided + maxZoom = minZoom + Math.floor( + Math.log(maxResolution / minResolution) / Math.log(zoomFactor)); + minResolution = maxResolution / Math.pow(zoomFactor, maxZoom - minZoom); + + resolutionConstraint = createSnapToPower( + zoomFactor, maxResolution, maxZoom - minZoom); + } + return {constraint: resolutionConstraint, maxResolution: maxResolution, + minResolution: minResolution, minZoom: minZoom, zoomFactor: zoomFactor}; +} + + +/** + * @param {ViewOptions} options View options. + * @return {import("./rotationconstraint.js").Type} Rotation constraint. + */ +function createRotationConstraint(options) { + var enableRotation = options.enableRotation !== undefined ? + options.enableRotation : true; + if (enableRotation) { + var constrainRotation = options.constrainRotation; + if (constrainRotation === undefined || constrainRotation === true) { + return createSnapToZero(); + } else if (constrainRotation === false) { + return rotationconstraint_none; + } else if (typeof constrainRotation === 'number') { + return createSnapToN(constrainRotation); + } else { + return rotationconstraint_none; + } + } else { + return disable; + } +} + + +/** + * Determine if an animation involves no view change. + * @param {Animation} animation The animation. + * @return {boolean} The animation involves no view change. + */ +function isNoopAnimation(animation) { + if (animation.sourceCenter && animation.targetCenter) { + if (!coordinate_equals(animation.sourceCenter, animation.targetCenter)) { + return false; + } + } + if (animation.sourceResolution !== animation.targetResolution) { + return false; + } + if (animation.sourceRotation !== animation.targetRotation) { + return false; + } + return true; +} + +/* harmony default export */ var ol_View = (View_View); + +//# sourceMappingURL=View.js.map +// CONCATENATED MODULE: ./node_modules/ol/dom.js +/** + * @module ol/dom + */ + + +/** + * Create an html canvas element and returns its 2d context. + * @param {number=} opt_width Canvas width. + * @param {number=} opt_height Canvas height. + * @return {CanvasRenderingContext2D} The context. + */ +function createCanvasContext2D(opt_width, opt_height) { + var canvas = /** @type {HTMLCanvasElement} */ (document.createElement('canvas')); + if (opt_width) { + canvas.width = opt_width; + } + if (opt_height) { + canvas.height = opt_height; + } + return /** @type {CanvasRenderingContext2D} */ (canvas.getContext('2d')); +} + + +/** + * Get the current computed width for the given element including margin, + * padding and border. + * Equivalent to jQuery's `$(el).outerWidth(true)`. + * @param {!HTMLElement} element Element. + * @return {number} The width. + */ +function dom_outerWidth(element) { + var width = element.offsetWidth; + var style = getComputedStyle(element); + width += parseInt(style.marginLeft, 10) + parseInt(style.marginRight, 10); + + return width; +} + + +/** + * Get the current computed height for the given element including margin, + * padding and border. + * Equivalent to jQuery's `$(el).outerHeight(true)`. + * @param {!HTMLElement} element Element. + * @return {number} The height. + */ +function dom_outerHeight(element) { + var height = element.offsetHeight; + var style = getComputedStyle(element); + height += parseInt(style.marginTop, 10) + parseInt(style.marginBottom, 10); + + return height; +} + +/** + * @param {Node} newNode Node to replace old node + * @param {Node} oldNode The node to be replaced + */ +function replaceNode(newNode, oldNode) { + var parent = oldNode.parentNode; + if (parent) { + parent.replaceChild(newNode, oldNode); + } +} + +/** + * @param {Node} node The node to remove. + * @returns {Node} The node that was removed or null. + */ +function removeNode(node) { + return node && node.parentNode ? node.parentNode.removeChild(node) : null; +} + +/** + * @param {Node} node The node to remove the children from. + */ +function removeChildren(node) { + while (node.lastChild) { + node.removeChild(node.lastChild); + } +} + +//# sourceMappingURL=dom.js.map +// CONCATENATED MODULE: ./node_modules/ol/layer/Property.js +/** + * @module ol/layer/Property + */ + +/** + * @enum {string} + */ +/* harmony default export */ var layer_Property = ({ + OPACITY: 'opacity', + VISIBLE: 'visible', + EXTENT: 'extent', + Z_INDEX: 'zIndex', + MAX_RESOLUTION: 'maxResolution', + MIN_RESOLUTION: 'minResolution', + SOURCE: 'source' +}); + +//# sourceMappingURL=Property.js.map +// CONCATENATED MODULE: ./node_modules/ol/layer/Base.js +/** + * @module ol/layer/Base + */ + + + + + + + +/** + * @typedef {Object} Options + * @property {number} [opacity=1] Opacity (0, 1). + * @property {boolean} [visible=true] Visibility. + * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be + * rendered outside of this extent. + * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers + * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed + * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()` + * method was used. + * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be + * visible. + * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will + * be visible. + */ + + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * Note that with {@link module:ol/layer/Base} and all its subclasses, any property set in + * the options is set as a {@link module:ol/Object} property on the layer object, so + * is observable, and has get/set accessors. + * + * @api + */ +var Base_BaseLayer = /*@__PURE__*/(function (BaseObject) { + function BaseLayer(options) { + + BaseObject.call(this); + + /** + * @type {Object} + */ + var properties = obj_assign({}, options); + properties[layer_Property.OPACITY] = + options.opacity !== undefined ? options.opacity : 1; + properties[layer_Property.VISIBLE] = + options.visible !== undefined ? options.visible : true; + properties[layer_Property.Z_INDEX] = options.zIndex; + properties[layer_Property.MAX_RESOLUTION] = + options.maxResolution !== undefined ? options.maxResolution : Infinity; + properties[layer_Property.MIN_RESOLUTION] = + options.minResolution !== undefined ? options.minResolution : 0; + + this.setProperties(properties); + + /** + * @type {import("./Layer.js").State} + * @private + */ + this.state_ = null; + + /** + * The layer type. + * @type {import("../LayerType.js").default} + * @protected; + */ + this.type; + + } + + if ( BaseObject ) BaseLayer.__proto__ = BaseObject; + BaseLayer.prototype = Object.create( BaseObject && BaseObject.prototype ); + BaseLayer.prototype.constructor = BaseLayer; + + /** + * Get the layer type (used when creating a layer renderer). + * @return {import("../LayerType.js").default} The layer type. + */ + BaseLayer.prototype.getType = function getType () { + return this.type; + }; + + /** + * @return {import("./Layer.js").State} Layer state. + */ + BaseLayer.prototype.getLayerState = function getLayerState () { + /** @type {import("./Layer.js").State} */ + var state = this.state_ || /** @type {?} */ ({ + layer: this, + managed: true + }); + state.opacity = clamp(this.getOpacity(), 0, 1); + state.sourceState = this.getSourceState(); + state.visible = this.getVisible(); + state.extent = this.getExtent(); + state.zIndex = this.getZIndex() || 0; + state.maxResolution = this.getMaxResolution(); + state.minResolution = Math.max(this.getMinResolution(), 0); + this.state_ = state; + + return state; + }; + + /** + * @abstract + * @param {Array=} opt_array Array of layers (to be + * modified in place). + * @return {Array} Array of layers. + */ + BaseLayer.prototype.getLayersArray = function getLayersArray (opt_array) { + return util_abstract(); + }; + + /** + * @abstract + * @param {Array=} opt_states Optional list of layer + * states (to be modified in place). + * @return {Array} List of layer states. + */ + BaseLayer.prototype.getLayerStatesArray = function getLayerStatesArray (opt_states) { + return util_abstract(); + }; + + /** + * Return the {@link module:ol/extent~Extent extent} of the layer or `undefined` if it + * will be visible regardless of extent. + * @return {import("../extent.js").Extent|undefined} The layer extent. + * @observable + * @api + */ + BaseLayer.prototype.getExtent = function getExtent () { + return ( + /** @type {import("../extent.js").Extent|undefined} */ (this.get(layer_Property.EXTENT)) + ); + }; + + /** + * Return the maximum resolution of the layer. + * @return {number} The maximum resolution of the layer. + * @observable + * @api + */ + BaseLayer.prototype.getMaxResolution = function getMaxResolution () { + return /** @type {number} */ (this.get(layer_Property.MAX_RESOLUTION)); + }; + + /** + * Return the minimum resolution of the layer. + * @return {number} The minimum resolution of the layer. + * @observable + * @api + */ + BaseLayer.prototype.getMinResolution = function getMinResolution () { + return /** @type {number} */ (this.get(layer_Property.MIN_RESOLUTION)); + }; + + /** + * Return the opacity of the layer (between 0 and 1). + * @return {number} The opacity of the layer. + * @observable + * @api + */ + BaseLayer.prototype.getOpacity = function getOpacity () { + return /** @type {number} */ (this.get(layer_Property.OPACITY)); + }; + + /** + * @abstract + * @return {import("../source/State.js").default} Source state. + */ + BaseLayer.prototype.getSourceState = function getSourceState () { + return util_abstract(); + }; + + /** + * Return the visibility of the layer (`true` or `false`). + * @return {boolean} The visibility of the layer. + * @observable + * @api + */ + BaseLayer.prototype.getVisible = function getVisible () { + return /** @type {boolean} */ (this.get(layer_Property.VISIBLE)); + }; + + /** + * Return the Z-index of the layer, which is used to order layers before + * rendering. The default Z-index is 0. + * @return {number} The Z-index of the layer. + * @observable + * @api + */ + BaseLayer.prototype.getZIndex = function getZIndex () { + return /** @type {number} */ (this.get(layer_Property.Z_INDEX)); + }; + + /** + * Set the extent at which the layer is visible. If `undefined`, the layer + * will be visible at all extents. + * @param {import("../extent.js").Extent|undefined} extent The extent of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setExtent = function setExtent (extent) { + this.set(layer_Property.EXTENT, extent); + }; + + /** + * Set the maximum resolution at which the layer is visible. + * @param {number} maxResolution The maximum resolution of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setMaxResolution = function setMaxResolution (maxResolution) { + this.set(layer_Property.MAX_RESOLUTION, maxResolution); + }; + + /** + * Set the minimum resolution at which the layer is visible. + * @param {number} minResolution The minimum resolution of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setMinResolution = function setMinResolution (minResolution) { + this.set(layer_Property.MIN_RESOLUTION, minResolution); + }; + + /** + * Set the opacity of the layer, allowed values range from 0 to 1. + * @param {number} opacity The opacity of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setOpacity = function setOpacity (opacity) { + this.set(layer_Property.OPACITY, opacity); + }; + + /** + * Set the visibility of the layer (`true` or `false`). + * @param {boolean} visible The visibility of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setVisible = function setVisible (visible) { + this.set(layer_Property.VISIBLE, visible); + }; + + /** + * Set Z-index of the layer, which is used to order layers before rendering. + * The default Z-index is 0. + * @param {number} zindex The z-index of the layer. + * @observable + * @api + */ + BaseLayer.prototype.setZIndex = function setZIndex (zindex) { + this.set(layer_Property.Z_INDEX, zindex); + }; + + return BaseLayer; +}(ol_Object)); + + +/* harmony default export */ var Base = (Base_BaseLayer); + +//# sourceMappingURL=Base.js.map +// CONCATENATED MODULE: ./node_modules/ol/source/State.js +/** + * @module ol/source/State + */ + +/** + * @enum {string} + * State of the source, one of 'undefined', 'loading', 'ready' or 'error'. + */ +/* harmony default export */ var State = ({ + UNDEFINED: 'undefined', + LOADING: 'loading', + READY: 'ready', + ERROR: 'error' +}); + +//# sourceMappingURL=State.js.map +// CONCATENATED MODULE: ./node_modules/ol/layer/Group.js +/** + * @module ol/layer/Group + */ + + + + + + + + + + + + + + +/** + * @typedef {Object} Options + * @property {number} [opacity=1] Opacity (0, 1). + * @property {boolean} [visible=true] Visibility. + * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be + * rendered outside of this extent. + * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers + * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed + * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()` + * method was used. + * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be + * visible. + * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will + * be visible. + * @property {Array|import("../Collection.js").default} [layers] Child layers. + */ + + +/** + * @enum {string} + * @private + */ +var Group_Property = { + LAYERS: 'layers' +}; + + +/** + * @classdesc + * A {@link module:ol/Collection~Collection} of layers that are handled together. + * + * A generic `change` event is triggered when the group/Collection changes. + * + * @api + */ +var Group_LayerGroup = /*@__PURE__*/(function (BaseLayer) { + function LayerGroup(opt_options) { + + var options = opt_options || {}; + var baseOptions = /** @type {Options} */ (obj_assign({}, options)); + delete baseOptions.layers; + + var layers = options.layers; + + BaseLayer.call(this, baseOptions); + + /** + * @private + * @type {Array} + */ + this.layersListenerKeys_ = []; + + /** + * @private + * @type {Object>} + */ + this.listenerKeys_ = {}; + + listen(this, + getChangeEventType(Group_Property.LAYERS), + this.handleLayersChanged_, this); + + if (layers) { + if (Array.isArray(layers)) { + layers = new ol_Collection(layers.slice(), {unique: true}); + } else { + assert(typeof /** @type {?} */ (layers).getArray === 'function', + 43); // Expected `layers` to be an array or a `Collection` + } + } else { + layers = new ol_Collection(undefined, {unique: true}); + } + + this.setLayers(layers); + + } + + if ( BaseLayer ) LayerGroup.__proto__ = BaseLayer; + LayerGroup.prototype = Object.create( BaseLayer && BaseLayer.prototype ); + LayerGroup.prototype.constructor = LayerGroup; + + /** + * @private + */ + LayerGroup.prototype.handleLayerChange_ = function handleLayerChange_ () { + this.changed(); + }; + + /** + * @private + */ + LayerGroup.prototype.handleLayersChanged_ = function handleLayersChanged_ () { + this.layersListenerKeys_.forEach(unlistenByKey); + this.layersListenerKeys_.length = 0; + + var layers = this.getLayers(); + this.layersListenerKeys_.push( + listen(layers, CollectionEventType.ADD, this.handleLayersAdd_, this), + listen(layers, CollectionEventType.REMOVE, this.handleLayersRemove_, this) + ); + + for (var id in this.listenerKeys_) { + this.listenerKeys_[id].forEach(unlistenByKey); + } + obj_clear(this.listenerKeys_); + + var layersArray = layers.getArray(); + for (var i = 0, ii = layersArray.length; i < ii; i++) { + var layer = layersArray[i]; + this.listenerKeys_[getUid(layer)] = [ + listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this), + listen(layer, EventType.CHANGE, this.handleLayerChange_, this) + ]; + } + + this.changed(); + }; + + /** + * @param {import("../Collection.js").CollectionEvent} collectionEvent CollectionEvent. + * @private + */ + LayerGroup.prototype.handleLayersAdd_ = function handleLayersAdd_ (collectionEvent) { + var layer = /** @type {import("./Base.js").default} */ (collectionEvent.element); + this.listenerKeys_[getUid(layer)] = [ + listen(layer, ObjectEventType.PROPERTYCHANGE, this.handleLayerChange_, this), + listen(layer, EventType.CHANGE, this.handleLayerChange_, this) + ]; + this.changed(); + }; + + /** + * @param {import("../Collection.js").CollectionEvent} collectionEvent CollectionEvent. + * @private + */ + LayerGroup.prototype.handleLayersRemove_ = function handleLayersRemove_ (collectionEvent) { + var layer = /** @type {import("./Base.js").default} */ (collectionEvent.element); + var key = getUid(layer); + this.listenerKeys_[key].forEach(unlistenByKey); + delete this.listenerKeys_[key]; + this.changed(); + }; + + /** + * Returns the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers} + * in this group. + * @return {!import("../Collection.js").default} Collection of + * {@link module:ol/layer/Base layers} that are part of this group. + * @observable + * @api + */ + LayerGroup.prototype.getLayers = function getLayers () { + return ( + /** @type {!import("../Collection.js").default} */ (this.get(Group_Property.LAYERS)) + ); + }; + + /** + * Set the {@link module:ol/Collection collection} of {@link module:ol/layer/Layer~Layer layers} + * in this group. + * @param {!import("../Collection.js").default} layers Collection of + * {@link module:ol/layer/Base layers} that are part of this group. + * @observable + * @api + */ + LayerGroup.prototype.setLayers = function setLayers (layers) { + this.set(Group_Property.LAYERS, layers); + }; + + /** + * @inheritDoc + */ + LayerGroup.prototype.getLayersArray = function getLayersArray (opt_array) { + var array = opt_array !== undefined ? opt_array : []; + this.getLayers().forEach(function(layer) { + layer.getLayersArray(array); + }); + return array; + }; + + /** + * @inheritDoc + */ + LayerGroup.prototype.getLayerStatesArray = function getLayerStatesArray (opt_states) { + var states = opt_states !== undefined ? opt_states : []; + + var pos = states.length; + + this.getLayers().forEach(function(layer) { + layer.getLayerStatesArray(states); + }); + + var ownLayerState = this.getLayerState(); + for (var i = pos, ii = states.length; i < ii; i++) { + var layerState = states[i]; + layerState.opacity *= ownLayerState.opacity; + layerState.visible = layerState.visible && ownLayerState.visible; + layerState.maxResolution = Math.min( + layerState.maxResolution, ownLayerState.maxResolution); + layerState.minResolution = Math.max( + layerState.minResolution, ownLayerState.minResolution); + if (ownLayerState.extent !== undefined) { + if (layerState.extent !== undefined) { + layerState.extent = getIntersection(layerState.extent, ownLayerState.extent); + } else { + layerState.extent = ownLayerState.extent; + } + } + } + + return states; + }; + + /** + * @inheritDoc + */ + LayerGroup.prototype.getSourceState = function getSourceState () { + return State.READY; + }; + + return LayerGroup; +}(Base)); + + +/* harmony default export */ var Group = (Group_LayerGroup); + +//# sourceMappingURL=Group.js.map +// CONCATENATED MODULE: ./node_modules/ol/size.js +/** + * @module ol/size + */ + + +/** + * An array of numbers representing a size: `[width, height]`. + * @typedef {Array} Size + * @api + */ + + +/** + * Returns a buffered size. + * @param {Size} size Size. + * @param {number} num The amount by which to buffer. + * @param {Size=} opt_size Optional reusable size array. + * @return {Size} The buffered size. + */ +function size_buffer(size, num, opt_size) { + if (opt_size === undefined) { + opt_size = [0, 0]; + } + opt_size[0] = size[0] + 2 * num; + opt_size[1] = size[1] + 2 * num; + return opt_size; +} + + +/** + * Determines if a size has a positive area. + * @param {Size} size The size to test. + * @return {boolean} The size has a positive area. + */ +function hasArea(size) { + return size[0] > 0 && size[1] > 0; +} + + +/** + * Returns a size scaled by a ratio. The result will be an array of integers. + * @param {Size} size Size. + * @param {number} ratio Ratio. + * @param {Size=} opt_size Optional reusable size array. + * @return {Size} The scaled size. + */ +function size_scale(size, ratio, opt_size) { + if (opt_size === undefined) { + opt_size = [0, 0]; + } + opt_size[0] = (size[0] * ratio + 0.5) | 0; + opt_size[1] = (size[1] * ratio + 0.5) | 0; + return opt_size; +} + + +/** + * Returns an `Size` array for the passed in number (meaning: square) or + * `Size` array. + * (meaning: non-square), + * @param {number|Size} size Width and height. + * @param {Size=} opt_size Optional reusable size array. + * @return {Size} Size. + * @api + */ +function toSize(size, opt_size) { + if (Array.isArray(size)) { + return size; + } else { + if (opt_size === undefined) { + opt_size = [size, size]; + } else { + opt_size[0] = opt_size[1] = /** @type {number} */ (size); + } + return opt_size; + } +} + +//# sourceMappingURL=size.js.map +// CONCATENATED MODULE: ./node_modules/ol/PluggableMap.js +/** + * @module ol/PluggableMap + */ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/** + * State of the current frame. Only `pixelRatio`, `time` and `viewState` should + * be used in applications. + * @typedef {Object} FrameState + * @property {number} pixelRatio The pixel ratio of the frame. + * @property {number} time The time when rendering of the frame was requested. + * @property {import("./View.js").State} viewState The state of the current view. + * @property {boolean} animate + * @property {import("./transform.js").Transform} coordinateToPixelTransform + * @property {null|import("./extent.js").Extent} extent + * @property {import("./coordinate.js").Coordinate} focus + * @property {number} index + * @property {Object} layerStates + * @property {Array} layerStatesArray + * @property {import("./transform.js").Transform} pixelToCoordinateTransform + * @property {Array} postRenderFunctions + * @property {import("./size.js").Size} size + * @property {!Object} skippedFeatureUids + * @property {TileQueue} tileQueue + * @property {Object>} usedTiles + * @property {Array} viewHints + * @property {!Object>} wantedTiles + */ + + +/** + * @typedef {function(PluggableMap, ?FrameState): boolean} PostRenderFunction + */ + + +/** + * @typedef {Object} AtPixelOptions + * @property {undefined|function(import("./layer/Layer.js").default): boolean} layerFilter Layer filter + * function. The filter function will receive one argument, the + * {@link module:ol/layer/Layer layer-candidate} and it should return a boolean value. + * Only layers which are visible and for which this function returns `true` + * will be tested for features. By default, all visible layers will be tested. + * @property {number} [hitTolerance=0] Hit-detection tolerance in pixels. Pixels + * inside the radius around the given position will be checked for features. This only + * works for the canvas renderer and not for WebGL. + */ + + +/** + * @typedef {Object} MapOptionsInternal + * @property {Collection} [controls] + * @property {Collection} [interactions] + * @property {HTMLElement|Document} keyboardEventTarget + * @property {Collection} overlays + * @property {Object} values + */ + + +/** + * Object literal with config options for the map. + * @typedef {Object} MapOptions + * @property {Collection|Array} [controls] + * Controls initially added to the map. If not specified, + * {@link module:ol/control~defaults} is used. + * @property {number} [pixelRatio=window.devicePixelRatio] The ratio between + * physical pixels and device-independent pixels (dips) on the device. + * @property {Collection|Array} [interactions] + * Interactions that are initially added to the map. If not specified, + * {@link module:ol/interaction~defaults} is used. + * @property {HTMLElement|Document|string} [keyboardEventTarget] The element to + * listen to keyboard events on. This determines when the `KeyboardPan` and + * `KeyboardZoom` interactions trigger. For example, if this option is set to + * `document` the keyboard interactions will always trigger. If this option is + * not specified, the element the library listens to keyboard events on is the + * map target (i.e. the user-provided div for the map). If this is not + * `document`, the target element needs to be focused for key events to be + * emitted, requiring that the target element has a `tabindex` attribute. + * @property {Array|Collection|LayerGroup} [layers] + * Layers. If this is not defined, a map with no layers will be rendered. Note + * that layers are rendered in the order supplied, so if you want, for example, + * a vector layer to appear on top of a tile layer, it must come after the tile + * layer. + * @property {number} [maxTilesLoading=16] Maximum number tiles to load + * simultaneously. + * @property {boolean} [loadTilesWhileAnimating=false] When set to `true`, tiles + * will be loaded during animations. This may improve the user experience, but + * can also make animations stutter on devices with slow memory. + * @property {boolean} [loadTilesWhileInteracting=false] When set to `true`, + * tiles will be loaded while interacting with the map. This may improve the + * user experience, but can also make map panning and zooming choppy on devices + * with slow memory. + * @property {number} [moveTolerance=1] The minimum distance in pixels the + * cursor must move to be detected as a map move event instead of a click. + * Increasing this value can make it easier to click on the map. + * @property {Collection|Array} [overlays] + * Overlays initially added to the map. By default, no overlays are added. + * @property {HTMLElement|string} [target] The container for the map, either the + * element itself or the `id` of the element. If not specified at construction + * time, {@link module:ol/Map~Map#setTarget} must be called for the map to be + * rendered. + * @property {View} [view] The map's view. No layer sources will be + * fetched unless this is specified at construction time or through + * {@link module:ol/Map~Map#setView}. + */ + + +/** + * @fires import("./MapBrowserEvent.js").MapBrowserEvent + * @fires import("./MapEvent.js").MapEvent + * @fires module:ol/render/Event~RenderEvent#postcompose + * @fires module:ol/render/Event~RenderEvent#precompose + * @fires module:ol/render/Event~RenderEvent#rendercomplete + * @api + */ +var PluggableMap_PluggableMap = /*@__PURE__*/(function (BaseObject) { + function PluggableMap(options) { + + BaseObject.call(this); + + var optionsInternal = createOptionsInternal(options); + + /** + * @type {number} + * @private + */ + this.maxTilesLoading_ = options.maxTilesLoading !== undefined ? options.maxTilesLoading : 16; + + /** + * @type {boolean} + * @private + */ + this.loadTilesWhileAnimating_ = + options.loadTilesWhileAnimating !== undefined ? + options.loadTilesWhileAnimating : false; + + /** + * @type {boolean} + * @private + */ + this.loadTilesWhileInteracting_ = + options.loadTilesWhileInteracting !== undefined ? + options.loadTilesWhileInteracting : false; + + /** + * @private + * @type {number} + */ + this.pixelRatio_ = options.pixelRatio !== undefined ? + options.pixelRatio : DEVICE_PIXEL_RATIO; + + /** + * @private + * @type {number|undefined} + */ + this.animationDelayKey_; + + /** + * @private + */ + this.animationDelay_ = function() { + this.animationDelayKey_ = undefined; + this.renderFrame_.call(this, Date.now()); + }.bind(this); + + /** + * @private + * @type {import("./transform.js").Transform} + */ + this.coordinateToPixelTransform_ = create(); + + /** + * @private + * @type {import("./transform.js").Transform} + */ + this.pixelToCoordinateTransform_ = create(); + + /** + * @private + * @type {number} + */ + this.frameIndex_ = 0; + + /** + * @private + * @type {?FrameState} + */ + this.frameState_ = null; + + /** + * The extent at the previous 'moveend' event. + * @private + * @type {import("./extent.js").Extent} + */ + this.previousExtent_ = null; + + /** + * @private + * @type {?import("./events.js").EventsKey} + */ + this.viewPropertyListenerKey_ = null; + + /** + * @private + * @type {?import("./events.js").EventsKey} + */ + this.viewChangeListenerKey_ = null; + + /** + * @private + * @type {Array} + */ + this.layerGroupPropertyListenerKeys_ = null; + + /** + * @private + * @type {!HTMLElement} + */ + this.viewport_ = document.createElement('div'); + this.viewport_.className = 'ol-viewport' + (TOUCH ? ' ol-touch' : ''); + this.viewport_.style.position = 'relative'; + this.viewport_.style.overflow = 'hidden'; + this.viewport_.style.width = '100%'; + this.viewport_.style.height = '100%'; + // prevent page zoom on IE >= 10 browsers + this.viewport_.style.msTouchAction = 'none'; + this.viewport_.style.touchAction = 'none'; + + /** + * @private + * @type {!HTMLElement} + */ + this.overlayContainer_ = document.createElement('div'); + this.overlayContainer_.className = 'ol-overlaycontainer'; + this.viewport_.appendChild(this.overlayContainer_); + + /** + * @private + * @type {!HTMLElement} + */ + this.overlayContainerStopEvent_ = document.createElement('div'); + this.overlayContainerStopEvent_.className = 'ol-overlaycontainer-stopevent'; + var overlayEvents = [ + EventType.CLICK, + EventType.DBLCLICK, + EventType.MOUSEDOWN, + EventType.TOUCHSTART, + EventType.MSPOINTERDOWN, + MapBrowserEventType.POINTERDOWN, + EventType.MOUSEWHEEL, + EventType.WHEEL + ]; + for (var i = 0, ii = overlayEvents.length; i < ii; ++i) { + listen(this.overlayContainerStopEvent_, overlayEvents[i], stopPropagation); + } + this.viewport_.appendChild(this.overlayContainerStopEvent_); + + /** + * @private + * @type {MapBrowserEventHandler} + */ + this.mapBrowserEventHandler_ = new ol_MapBrowserEventHandler(this, options.moveTolerance); + for (var key in MapBrowserEventType) { + listen(this.mapBrowserEventHandler_, MapBrowserEventType[key], + this.handleMapBrowserEvent, this); + } + + /** + * @private + * @type {HTMLElement|Document} + */ + this.keyboardEventTarget_ = optionsInternal.keyboardEventTarget; + + /** + * @private + * @type {Array} + */ + this.keyHandlerKeys_ = null; + + listen(this.viewport_, EventType.CONTEXTMENU, this.handleBrowserEvent, this); + listen(this.viewport_, EventType.WHEEL, this.handleBrowserEvent, this); + listen(this.viewport_, EventType.MOUSEWHEEL, this.handleBrowserEvent, this); + + /** + * @type {Collection} + * @protected + */ + this.controls = optionsInternal.controls || new ol_Collection(); + + /** + * @type {Collection} + * @protected + */ + this.interactions = optionsInternal.interactions || new ol_Collection(); + + /** + * @type {Collection} + * @private + */ + this.overlays_ = optionsInternal.overlays; + + /** + * A lookup of overlays by id. + * @private + * @type {Object} + */ + this.overlayIdIndex_ = {}; + + /** + * @type {import("./renderer/Map.js").default} + * @private + */ + this.renderer_ = this.createRenderer(); + + /** + * @type {function(Event)|undefined} + * @private + */ + this.handleResize_; + + /** + * @private + * @type {import("./coordinate.js").Coordinate} + */ + this.focus_ = null; + + /** + * @private + * @type {!Array} + */ + this.postRenderFunctions_ = []; + + /** + * @private + * @type {TileQueue} + */ + this.tileQueue_ = new ol_TileQueue( + this.getTilePriority.bind(this), + this.handleTileChange_.bind(this)); + + /** + * Uids of features to skip at rendering time. + * @type {Object} + * @private + */ + this.skippedFeatureUids_ = {}; + + listen( + this, getChangeEventType(MapProperty.LAYERGROUP), + this.handleLayerGroupChanged_, this); + listen(this, getChangeEventType(MapProperty.VIEW), + this.handleViewChanged_, this); + listen(this, getChangeEventType(MapProperty.SIZE), + this.handleSizeChanged_, this); + listen(this, getChangeEventType(MapProperty.TARGET), + this.handleTargetChanged_, this); + + // setProperties will trigger the rendering of the map if the map + // is "defined" already. + this.setProperties(optionsInternal.values); + + this.controls.forEach( + /** + * @param {import("./control/Control.js").default} control Control. + * @this {PluggableMap} + */ + (function(control) { + control.setMap(this); + }).bind(this)); + + listen(this.controls, CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + event.element.setMap(this); + }, this); + + listen(this.controls, CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + event.element.setMap(null); + }, this); + + this.interactions.forEach( + /** + * @param {import("./interaction/Interaction.js").default} interaction Interaction. + * @this {PluggableMap} + */ + (function(interaction) { + interaction.setMap(this); + }).bind(this)); + + listen(this.interactions, CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + event.element.setMap(this); + }, this); + + listen(this.interactions, CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + event.element.setMap(null); + }, this); + + this.overlays_.forEach(this.addOverlayInternal_.bind(this)); + + listen(this.overlays_, CollectionEventType.ADD, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + this.addOverlayInternal_(/** @type {import("./Overlay.js").default} */ (event.element)); + }, this); + + listen(this.overlays_, CollectionEventType.REMOVE, + /** + * @param {import("./Collection.js").CollectionEvent} event CollectionEvent. + */ + function(event) { + var overlay = /** @type {import("./Overlay.js").default} */ (event.element); + var id = overlay.getId(); + if (id !== undefined) { + delete this.overlayIdIndex_[id.toString()]; + } + event.element.setMap(null); + }, this); + + } + + if ( BaseObject ) PluggableMap.__proto__ = BaseObject; + PluggableMap.prototype = Object.create( BaseObject && BaseObject.prototype ); + PluggableMap.prototype.constructor = PluggableMap; + + /** + * @abstract + * @return {import("./renderer/Map.js").default} The map renderer + */ + PluggableMap.prototype.createRenderer = function createRenderer () { + throw new Error('Use a map type that has a createRenderer method'); + }; + + /** + * Add the given control to the map. + * @param {import("./control/Control.js").default} control Control. + * @api + */ + PluggableMap.prototype.addControl = function addControl (control) { + this.getControls().push(control); + }; + + /** + * Add the given interaction to the map. + * @param {import("./interaction/Interaction.js").default} interaction Interaction to add. + * @api + */ + PluggableMap.prototype.addInteraction = function addInteraction (interaction) { + this.getInteractions().push(interaction); + }; + + /** + * Adds the given layer to the top of this map. If you want to add a layer + * elsewhere in the stack, use `getLayers()` and the methods available on + * {@link module:ol/Collection~Collection}. + * @param {import("./layer/Base.js").default} layer Layer. + * @api + */ + PluggableMap.prototype.addLayer = function addLayer (layer) { + var layers = this.getLayerGroup().getLayers(); + layers.push(layer); + }; + + /** + * Add the given overlay to the map. + * @param {import("./Overlay.js").default} overlay Overlay. + * @api + */ + PluggableMap.prototype.addOverlay = function addOverlay (overlay) { + this.getOverlays().push(overlay); + }; + + /** + * This deals with map's overlay collection changes. + * @param {import("./Overlay.js").default} overlay Overlay. + * @private + */ + PluggableMap.prototype.addOverlayInternal_ = function addOverlayInternal_ (overlay) { + var id = overlay.getId(); + if (id !== undefined) { + this.overlayIdIndex_[id.toString()] = overlay; + } + overlay.setMap(this); + }; + + /** + * + * @inheritDoc + */ + PluggableMap.prototype.disposeInternal = function disposeInternal () { + this.mapBrowserEventHandler_.dispose(); + unlisten(this.viewport_, EventType.CONTEXTMENU, this.handleBrowserEvent, this); + unlisten(this.viewport_, EventType.WHEEL, this.handleBrowserEvent, this); + unlisten(this.viewport_, EventType.MOUSEWHEEL, this.handleBrowserEvent, this); + if (this.handleResize_ !== undefined) { + removeEventListener(EventType.RESIZE, this.handleResize_, false); + this.handleResize_ = undefined; + } + if (this.animationDelayKey_) { + cancelAnimationFrame(this.animationDelayKey_); + this.animationDelayKey_ = undefined; + } + this.setTarget(null); + BaseObject.prototype.disposeInternal.call(this); + }; + + /** + * Detect features that intersect a pixel on the viewport, and execute a + * callback with each intersecting feature. Layers included in the detection can + * be configured through the `layerFilter` option in `opt_options`. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {function(this: S, import("./Feature.js").FeatureLike, + * import("./layer/Layer.js").default): T} callback Feature callback. The callback will be + * called with two arguments. The first argument is one + * {@link module:ol/Feature feature} or + * {@link module:ol/render/Feature render feature} at the pixel, the second is + * the {@link module:ol/layer/Layer layer} of the feature and will be null for + * unmanaged layers. To stop detection, callback functions can return a + * truthy value. + * @param {AtPixelOptions=} opt_options Optional options. + * @return {T|undefined} Callback result, i.e. the return value of last + * callback execution, or the first truthy callback return value. + * @template S,T + * @api + */ + PluggableMap.prototype.forEachFeatureAtPixel = function forEachFeatureAtPixel (pixel, callback, opt_options) { + if (!this.frameState_) { + return; + } + var coordinate = this.getCoordinateFromPixel(pixel); + opt_options = opt_options !== undefined ? opt_options : + /** @type {AtPixelOptions} */ ({}); + var hitTolerance = opt_options.hitTolerance !== undefined ? + opt_options.hitTolerance * this.frameState_.pixelRatio : 0; + var layerFilter = opt_options.layerFilter !== undefined ? + opt_options.layerFilter : TRUE; + return this.renderer_.forEachFeatureAtCoordinate( + coordinate, this.frameState_, hitTolerance, callback, null, + layerFilter, null); + }; + + /** + * Get all features that intersect a pixel on the viewport. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {AtPixelOptions=} opt_options Optional options. + * @return {Array} The detected features or + * `null` if none were found. + * @api + */ + PluggableMap.prototype.getFeaturesAtPixel = function getFeaturesAtPixel (pixel, opt_options) { + var features = null; + this.forEachFeatureAtPixel(pixel, function(feature) { + if (!features) { + features = []; + } + features.push(feature); + }, opt_options); + return features; + }; + + /** + * Detect layers that have a color value at a pixel on the viewport, and + * execute a callback with each matching layer. Layers included in the + * detection can be configured through `opt_layerFilter`. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {function(this: S, import("./layer/Layer.js").default, (Uint8ClampedArray|Uint8Array)): T} callback + * Layer callback. This callback will receive two arguments: first is the + * {@link module:ol/layer/Layer layer}, second argument is an array representing + * [R, G, B, A] pixel values (0 - 255) and will be `null` for layer types + * that do not currently support this argument. To stop detection, callback + * functions can return a truthy value. + * @param {AtPixelOptions=} opt_options Configuration options. + * @return {T|undefined} Callback result, i.e. the return value of last + * callback execution, or the first truthy callback return value. + * @template S,T + * @api + */ + PluggableMap.prototype.forEachLayerAtPixel = function forEachLayerAtPixel (pixel, callback, opt_options) { + if (!this.frameState_) { + return; + } + var options = opt_options || /** @type {AtPixelOptions} */ ({}); + var hitTolerance = options.hitTolerance !== undefined ? + opt_options.hitTolerance * this.frameState_.pixelRatio : 0; + var layerFilter = options.layerFilter || TRUE; + return this.renderer_.forEachLayerAtPixel( + pixel, this.frameState_, hitTolerance, callback, null, layerFilter, null); + }; + + /** + * Detect if features intersect a pixel on the viewport. Layers included in the + * detection can be configured through `opt_layerFilter`. + * @param {import("./pixel.js").Pixel} pixel Pixel. + * @param {AtPixelOptions=} opt_options Optional options. + * @return {boolean} Is there a feature at the given pixel? + * @template U + * @api + */ + PluggableMap.prototype.hasFeatureAtPixel = function hasFeatureAtPixel (pixel, opt_options) { + if (!this.frameState_) { + return false; + } + var coordinate = this.getCoordinateFromPixel(pixel); + opt_options = opt_options !== undefined ? opt_options : + /** @type {AtPixelOptions} */ ({}); + var layerFilter = opt_options.layerFilter !== undefined ? opt_options.layerFilter : TRUE; + var hitTolerance = opt_options.hitTolerance !== undefined ? + opt_options.hitTolerance * this.frameState_.pixelRatio : 0; + return this.renderer_.hasFeatureAtCoordinate( + coordinate, this.frameState_, hitTolerance, layerFilter, null); + }; + + /** + * Returns the coordinate in view projection for a browser event. + * @param {Event} event Event. + * @return {import("./coordinate.js").Coordinate} Coordinate. + * @api + */ + PluggableMap.prototype.getEventCoordinate = function getEventCoordinate (event) { + return this.getCoordinateFromPixel(this.getEventPixel(event)); + }; + + /** + * Returns the map pixel position for a browser event relative to the viewport. + * @param {Event|TouchEvent} event Event. + * @return {import("./pixel.js").Pixel} Pixel. + * @api + */ + PluggableMap.prototype.getEventPixel = function getEventPixel (event) { + var viewportPosition = this.viewport_.getBoundingClientRect(); + var eventPosition = 'changedTouches' in event ? + /** @type {TouchEvent} */ (event).changedTouches[0] : + /** @type {MouseEvent} */ (event); + + return [ + eventPosition.clientX - viewportPosition.left, + eventPosition.clientY - viewportPosition.top + ]; + }; + + /** + * Get the target in which this map is rendered. + * Note that this returns what is entered as an option or in setTarget: + * if that was an element, it returns an element; if a string, it returns that. + * @return {HTMLElement|string|undefined} The Element or id of the Element that the + * map is rendered in. + * @observable + * @api + */ + PluggableMap.prototype.getTarget = function getTarget () { + return /** @type {HTMLElement|string|undefined} */ (this.get(MapProperty.TARGET)); + }; + + /** + * Get the DOM element into which this map is rendered. In contrast to + * `getTarget` this method always return an `Element`, or `null` if the + * map has no target. + * @return {HTMLElement} The element that the map is rendered in. + * @api + */ + PluggableMap.prototype.getTargetElement = function getTargetElement () { + var target = this.getTarget(); + if (target !== undefined) { + return typeof target === 'string' ? document.getElementById(target) : target; + } else { + return null; + } + }; + + /** + * Get the coordinate for a given pixel. This returns a coordinate in the + * map view projection. + * @param {import("./pixel.js").Pixel} pixel Pixel position in the map viewport. + * @return {import("./coordinate.js").Coordinate} The coordinate for the pixel position. + * @api + */ + PluggableMap.prototype.getCoordinateFromPixel = function getCoordinateFromPixel (pixel) { + var frameState = this.frameState_; + if (!frameState) { + return null; + } else { + return apply(frameState.pixelToCoordinateTransform, pixel.slice()); + } + }; + + /** + * Get the map controls. Modifying this collection changes the controls + * associated with the map. + * @return {Collection} Controls. + * @api + */ + PluggableMap.prototype.getControls = function getControls () { + return this.controls; + }; + + /** + * Get the map overlays. Modifying this collection changes the overlays + * associated with the map. + * @return {Collection} Overlays. + * @api + */ + PluggableMap.prototype.getOverlays = function getOverlays () { + return this.overlays_; + }; + + /** + * Get an overlay by its identifier (the value returned by overlay.getId()). + * Note that the index treats string and numeric identifiers as the same. So + * `map.getOverlayById(2)` will return an overlay with id `'2'` or `2`. + * @param {string|number} id Overlay identifier. + * @return {import("./Overlay.js").default} Overlay. + * @api + */ + PluggableMap.prototype.getOverlayById = function getOverlayById (id) { + var overlay = this.overlayIdIndex_[id.toString()]; + return overlay !== undefined ? overlay : null; + }; + + /** + * Get the map interactions. Modifying this collection changes the interactions + * associated with the map. + * + * Interactions are used for e.g. pan, zoom and rotate. + * @return {Collection} Interactions. + * @api + */ + PluggableMap.prototype.getInteractions = function getInteractions () { + return this.interactions; + }; + + /** + * Get the layergroup associated with this map. + * @return {LayerGroup} A layer group containing the layers in this map. + * @observable + * @api + */ + PluggableMap.prototype.getLayerGroup = function getLayerGroup () { + return ( + /** @type {LayerGroup} */ (this.get(MapProperty.LAYERGROUP)) + ); + }; + + /** + * Get the collection of layers associated with this map. + * @return {!Collection} Layers. + * @api + */ + PluggableMap.prototype.getLayers = function getLayers () { + var layers = this.getLayerGroup().getLayers(); + return layers; + }; + + /** + * Get the pixel for a coordinate. This takes a coordinate in the map view + * projection and returns the corresponding pixel. + * @param {import("./coordinate.js").Coordinate} coordinate A map coordinate. + * @return {import("./pixel.js").Pixel} A pixel position in the map viewport. + * @api + */ + PluggableMap.prototype.getPixelFromCoordinate = function getPixelFromCoordinate (coordinate) { + var frameState = this.frameState_; + if (!frameState) { + return null; + } else { + return apply(frameState.coordinateToPixelTransform, coordinate.slice(0, 2)); + } + }; + + /** + * Get the map renderer. + * @return {import("./renderer/Map.js").default} Renderer + */ + PluggableMap.prototype.getRenderer = function getRenderer () { + return this.renderer_; + }; + + /** + * Get the size of this map. + * @return {import("./size.js").Size|undefined} The size in pixels of the map in the DOM. + * @observable + * @api + */ + PluggableMap.prototype.getSize = function getSize () { + return ( + /** @type {import("./size.js").Size|undefined} */ (this.get(MapProperty.SIZE)) + ); + }; + + /** + * Get the view associated with this map. A view manages properties such as + * center and resolution. + * @return {View} The view that controls this map. + * @observable + * @api + */ + PluggableMap.prototype.getView = function getView () { + return ( + /** @type {View} */ (this.get(MapProperty.VIEW)) + ); + }; + + /** + * Get the element that serves as the map viewport. + * @return {HTMLElement} Viewport. + * @api + */ + PluggableMap.prototype.getViewport = function getViewport () { + return this.viewport_; + }; + + /** + * Get the element that serves as the container for overlays. Elements added to + * this container will let mousedown and touchstart events through to the map, + * so clicks and gestures on an overlay will trigger {@link module:ol/MapBrowserEvent~MapBrowserEvent} + * events. + * @return {!HTMLElement} The map's overlay container. + */ + PluggableMap.prototype.getOverlayContainer = function getOverlayContainer () { + return this.overlayContainer_; + }; + + /** + * Get the element that serves as a container for overlays that don't allow + * event propagation. Elements added to this container won't let mousedown and + * touchstart events through to the map, so clicks and gestures on an overlay + * don't trigger any {@link module:ol/MapBrowserEvent~MapBrowserEvent}. + * @return {!HTMLElement} The map's overlay container that stops events. + */ + PluggableMap.prototype.getOverlayContainerStopEvent = function getOverlayContainerStopEvent () { + return this.overlayContainerStopEvent_; + }; + + /** + * @param {import("./Tile.js").default} tile Tile. + * @param {string} tileSourceKey Tile source key. + * @param {import("./coordinate.js").Coordinate} tileCenter Tile center. + * @param {number} tileResolution Tile resolution. + * @return {number} Tile priority. + */ + PluggableMap.prototype.getTilePriority = function getTilePriority (tile, tileSourceKey, tileCenter, tileResolution) { + // Filter out tiles at higher zoom levels than the current zoom level, or that + // are outside the visible extent. + var frameState = this.frameState_; + if (!frameState || !(tileSourceKey in frameState.wantedTiles)) { + return DROP; + } + if (!frameState.wantedTiles[tileSourceKey][tile.getKey()]) { + return DROP; + } + // Prioritize the highest zoom level tiles closest to the focus. + // Tiles at higher zoom levels are prioritized using Math.log(tileResolution). + // Within a zoom level, tiles are prioritized by the distance in pixels + // between the center of the tile and the focus. The factor of 65536 means + // that the prioritization should behave as desired for tiles up to + // 65536 * Math.log(2) = 45426 pixels from the focus. + var deltaX = tileCenter[0] - frameState.focus[0]; + var deltaY = tileCenter[1] - frameState.focus[1]; + return 65536 * Math.log(tileResolution) + + Math.sqrt(deltaX * deltaX + deltaY * deltaY) / tileResolution; + }; + + /** + * @param {Event} browserEvent Browser event. + * @param {string=} opt_type Type. + */ + PluggableMap.prototype.handleBrowserEvent = function handleBrowserEvent (browserEvent, opt_type) { + var type = opt_type || browserEvent.type; + var mapBrowserEvent = new ol_MapBrowserEvent(type, this, browserEvent); + this.handleMapBrowserEvent(mapBrowserEvent); + }; + + /** + * @param {MapBrowserEvent} mapBrowserEvent The event to handle. + */ + PluggableMap.prototype.handleMapBrowserEvent = function handleMapBrowserEvent (mapBrowserEvent) { + if (!this.frameState_) { + // With no view defined, we cannot translate pixels into geographical + // coordinates so interactions cannot be used. + return; + } + this.focus_ = mapBrowserEvent.coordinate; + mapBrowserEvent.frameState = this.frameState_; + var interactionsArray = this.getInteractions().getArray(); + if (this.dispatchEvent(mapBrowserEvent) !== false) { + for (var i = interactionsArray.length - 1; i >= 0; i--) { + var interaction = interactionsArray[i]; + if (!interaction.getActive()) { + continue; + } + var cont = interaction.handleEvent(mapBrowserEvent); + if (!cont) { + break; + } + } + } + }; + + /** + * @protected + */ + PluggableMap.prototype.handlePostRender = function handlePostRender () { + + var frameState = this.frameState_; + + // Manage the tile queue + // Image loads are expensive and a limited resource, so try to use them + // efficiently: + // * When the view is static we allow a large number of parallel tile loads + // to complete the frame as quickly as possible. + // * When animating or interacting, image loads can cause janks, so we reduce + // the maximum number of loads per frame and limit the number of parallel + // tile loads to remain reactive to view changes and to reduce the chance of + // loading tiles that will quickly disappear from view. + var tileQueue = this.tileQueue_; + if (!tileQueue.isEmpty()) { + var maxTotalLoading = this.maxTilesLoading_; + var maxNewLoads = maxTotalLoading; + if (frameState) { + var hints = frameState.viewHints; + if (hints[ViewHint.ANIMATING]) { + maxTotalLoading = this.loadTilesWhileAnimating_ ? 8 : 0; + maxNewLoads = 2; + } + if (hints[ViewHint.INTERACTING]) { + maxTotalLoading = this.loadTilesWhileInteracting_ ? 8 : 0; + maxNewLoads = 2; + } + } + if (tileQueue.getTilesLoading() < maxTotalLoading) { + tileQueue.reprioritize(); // FIXME only call if view has changed + tileQueue.loadMoreTiles(maxTotalLoading, maxNewLoads); + } + } + if (frameState && this.hasListener(render_EventType.RENDERCOMPLETE) && !frameState.animate && + !this.tileQueue_.getTilesLoading() && !getLoading(this.getLayers().getArray())) { + this.renderer_.dispatchRenderEvent(render_EventType.RENDERCOMPLETE, frameState); + } + + var postRenderFunctions = this.postRenderFunctions_; + for (var i = 0, ii = postRenderFunctions.length; i < ii; ++i) { + postRenderFunctions[i](this, frameState); + } + postRenderFunctions.length = 0; + }; + + /** + * @private + */ + PluggableMap.prototype.handleSizeChanged_ = function handleSizeChanged_ () { + this.render(); + }; + + /** + * @private + */ + PluggableMap.prototype.handleTargetChanged_ = function handleTargetChanged_ () { + // target may be undefined, null, a string or an Element. + // If it's a string we convert it to an Element before proceeding. + // If it's not now an Element we remove the viewport from the DOM. + // If it's an Element we append the viewport element to it. + + var targetElement; + if (this.getTarget()) { + targetElement = this.getTargetElement(); + } + + if (this.keyHandlerKeys_) { + for (var i = 0, ii = this.keyHandlerKeys_.length; i < ii; ++i) { + unlistenByKey(this.keyHandlerKeys_[i]); + } + this.keyHandlerKeys_ = null; + } + + if (!targetElement) { + this.renderer_.removeLayerRenderers(); + removeNode(this.viewport_); + if (this.handleResize_ !== undefined) { + removeEventListener(EventType.RESIZE, this.handleResize_, false); + this.handleResize_ = undefined; + } + } else { + targetElement.appendChild(this.viewport_); + + var keyboardEventTarget = !this.keyboardEventTarget_ ? + targetElement : this.keyboardEventTarget_; + this.keyHandlerKeys_ = [ + listen(keyboardEventTarget, EventType.KEYDOWN, this.handleBrowserEvent, this), + listen(keyboardEventTarget, EventType.KEYPRESS, this.handleBrowserEvent, this) + ]; + + if (!this.handleResize_) { + this.handleResize_ = this.updateSize.bind(this); + window.addEventListener(EventType.RESIZE, this.handleResize_, false); + } + } + + this.updateSize(); + // updateSize calls setSize, so no need to call this.render + // ourselves here. + }; + + /** + * @private + */ + PluggableMap.prototype.handleTileChange_ = function handleTileChange_ () { + this.render(); + }; + + /** + * @private + */ + PluggableMap.prototype.handleViewPropertyChanged_ = function handleViewPropertyChanged_ () { + this.render(); + }; + + /** + * @private + */ + PluggableMap.prototype.handleViewChanged_ = function handleViewChanged_ () { + if (this.viewPropertyListenerKey_) { + unlistenByKey(this.viewPropertyListenerKey_); + this.viewPropertyListenerKey_ = null; + } + if (this.viewChangeListenerKey_) { + unlistenByKey(this.viewChangeListenerKey_); + this.viewChangeListenerKey_ = null; + } + var view = this.getView(); + if (view) { + this.viewport_.setAttribute('data-view', getUid(view)); + this.viewPropertyListenerKey_ = listen( + view, ObjectEventType.PROPERTYCHANGE, + this.handleViewPropertyChanged_, this); + this.viewChangeListenerKey_ = listen( + view, EventType.CHANGE, + this.handleViewPropertyChanged_, this); + } + this.render(); + }; + + /** + * @private + */ + PluggableMap.prototype.handleLayerGroupChanged_ = function handleLayerGroupChanged_ () { + if (this.layerGroupPropertyListenerKeys_) { + this.layerGroupPropertyListenerKeys_.forEach(unlistenByKey); + this.layerGroupPropertyListenerKeys_ = null; + } + var layerGroup = this.getLayerGroup(); + if (layerGroup) { + this.layerGroupPropertyListenerKeys_ = [ + listen( + layerGroup, ObjectEventType.PROPERTYCHANGE, + this.render, this), + listen( + layerGroup, EventType.CHANGE, + this.render, this) + ]; + } + this.render(); + }; + + /** + * @return {boolean} Is rendered. + */ + PluggableMap.prototype.isRendered = function isRendered () { + return !!this.frameState_; + }; + + /** + * Requests an immediate render in a synchronous manner. + * @api + */ + PluggableMap.prototype.renderSync = function renderSync () { + if (this.animationDelayKey_) { + cancelAnimationFrame(this.animationDelayKey_); + } + this.animationDelay_(); + }; + + /** + * Request a map rendering (at the next animation frame). + * @api + */ + PluggableMap.prototype.render = function render () { + if (this.animationDelayKey_ === undefined) { + this.animationDelayKey_ = requestAnimationFrame(this.animationDelay_); + } + }; + + /** + * Remove the given control from the map. + * @param {import("./control/Control.js").default} control Control. + * @return {import("./control/Control.js").default|undefined} The removed control (or undefined + * if the control was not found). + * @api + */ + PluggableMap.prototype.removeControl = function removeControl (control) { + return this.getControls().remove(control); + }; + + /** + * Remove the given interaction from the map. + * @param {import("./interaction/Interaction.js").default} interaction Interaction to remove. + * @return {import("./interaction/Interaction.js").default|undefined} The removed interaction (or + * undefined if the interaction was not found). + * @api + */ + PluggableMap.prototype.removeInteraction = function removeInteraction (interaction) { + return this.getInteractions().remove(interaction); + }; + + /** + * Removes the given layer from the map. + * @param {import("./layer/Base.js").default} layer Layer. + * @return {import("./layer/Base.js").default|undefined} The removed layer (or undefined if the + * layer was not found). + * @api + */ + PluggableMap.prototype.removeLayer = function removeLayer (layer) { + var layers = this.getLayerGroup().getLayers(); + return layers.remove(layer); + }; + + /** + * Remove the given overlay from the map. + * @param {import("./Overlay.js").default} overlay Overlay. + * @return {import("./Overlay.js").default|undefined} The removed overlay (or undefined + * if the overlay was not found). + * @api + */ + PluggableMap.prototype.removeOverlay = function removeOverlay (overlay) { + return this.getOverlays().remove(overlay); + }; + + /** + * @param {number} time Time. + * @private + */ + PluggableMap.prototype.renderFrame_ = function renderFrame_ (time) { + var viewState; + + var size = this.getSize(); + var view = this.getView(); + var extent = createEmpty(); + var previousFrameState = this.frameState_; + /** @type {?FrameState} */ + var frameState = null; + if (size !== undefined && hasArea(size) && view && view.isDef()) { + var viewHints = view.getHints(this.frameState_ ? this.frameState_.viewHints : undefined); + var layerStatesArray = this.getLayerGroup().getLayerStatesArray(); + var layerStates = {}; + for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) { + layerStates[getUid(layerStatesArray[i].layer)] = layerStatesArray[i]; + } + viewState = view.getState(this.pixelRatio_); + frameState = /** @type {FrameState} */ ({ + animate: false, + coordinateToPixelTransform: this.coordinateToPixelTransform_, + extent: extent, + focus: this.focus_ ? this.focus_ : viewState.center, + index: this.frameIndex_++, + layerStates: layerStates, + layerStatesArray: layerStatesArray, + pixelRatio: this.pixelRatio_, + pixelToCoordinateTransform: this.pixelToCoordinateTransform_, + postRenderFunctions: [], + size: size, + skippedFeatureUids: this.skippedFeatureUids_, + tileQueue: this.tileQueue_, + time: time, + usedTiles: {}, + viewState: viewState, + viewHints: viewHints, + wantedTiles: {} + }); + } + + if (frameState) { + frameState.extent = getForViewAndSize(viewState.center, + viewState.resolution, viewState.rotation, frameState.size, extent); + } + + this.frameState_ = frameState; + this.renderer_.renderFrame(frameState); + + if (frameState) { + if (frameState.animate) { + this.render(); + } + Array.prototype.push.apply(this.postRenderFunctions_, frameState.postRenderFunctions); + + if (previousFrameState) { + var moveStart = !this.previousExtent_ || + (!extent_isEmpty(this.previousExtent_) && + !extent_equals(frameState.extent, this.previousExtent_)); + if (moveStart) { + this.dispatchEvent( + new ol_MapEvent(MapEventType.MOVESTART, this, previousFrameState)); + this.previousExtent_ = createOrUpdateEmpty(this.previousExtent_); + } + } + + var idle = this.previousExtent_ && + !frameState.viewHints[ViewHint.ANIMATING] && + !frameState.viewHints[ViewHint.INTERACTING] && + !extent_equals(frameState.extent, this.previousExtent_); + + if (idle) { + this.dispatchEvent(new ol_MapEvent(MapEventType.MOVEEND, this, frameState)); + extent_clone(frameState.extent, this.previousExtent_); + } + } + + this.dispatchEvent(new ol_MapEvent(MapEventType.POSTRENDER, this, frameState)); + + setTimeout(this.handlePostRender.bind(this), 0); + + }; + + /** + * Sets the layergroup of this map. + * @param {LayerGroup} layerGroup A layer group containing the layers in this map. + * @observable + * @api + */ + PluggableMap.prototype.setLayerGroup = function setLayerGroup (layerGroup) { + this.set(MapProperty.LAYERGROUP, layerGroup); + }; + + /** + * Set the size of this map. + * @param {import("./size.js").Size|undefined} size The size in pixels of the map in the DOM. + * @observable + * @api + */ + PluggableMap.prototype.setSize = function setSize (size) { + this.set(MapProperty.SIZE, size); + }; + + /** + * Set the target element to render this map into. + * @param {HTMLElement|string|undefined} target The Element or id of the Element + * that the map is rendered in. + * @observable + * @api + */ + PluggableMap.prototype.setTarget = function setTarget (target) { + this.set(MapProperty.TARGET, target); + }; + + /** + * Set the view for this map. + * @param {View} view The view that controls this map. + * @observable + * @api + */ + PluggableMap.prototype.setView = function setView (view) { + this.set(MapProperty.VIEW, view); + }; + + /** + * @param {import("./Feature.js").default} feature Feature. + */ + PluggableMap.prototype.skipFeature = function skipFeature (feature) { + this.skippedFeatureUids_[getUid(feature)] = true; + this.render(); + }; + + /** + * Force a recalculation of the map viewport size. This should be called when + * third-party code changes the size of the map viewport. + * @api + */ + PluggableMap.prototype.updateSize = function updateSize () { + var targetElement = this.getTargetElement(); + + if (!targetElement) { + this.setSize(undefined); + } else { + var computedStyle = getComputedStyle(targetElement); + this.setSize([ + targetElement.offsetWidth - + parseFloat(computedStyle['borderLeftWidth']) - + parseFloat(computedStyle['paddingLeft']) - + parseFloat(computedStyle['paddingRight']) - + parseFloat(computedStyle['borderRightWidth']), + targetElement.offsetHeight - + parseFloat(computedStyle['borderTopWidth']) - + parseFloat(computedStyle['paddingTop']) - + parseFloat(computedStyle['paddingBottom']) - + parseFloat(computedStyle['borderBottomWidth']) + ]); + } + }; + + /** + * @param {import("./Feature.js").default} feature Feature. + */ + PluggableMap.prototype.unskipFeature = function unskipFeature (feature) { + delete this.skippedFeatureUids_[getUid(feature)]; + this.render(); + }; + + return PluggableMap; +}(ol_Object)); + + +/** + * @param {MapOptions} options Map options. + * @return {MapOptionsInternal} Internal map options. + */ +function createOptionsInternal(options) { + + /** + * @type {HTMLElement|Document} + */ + var keyboardEventTarget = null; + if (options.keyboardEventTarget !== undefined) { + keyboardEventTarget = typeof options.keyboardEventTarget === 'string' ? + document.getElementById(options.keyboardEventTarget) : + options.keyboardEventTarget; + } + + /** + * @type {Object} + */ + var values = {}; + + var layerGroup = options.layers && typeof /** @type {?} */ (options.layers).getLayers === 'function' ? + /** @type {LayerGroup} */ (options.layers) : new Group({layers: /** @type {Collection} */ (options.layers)}); + values[MapProperty.LAYERGROUP] = layerGroup; + + values[MapProperty.TARGET] = options.target; + + values[MapProperty.VIEW] = options.view !== undefined ? + options.view : new ol_View(); + + var controls; + if (options.controls !== undefined) { + if (Array.isArray(options.controls)) { + controls = new ol_Collection(options.controls.slice()); + } else { + assert(typeof /** @type {?} */ (options.controls).getArray === 'function', + 47); // Expected `controls` to be an array or an `import("./Collection.js").Collection` + controls = /** @type {Collection} */ (options.controls); + } + } + + var interactions; + if (options.interactions !== undefined) { + if (Array.isArray(options.interactions)) { + interactions = new ol_Collection(options.interactions.slice()); + } else { + assert(typeof /** @type {?} */ (options.interactions).getArray === 'function', + 48); // Expected `interactions` to be an array or an `import("./Collection.js").Collection` + interactions = /** @type {Collection} */ (options.interactions); + } + } + + var overlays; + if (options.overlays !== undefined) { + if (Array.isArray(options.overlays)) { + overlays = new ol_Collection(options.overlays.slice()); + } else { + assert(typeof /** @type {?} */ (options.overlays).getArray === 'function', + 49); // Expected `overlays` to be an array or an `import("./Collection.js").Collection` + overlays = options.overlays; + } + } else { + overlays = new ol_Collection(); + } + + return { + controls: controls, + interactions: interactions, + keyboardEventTarget: keyboardEventTarget, + overlays: overlays, + values: values + }; + +} +/* harmony default export */ var ol_PluggableMap = (PluggableMap_PluggableMap); + +/** + * @param {Array} layers Layers. + * @return {boolean} Layers have sources that are still loading. + */ +function getLoading(layers) { + for (var i = 0, ii = layers.length; i < ii; ++i) { + var layer = layers[i]; + if (typeof /** @type {?} */ (layer).getLayers === 'function') { + return getLoading(/** @type {LayerGroup} */ (layer).getLayers().getArray()); + } else { + var source = /** @type {import("./layer/Layer.js").default} */ ( + layer).getSource(); + if (source && source.loading) { + return true; + } + } + } + return false; +} + +//# sourceMappingURL=PluggableMap.js.map +// CONCATENATED MODULE: ./node_modules/ol/control/Control.js +/** + * @module ol/control/Control + */ + + + + + + + +/** + * @typedef {Object} Options + * @property {HTMLElement} [element] The element is the control's + * container element. This only needs to be specified if you're developing + * a custom control. + * @property {function(import("../MapEvent.js").default)} [render] Function called when + * the control should be re-rendered. This is called in a `requestAnimationFrame` + * callback. + * @property {HTMLElement|string} [target] Specify a target if you want + * the control to be rendered outside of the map's viewport. + */ + + +/** + * @classdesc + * A control is a visible widget with a DOM element in a fixed position on the + * screen. They can involve user input (buttons), or be informational only; + * the position is determined using CSS. By default these are placed in the + * container with CSS class name `ol-overlaycontainer-stopevent`, but can use + * any outside DOM element. + * + * This is the base class for controls. You can use it for simple custom + * controls by creating the element with listeners, creating an instance: + * ```js + * var myControl = new Control({element: myElement}); + * ``` + * and then adding this to the map. + * + * The main advantage of having this as a control rather than a simple separate + * DOM element is that preventing propagation is handled for you. Controls + * will also be objects in a {@link module:ol/Collection~Collection}, so you can use their methods. + * + * You can also extend this base for your own control class. See + * examples/custom-controls for an example of how to do this. + * + * @api + */ +var Control_Control = /*@__PURE__*/(function (BaseObject) { + function Control(options) { + + BaseObject.call(this); + + /** + * @protected + * @type {HTMLElement} + */ + this.element = options.element ? options.element : null; + + /** + * @private + * @type {HTMLElement} + */ + this.target_ = null; + + /** + * @private + * @type {import("../PluggableMap.js").default} + */ + this.map_ = null; + + /** + * @protected + * @type {!Array} + */ + this.listenerKeys = []; + + /** + * @type {function(import("../MapEvent.js").default)} + */ + this.render = options.render ? options.render : VOID; + + if (options.target) { + this.setTarget(options.target); + } + + } + + if ( BaseObject ) Control.__proto__ = BaseObject; + Control.prototype = Object.create( BaseObject && BaseObject.prototype ); + Control.prototype.constructor = Control; + + /** + * @inheritDoc + */ + Control.prototype.disposeInternal = function disposeInternal () { + removeNode(this.element); + BaseObject.prototype.disposeInternal.call(this); + }; + + /** + * Get the map associated with this control. + * @return {import("../PluggableMap.js").default} Map. + * @api + */ + Control.prototype.getMap = function getMap () { + return this.map_; + }; + + /** + * Remove the control from its current map and attach it to the new map. + * Subclasses may set up event handlers to get notified about changes to + * the map here. + * @param {import("../PluggableMap.js").default} map Map. + * @api + */ + Control.prototype.setMap = function setMap (map) { + if (this.map_) { + removeNode(this.element); + } + for (var i = 0, ii = this.listenerKeys.length; i < ii; ++i) { + unlistenByKey(this.listenerKeys[i]); + } + this.listenerKeys.length = 0; + this.map_ = map; + if (this.map_) { + var target = this.target_ ? + this.target_ : map.getOverlayContainerStopEvent(); + target.appendChild(this.element); + if (this.render !== VOID) { + this.listenerKeys.push(listen(map, + MapEventType.POSTRENDER, this.render, this)); + } + map.render(); + } + }; + + /** + * This function is used to set a target element for the control. It has no + * effect if it is called after the control has been added to the map (i.e. + * after `setMap` is called on the control). If no `target` is set in the + * options passed to the control constructor and if `setTarget` is not called + * then the control is added to the map's overlay container. + * @param {HTMLElement|string} target Target. + * @api + */ + Control.prototype.setTarget = function setTarget (target) { + this.target_ = typeof target === 'string' ? + document.getElementById(target) : + target; + }; + + return Control; +}(ol_Object)); + + +/* harmony default export */ var control_Control = (Control_Control); + +//# sourceMappingURL=Control.js.map +// CONCATENATED MODULE: ./node_modules/ol/css.js +/** + * @module ol/css + */ + + +/** + * The CSS class for hidden feature. + * + * @const + * @type {string} + */ +var CLASS_HIDDEN = 'ol-hidden'; + + +/** + * The CSS class that we'll give the DOM elements to have them selectable. + * + * @const + * @type {string} + */ +var CLASS_SELECTABLE = 'ol-selectable'; + + +/** + * The CSS class that we'll give the DOM elements to have them unselectable. + * + * @const + * @type {string} + */ +var CLASS_UNSELECTABLE = 'ol-unselectable'; + + +/** + * The CSS class for unsupported feature. + * + * @const + * @type {string} + */ +var CLASS_UNSUPPORTED = 'ol-unsupported'; + + +/** + * The CSS class for controls. + * + * @const + * @type {string} + */ +var CLASS_CONTROL = 'ol-control'; + + +/** + * The CSS class that we'll give the DOM elements that are collapsed, i.e. + * to those elements which usually can be expanded. + * + * @const + * @type {string} + */ +var CLASS_COLLAPSED = 'ol-collapsed'; + + +/** + * Get the list of font families from a font spec. Note that this doesn't work + * for font families that have commas in them. + * @param {string} The CSS font property. + * @return {Object} The font families (or null if the input spec is invalid). + */ +var getFontFamilies = (function() { + var style; + var cache = {}; + return function(font) { + if (!style) { + style = document.createElement('div').style; + } + if (!(font in cache)) { + style.font = font; + var family = style.fontFamily; + style.font = ''; + if (!family) { + return null; + } + cache[font] = family.split(/,\s?/); + } + return cache[font]; + }; +})(); + +//# sourceMappingURL=css.js.map +// CONCATENATED MODULE: ./node_modules/ol/layer/Layer.js +/** + * @module ol/layer/Layer + */ + + + + + + + + + + + +/** + * @typedef {Object} Options + * @property {number} [opacity=1] Opacity (0, 1). + * @property {boolean} [visible=true] Visibility. + * @property {import("../extent.js").Extent} [extent] The bounding extent for layer rendering. The layer will not be + * rendered outside of this extent. + * @property {number} [zIndex] The z-index for layer rendering. At rendering time, the layers + * will be ordered, first by Z-index and then by position. When `undefined`, a `zIndex` of 0 is assumed + * for layers that are added to the map's `layers` collection, or `Infinity` when the layer's `setMap()` + * method was used. + * @property {number} [minResolution] The minimum resolution (inclusive) at which this layer will be + * visible. + * @property {number} [maxResolution] The maximum resolution (exclusive) below which this layer will + * be visible. + * @property {import("../source/Source.js").default} [source] Source for this layer. If not provided to the constructor, + * the source can be set by calling {@link module:ol/layer/Layer#setSource layer.setSource(source)} after + * construction. + * @property {import("../PluggableMap.js").default} [map] Map. + */ + + +/** + * @typedef {Object} State + * @property {import("./Base.js").default} layer + * @property {number} opacity + * @property {SourceState} sourceState + * @property {boolean} visible + * @property {boolean} managed + * @property {import("../extent.js").Extent} [extent] + * @property {number} zIndex + * @property {number} maxResolution + * @property {number} minResolution + */ + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * A visual representation of raster or vector map data. + * Layers group together those properties that pertain to how the data is to be + * displayed, irrespective of the source of that data. + * + * Layers are usually added to a map with {@link module:ol/Map#addLayer}. Components + * like {@link module:ol/interaction/Select~Select} use unmanaged layers + * internally. These unmanaged layers are associated with the map using + * {@link module:ol/layer/Layer~Layer#setMap} instead. + * + * A generic `change` event is fired when the state of the source changes. + * + * @fires import("../render/Event.js").RenderEvent + */ +var Layer_Layer = /*@__PURE__*/(function (BaseLayer) { + function Layer(options) { + + var baseOptions = obj_assign({}, options); + delete baseOptions.source; + + BaseLayer.call(this, baseOptions); + + /** + * @private + * @type {?import("../events.js").EventsKey} + */ + this.mapPrecomposeKey_ = null; + + /** + * @private + * @type {?import("../events.js").EventsKey} + */ + this.mapRenderKey_ = null; + + /** + * @private + * @type {?import("../events.js").EventsKey} + */ + this.sourceChangeKey_ = null; + + if (options.map) { + this.setMap(options.map); + } + + listen(this, + getChangeEventType(layer_Property.SOURCE), + this.handleSourcePropertyChange_, this); + + var source = options.source ? options.source : null; + this.setSource(source); + } + + if ( BaseLayer ) Layer.__proto__ = BaseLayer; + Layer.prototype = Object.create( BaseLayer && BaseLayer.prototype ); + Layer.prototype.constructor = Layer; + + /** + * @inheritDoc + */ + Layer.prototype.getLayersArray = function getLayersArray (opt_array) { + var array = opt_array ? opt_array : []; + array.push(this); + return array; + }; + + /** + * @inheritDoc + */ + Layer.prototype.getLayerStatesArray = function getLayerStatesArray (opt_states) { + var states = opt_states ? opt_states : []; + states.push(this.getLayerState()); + return states; + }; + + /** + * Get the layer source. + * @return {import("../source/Source.js").default} The layer source (or `null` if not yet set). + * @observable + * @api + */ + Layer.prototype.getSource = function getSource () { + var source = this.get(layer_Property.SOURCE); + return ( + /** @type {import("../source/Source.js").default} */ (source) || null + ); + }; + + /** + * @inheritDoc + */ + Layer.prototype.getSourceState = function getSourceState () { + var source = this.getSource(); + return !source ? State.UNDEFINED : source.getState(); + }; + + /** + * @private + */ + Layer.prototype.handleSourceChange_ = function handleSourceChange_ () { + this.changed(); + }; + + /** + * @private + */ + Layer.prototype.handleSourcePropertyChange_ = function handleSourcePropertyChange_ () { + if (this.sourceChangeKey_) { + unlistenByKey(this.sourceChangeKey_); + this.sourceChangeKey_ = null; + } + var source = this.getSource(); + if (source) { + this.sourceChangeKey_ = listen(source, + EventType.CHANGE, this.handleSourceChange_, this); + } + this.changed(); + }; + + /** + * Sets the layer to be rendered on top of other layers on a map. The map will + * not manage this layer in its layers collection, and the callback in + * {@link module:ol/Map#forEachLayerAtPixel} will receive `null` as layer. This + * is useful for temporary layers. To remove an unmanaged layer from the map, + * use `#setMap(null)`. + * + * To add the layer to a map and have it managed by the map, use + * {@link module:ol/Map#addLayer} instead. + * @param {import("../PluggableMap.js").default} map Map. + * @api + */ + Layer.prototype.setMap = function setMap (map) { + if (this.mapPrecomposeKey_) { + unlistenByKey(this.mapPrecomposeKey_); + this.mapPrecomposeKey_ = null; + } + if (!map) { + this.changed(); + } + if (this.mapRenderKey_) { + unlistenByKey(this.mapRenderKey_); + this.mapRenderKey_ = null; + } + if (map) { + this.mapPrecomposeKey_ = listen(map, render_EventType.PRECOMPOSE, function(evt) { + var renderEvent = /** @type {import("../render/Event.js").default} */ (evt); + var layerState = this.getLayerState(); + layerState.managed = false; + if (this.getZIndex() === undefined) { + layerState.zIndex = Infinity; + } + renderEvent.frameState.layerStatesArray.push(layerState); + renderEvent.frameState.layerStates[getUid(this)] = layerState; + }, this); + this.mapRenderKey_ = listen(this, EventType.CHANGE, map.render, map); + this.changed(); + } + }; + + /** + * Set the layer source. + * @param {import("../source/Source.js").default} source The layer source. + * @observable + * @api + */ + Layer.prototype.setSource = function setSource (source) { + this.set(layer_Property.SOURCE, source); + }; + + return Layer; +}(Base)); + + +/** + * Return `true` if the layer is visible, and if the passed resolution is + * between the layer's minResolution and maxResolution. The comparison is + * inclusive for `minResolution` and exclusive for `maxResolution`. + * @param {State} layerState Layer state. + * @param {number} resolution Resolution. + * @return {boolean} The layer is visible at the given resolution. + */ +function visibleAtResolution(layerState, resolution) { + return layerState.visible && resolution >= layerState.minResolution && + resolution < layerState.maxResolution; +} + + +/* harmony default export */ var layer_Layer = (Layer_Layer); + +//# sourceMappingURL=Layer.js.map +// CONCATENATED MODULE: ./node_modules/ol/control/Attribution.js +/** + * @module ol/control/Attribution + */ + + + + + + + + + +/** + * @typedef {Object} Options + * @property {string} [className='ol-attribution'] CSS class name. + * @property {HTMLElement|string} [target] Specify a target if you + * want the control to be rendered outside of the map's + * viewport. + * @property {boolean} [collapsible] Specify if attributions can + * be collapsed. If not specified, sources control this behavior with their + * `attributionsCollapsible` setting. + * @property {boolean} [collapsed=true] Specify if attributions should + * be collapsed at startup. + * @property {string} [tipLabel='Attributions'] Text label to use for the button tip. + * @property {string} [label='i'] Text label to use for the + * collapsed attributions button. + * Instead of text, also an element (e.g. a `span` element) can be used. + * @property {string|HTMLElement} [collapseLabel='»'] Text label to use + * for the expanded attributions button. + * Instead of text, also an element (e.g. a `span` element) can be used. + * @property {function(import("../MapEvent.js").default)} [render] Function called when + * the control should be re-rendered. This is called in a `requestAnimationFrame` + * callback. + */ + + +/** + * @classdesc + * Control to show all the attributions associated with the layer sources + * in the map. This control is one of the default controls included in maps. + * By default it will show in the bottom right portion of the map, but this can + * be changed by using a css selector for `.ol-attribution`. + * + * @api + */ +var Attribution_Attribution = /*@__PURE__*/(function (Control) { + function Attribution(opt_options) { + + var options = opt_options ? opt_options : {}; + + Control.call(this, { + element: document.createElement('div'), + render: options.render || Attribution_render, + target: options.target + }); + + /** + * @private + * @type {HTMLElement} + */ + this.ulElement_ = document.createElement('ul'); + + /** + * @private + * @type {boolean} + */ + this.collapsed_ = options.collapsed !== undefined ? options.collapsed : true; + + /** + * @private + * @type {boolean} + */ + this.overrideCollapsible_ = options.collapsible !== undefined; + + /** + * @private + * @type {boolean} + */ + this.collapsible_ = options.collapsible !== undefined ? + options.collapsible : true; + + if (!this.collapsible_) { + this.collapsed_ = false; + } + + var className = options.className !== undefined ? options.className : 'ol-attribution'; + + var tipLabel = options.tipLabel !== undefined ? options.tipLabel : 'Attributions'; + + var collapseLabel = options.collapseLabel !== undefined ? options.collapseLabel : '\u00BB'; + + if (typeof collapseLabel === 'string') { + /** + * @private + * @type {HTMLElement} + */ + this.collapseLabel_ = document.createElement('span'); + this.collapseLabel_.textContent = collapseLabel; + } else { + this.collapseLabel_ = collapseLabel; + } + + var label = options.label !== undefined ? options.label : 'i'; + + if (typeof label === 'string') { + /** + * @private + * @type {HTMLElement} + */ + this.label_ = document.createElement('span'); + this.label_.textContent = label; + } else { + this.label_ = label; + } + + + var activeLabel = (this.collapsible_ && !this.collapsed_) ? + this.collapseLabel_ : this.label_; + var button = document.createElement('button'); + button.setAttribute('type', 'button'); + button.title = tipLabel; + button.appendChild(activeLabel); + + listen(button, EventType.CLICK, this.handleClick_, this); + + var cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL + + (this.collapsed_ && this.collapsible_ ? ' ' + CLASS_COLLAPSED : '') + + (this.collapsible_ ? '' : ' ol-uncollapsible'); + var element = this.element; + element.className = cssClasses; + element.appendChild(this.ulElement_); + element.appendChild(button); + + /** + * A list of currently rendered resolutions. + * @type {Array} + * @private + */ + this.renderedAttributions_ = []; + + /** + * @private + * @type {boolean} + */ + this.renderedVisible_ = true; + + } + + if ( Control ) Attribution.__proto__ = Control; + Attribution.prototype = Object.create( Control && Control.prototype ); + Attribution.prototype.constructor = Attribution; + + /** + * Collect a list of visible attributions and set the collapsible state. + * @param {import("../PluggableMap.js").FrameState} frameState Frame state. + * @return {Array} Attributions. + * @private + */ + Attribution.prototype.collectSourceAttributions_ = function collectSourceAttributions_ (frameState) { + /** + * Used to determine if an attribution already exists. + * @type {!Object} + */ + var lookup = {}; + + /** + * A list of visible attributions. + * @type {Array} + */ + var visibleAttributions = []; + + var layerStatesArray = frameState.layerStatesArray; + var resolution = frameState.viewState.resolution; + for (var i = 0, ii = layerStatesArray.length; i < ii; ++i) { + var layerState = layerStatesArray[i]; + if (!visibleAtResolution(layerState, resolution)) { + continue; + } + + var source = /** @type {import("../layer/Layer.js").default} */ (layerState.layer).getSource(); + if (!source) { + continue; + } + + var attributionGetter = source.getAttributions(); + if (!attributionGetter) { + continue; + } + + var attributions = attributionGetter(frameState); + if (!attributions) { + continue; + } + + if (!this.overrideCollapsible_ && source.getAttributionsCollapsible() === false) { + this.setCollapsible(false); + } + + if (Array.isArray(attributions)) { + for (var j = 0, jj = attributions.length; j < jj; ++j) { + if (!(attributions[j] in lookup)) { + visibleAttributions.push(attributions[j]); + lookup[attributions[j]] = true; + } + } + } else { + if (!(attributions in lookup)) { + visibleAttributions.push(attributions); + lookup[attributions] = true; + } + } + } + return visibleAttributions; + }; + + /** + * @private + * @param {?import("../PluggableMap.js").FrameState} frameState Frame state. + */ + Attribution.prototype.updateElement_ = function updateElement_ (frameState) { + if (!frameState) { + if (this.renderedVisible_) { + this.element.style.display = 'none'; + this.renderedVisible_ = false; + } + return; + } + + var attributions = this.collectSourceAttributions_(frameState); + + var visible = attributions.length > 0; + if (this.renderedVisible_ != visible) { + this.element.style.display = visible ? '' : 'none'; + this.renderedVisible_ = visible; + } + + if (equals(attributions, this.renderedAttributions_)) { + return; + } + + removeChildren(this.ulElement_); + + // append the attributions + for (var i = 0, ii = attributions.length; i < ii; ++i) { + var element = document.createElement('li'); + element.innerHTML = attributions[i]; + this.ulElement_.appendChild(element); + } + + this.renderedAttributions_ = attributions; + }; + + /** + * @param {MouseEvent} event The event to handle + * @private + */ + Attribution.prototype.handleClick_ = function handleClick_ (event) { + event.preventDefault(); + this.handleToggle_(); + }; + + /** + * @private + */ + Attribution.prototype.handleToggle_ = function handleToggle_ () { + this.element.classList.toggle(CLASS_COLLAPSED); + if (this.collapsed_) { + replaceNode(this.collapseLabel_, this.label_); + } else { + replaceNode(this.label_, this.collapseLabel_); + } + this.collapsed_ = !this.collapsed_; + }; + + /** + * Return `true` if the attribution is collapsible, `false` otherwise. + * @return {boolean} True if the widget is collapsible. + * @api + */ + Attribution.prototype.getCollapsible = function getCollapsible () { + return this.collapsible_; + }; + + /** + * Set whether the attribution should be collapsible. + * @param {boolean} collapsible True if the widget is collapsible. + * @api + */ + Attribution.prototype.setCollapsible = function setCollapsible (collapsible) { + if (this.collapsible_ === collapsible) { + return; + } + this.collapsible_ = collapsible; + this.element.classList.toggle('ol-uncollapsible'); + if (!collapsible && this.collapsed_) { + this.handleToggle_(); + } + }; + + /** + * Collapse or expand the attribution according to the passed parameter. Will + * not do anything if the attribution isn't collapsible or if the current + * collapsed state is already the one requested. + * @param {boolean} collapsed True if the widget is collapsed. + * @api + */ + Attribution.prototype.setCollapsed = function setCollapsed (collapsed) { + if (!this.collapsible_ || this.collapsed_ === collapsed) { + return; + } + this.handleToggle_(); + }; + + /** + * Return `true` when the attribution is currently collapsed or `false` + * otherwise. + * @return {boolean} True if the widget is collapsed. + * @api + */ + Attribution.prototype.getCollapsed = function getCollapsed () { + return this.collapsed_; + }; + + return Attribution; +}(control_Control)); + + +/** + * Update the attribution element. + * @param {import("../MapEvent.js").default} mapEvent Map event. + * @this {Attribution} + * @api + */ +function Attribution_render(mapEvent) { + this.updateElement_(mapEvent.frameState); +} + + +/* harmony default export */ var control_Attribution = (Attribution_Attribution); + +//# sourceMappingURL=Attribution.js.map +// CONCATENATED MODULE: ./node_modules/ol/control/Rotate.js +/** + * @module ol/control/Rotate + */ + + + + + + + +/** + * @typedef {Object} Options + * @property {string} [className='ol-rotate'] CSS class name. + * @property {string|HTMLElement} [label='⇧'] Text label to use for the rotate button. + * Instead of text, also an element (e.g. a `span` element) can be used. + * @property {string} [tipLabel='Reset rotation'] Text label to use for the rotate tip. + * @property {number} [duration=250] Animation duration in milliseconds. + * @property {boolean} [autoHide=true] Hide the control when rotation is 0. + * @property {function(import("../MapEvent.js").default)} [render] Function called when the control should + * be re-rendered. This is called in a `requestAnimationFrame` callback. + * @property {function()} [resetNorth] Function called when the control is clicked. + * This will override the default `resetNorth`. + * @property {HTMLElement|string} [target] Specify a target if you want the control to be + * rendered outside of the map's viewport. + */ + + +/** + * @classdesc + * A button control to reset rotation to 0. + * To style this control use css selector `.ol-rotate`. A `.ol-hidden` css + * selector is added to the button when the rotation is 0. + * + * @api + */ +var Rotate_Rotate = /*@__PURE__*/(function (Control) { + function Rotate(opt_options) { + + var options = opt_options ? opt_options : {}; + + Control.call(this, { + element: document.createElement('div'), + render: options.render || Rotate_render, + target: options.target + }); + + var className = options.className !== undefined ? options.className : 'ol-rotate'; + + var label = options.label !== undefined ? options.label : '\u21E7'; + + /** + * @type {HTMLElement} + * @private + */ + this.label_ = null; + + if (typeof label === 'string') { + this.label_ = document.createElement('span'); + this.label_.className = 'ol-compass'; + this.label_.textContent = label; + } else { + this.label_ = label; + this.label_.classList.add('ol-compass'); + } + + var tipLabel = options.tipLabel ? options.tipLabel : 'Reset rotation'; + + var button = document.createElement('button'); + button.className = className + '-reset'; + button.setAttribute('type', 'button'); + button.title = tipLabel; + button.appendChild(this.label_); + + listen(button, EventType.CLICK, this.handleClick_, this); + + var cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL; + var element = this.element; + element.className = cssClasses; + element.appendChild(button); + + this.callResetNorth_ = options.resetNorth ? options.resetNorth : undefined; + + /** + * @type {number} + * @private + */ + this.duration_ = options.duration !== undefined ? options.duration : 250; + + /** + * @type {boolean} + * @private + */ + this.autoHide_ = options.autoHide !== undefined ? options.autoHide : true; + + /** + * @private + * @type {number|undefined} + */ + this.rotation_ = undefined; + + if (this.autoHide_) { + this.element.classList.add(CLASS_HIDDEN); + } + + } + + if ( Control ) Rotate.__proto__ = Control; + Rotate.prototype = Object.create( Control && Control.prototype ); + Rotate.prototype.constructor = Rotate; + + /** + * @param {MouseEvent} event The event to handle + * @private + */ + Rotate.prototype.handleClick_ = function handleClick_ (event) { + event.preventDefault(); + if (this.callResetNorth_ !== undefined) { + this.callResetNorth_(); + } else { + this.resetNorth_(); + } + }; + + /** + * @private + */ + Rotate.prototype.resetNorth_ = function resetNorth_ () { + var map = this.getMap(); + var view = map.getView(); + if (!view) { + // the map does not have a view, so we can't act + // upon it + return; + } + if (view.getRotation() !== undefined) { + if (this.duration_ > 0) { + view.animate({ + rotation: 0, + duration: this.duration_, + easing: easeOut + }); + } else { + view.setRotation(0); + } + } + }; + + return Rotate; +}(control_Control)); + + +/** + * Update the rotate control element. + * @param {import("../MapEvent.js").default} mapEvent Map event. + * @this {Rotate} + * @api + */ +function Rotate_render(mapEvent) { + var frameState = mapEvent.frameState; + if (!frameState) { + return; + } + var rotation = frameState.viewState.rotation; + if (rotation != this.rotation_) { + var transform = 'rotate(' + rotation + 'rad)'; + if (this.autoHide_) { + var contains = this.element.classList.contains(CLASS_HIDDEN); + if (!contains && rotation === 0) { + this.element.classList.add(CLASS_HIDDEN); + } else if (contains && rotation !== 0) { + this.element.classList.remove(CLASS_HIDDEN); + } + } + this.label_.style.msTransform = transform; + this.label_.style.webkitTransform = transform; + this.label_.style.transform = transform; + } + this.rotation_ = rotation; +} + +/* harmony default export */ var control_Rotate = (Rotate_Rotate); + +//# sourceMappingURL=Rotate.js.map +// CONCATENATED MODULE: ./node_modules/ol/control/Zoom.js +/** + * @module ol/control/Zoom + */ + + + + + + + +/** + * @typedef {Object} Options + * @property {number} [duration=250] Animation duration in milliseconds. + * @property {string} [className='ol-zoom'] CSS class name. + * @property {string|HTMLElement} [zoomInLabel='+'] Text label to use for the zoom-in + * button. Instead of text, also an element (e.g. a `span` element) can be used. + * @property {string|HTMLElement} [zoomOutLabel='-'] Text label to use for the zoom-out button. + * Instead of text, also an element (e.g. a `span` element) can be used. + * @property {string} [zoomInTipLabel='Zoom in'] Text label to use for the button tip. + * @property {string} [zoomOutTipLabel='Zoom out'] Text label to use for the button tip. + * @property {number} [delta=1] The zoom delta applied on each click. + * @property {HTMLElement|string} [target] Specify a target if you want the control to be + * rendered outside of the map's viewport. + */ + + +/** + * @classdesc + * A control with 2 buttons, one for zoom in and one for zoom out. + * This control is one of the default controls of a map. To style this control + * use css selectors `.ol-zoom-in` and `.ol-zoom-out`. + * + * @api + */ +var Zoom_Zoom = /*@__PURE__*/(function (Control) { + function Zoom(opt_options) { + + var options = opt_options ? opt_options : {}; + + Control.call(this, { + element: document.createElement('div'), + target: options.target + }); + + var className = options.className !== undefined ? options.className : 'ol-zoom'; + + var delta = options.delta !== undefined ? options.delta : 1; + + var zoomInLabel = options.zoomInLabel !== undefined ? options.zoomInLabel : '+'; + var zoomOutLabel = options.zoomOutLabel !== undefined ? options.zoomOutLabel : '\u2212'; + + var zoomInTipLabel = options.zoomInTipLabel !== undefined ? + options.zoomInTipLabel : 'Zoom in'; + var zoomOutTipLabel = options.zoomOutTipLabel !== undefined ? + options.zoomOutTipLabel : 'Zoom out'; + + var inElement = document.createElement('button'); + inElement.className = className + '-in'; + inElement.setAttribute('type', 'button'); + inElement.title = zoomInTipLabel; + inElement.appendChild( + typeof zoomInLabel === 'string' ? document.createTextNode(zoomInLabel) : zoomInLabel + ); + + listen(inElement, EventType.CLICK, this.handleClick_.bind(this, delta)); + + var outElement = document.createElement('button'); + outElement.className = className + '-out'; + outElement.setAttribute('type', 'button'); + outElement.title = zoomOutTipLabel; + outElement.appendChild( + typeof zoomOutLabel === 'string' ? document.createTextNode(zoomOutLabel) : zoomOutLabel + ); + + listen(outElement, EventType.CLICK, this.handleClick_.bind(this, -delta)); + + var cssClasses = className + ' ' + CLASS_UNSELECTABLE + ' ' + CLASS_CONTROL; + var element = this.element; + element.className = cssClasses; + element.appendChild(inElement); + element.appendChild(outElement); + + /** + * @type {number} + * @private + */ + this.duration_ = options.duration !== undefined ? options.duration : 250; + + } + + if ( Control ) Zoom.__proto__ = Control; + Zoom.prototype = Object.create( Control && Control.prototype ); + Zoom.prototype.constructor = Zoom; + + /** + * @param {number} delta Zoom delta. + * @param {MouseEvent} event The event to handle + * @private + */ + Zoom.prototype.handleClick_ = function handleClick_ (delta, event) { + event.preventDefault(); + this.zoomByDelta_(delta); + }; + + /** + * @param {number} delta Zoom delta. + * @private + */ + Zoom.prototype.zoomByDelta_ = function zoomByDelta_ (delta) { + var map = this.getMap(); + var view = map.getView(); + if (!view) { + // the map does not have a view, so we can't act + // upon it + return; + } + var currentResolution = view.getResolution(); + if (currentResolution) { + var newResolution = view.constrainResolution(currentResolution, delta); + if (this.duration_ > 0) { + if (view.getAnimating()) { + view.cancelAnimations(); + } + view.animate({ + resolution: newResolution, + duration: this.duration_, + easing: easeOut + }); + } else { + view.setResolution(newResolution); + } + } + }; + + return Zoom; +}(control_Control)); + + +/* harmony default export */ var control_Zoom = (Zoom_Zoom); + +//# sourceMappingURL=Zoom.js.map +// CONCATENATED MODULE: ./node_modules/ol/control/util.js +/** + * @module ol/control/util + */ + + + + + + +/** + * @typedef {Object} DefaultsOptions + * @property {boolean} [attribution=true] Include + * {@link module:ol/control/Attribution~Attribution}. + * @property {import("./Attribution.js").Options} [attributionOptions] + * Options for {@link module:ol/control/Attribution~Attribution}. + * @property {boolean} [rotate=true] Include + * {@link module:ol/control/Rotate~Rotate}. + * @property {import("./Rotate.js").Options} [rotateOptions] Options + * for {@link module:ol/control/Rotate~Rotate}. + * @property {boolean} [zoom] Include {@link module:ol/control/Zoom~Zoom}. + * @property {import("./Zoom.js").Options} [zoomOptions] Options for + * {@link module:ol/control/Zoom~Zoom}. + * @api + */ + + +/** + * Set of controls included in maps by default. Unless configured otherwise, + * this returns a collection containing an instance of each of the following + * controls: + * * {@link module:ol/control/Zoom~Zoom} + * * {@link module:ol/control/Rotate~Rotate} + * * {@link module:ol/control/Attribution~Attribution} + * + * @param {DefaultsOptions=} opt_options + * Defaults options. + * @return {Collection} + * Controls. + * @function module:ol/control.defaults + * @api + */ +function defaults(opt_options) { + + var options = opt_options ? opt_options : {}; + + var controls = new ol_Collection(); + + var zoomControl = options.zoom !== undefined ? options.zoom : true; + if (zoomControl) { + controls.push(new control_Zoom(options.zoomOptions)); + } + + var rotateControl = options.rotate !== undefined ? options.rotate : true; + if (rotateControl) { + controls.push(new control_Rotate(options.rotateOptions)); + } + + var attributionControl = options.attribution !== undefined ? + options.attribution : true; + if (attributionControl) { + controls.push(new control_Attribution(options.attributionOptions)); + } + + return controls; +} + +//# sourceMappingURL=util.js.map +// CONCATENATED MODULE: ./node_modules/ol/Kinetic.js +/** + * @module ol/Kinetic + */ + +/** + * @classdesc + * Implementation of inertial deceleration for map movement. + * + * @api + */ +var Kinetic = function Kinetic(decay, minVelocity, delay) { + + /** + * @private + * @type {number} + */ + this.decay_ = decay; + + /** + * @private + * @type {number} + */ + this.minVelocity_ = minVelocity; + + /** + * @private + * @type {number} + */ + this.delay_ = delay; + + /** + * @private + * @type {Array} + */ + this.points_ = []; + + /** + * @private + * @type {number} + */ + this.angle_ = 0; + + /** + * @private + * @type {number} + */ + this.initialVelocity_ = 0; +}; + +/** + * FIXME empty description for jsdoc + */ +Kinetic.prototype.begin = function begin () { + this.points_.length = 0; + this.angle_ = 0; + this.initialVelocity_ = 0; +}; + +/** + * @param {number} x X. + * @param {number} y Y. + */ +Kinetic.prototype.update = function update (x, y) { + this.points_.push(x, y, Date.now()); +}; + +/** + * @return {boolean} Whether we should do kinetic animation. + */ +Kinetic.prototype.end = function end () { + if (this.points_.length < 6) { + // at least 2 points are required (i.e. there must be at least 6 elements + // in the array) + return false; + } + var delay = Date.now() - this.delay_; + var lastIndex = this.points_.length - 3; + if (this.points_[lastIndex + 2] < delay) { + // the last tracked point is too old, which means that the user stopped + // panning before releasing the map + return false; + } + + // get the first point which still falls into the delay time + var firstIndex = lastIndex - 3; + while (firstIndex > 0 && this.points_[firstIndex + 2] > delay) { + firstIndex -= 3; + } + + var duration = this.points_[lastIndex + 2] - this.points_[firstIndex + 2]; + // we don't want a duration of 0 (divide by zero) + // we also make sure the user panned for a duration of at least one frame + // (1/60s) to compute sane displacement values + if (duration < 1000 / 60) { + return false; + } + + var dx = this.points_[lastIndex] - this.points_[firstIndex]; + var dy = this.points_[lastIndex + 1] - this.points_[firstIndex + 1]; + this.angle_ = Math.atan2(dy, dx); + this.initialVelocity_ = Math.sqrt(dx * dx + dy * dy) / duration; + return this.initialVelocity_ > this.minVelocity_; +}; + +/** + * @return {number} Total distance travelled (pixels). + */ +Kinetic.prototype.getDistance = function getDistance () { + return (this.minVelocity_ - this.initialVelocity_) / this.decay_; +}; + +/** + * @return {number} Angle of the kinetic panning animation (radians). + */ +Kinetic.prototype.getAngle = function getAngle () { + return this.angle_; +}; + +/* harmony default export */ var ol_Kinetic = (Kinetic); + +//# sourceMappingURL=Kinetic.js.map +// CONCATENATED MODULE: ./node_modules/ol/interaction/Property.js +/** + * @module ol/interaction/Property + */ + +/** + * @enum {string} + */ +/* harmony default export */ var interaction_Property = ({ + ACTIVE: 'active' +}); + +//# sourceMappingURL=Property.js.map +// CONCATENATED MODULE: ./node_modules/ol/interaction/Interaction.js +/** + * @module ol/interaction/Interaction + */ + + + + + + +/** + * Object literal with config options for interactions. + * @typedef {Object} InteractionOptions + * @property {function(import("../MapBrowserEvent.js").default):boolean} handleEvent + * Method called by the map to notify the interaction that a browser event was + * dispatched to the map. If the function returns a falsy value, propagation of + * the event to other interactions in the map's interactions chain will be + * prevented (this includes functions with no explicit return). + */ + + +/** + * @classdesc + * Abstract base class; normally only used for creating subclasses and not + * instantiated in apps. + * User actions that change the state of the map. Some are similar to controls, + * but are not associated with a DOM element. + * For example, {@link module:ol/interaction/KeyboardZoom~KeyboardZoom} is + * functionally the same as {@link module:ol/control/Zoom~Zoom}, but triggered + * by a keyboard event not a button element event. + * Although interactions do not have a DOM element, some of them do render + * vectors and so are visible on the screen. + * @api + */ +var Interaction_Interaction = /*@__PURE__*/(function (BaseObject) { + function Interaction(options) { + BaseObject.call(this); + + if (options.handleEvent) { + this.handleEvent = options.handleEvent; + } + + /** + * @private + * @type {import("../PluggableMap.js").default} + */ + this.map_ = null; + + this.setActive(true); + } + + if ( BaseObject ) Interaction.__proto__ = BaseObject; + Interaction.prototype = Object.create( BaseObject && BaseObject.prototype ); + Interaction.prototype.constructor = Interaction; + + /** + * Return whether the interaction is currently active. + * @return {boolean} `true` if the interaction is active, `false` otherwise. + * @observable + * @api + */ + Interaction.prototype.getActive = function getActive () { + return /** @type {boolean} */ (this.get(interaction_Property.ACTIVE)); + }; + + /** + * Get the map associated with this interaction. + * @return {import("../PluggableMap.js").default} Map. + * @api + */ + Interaction.prototype.getMap = function getMap () { + return this.map_; + }; + + /** + * Handles the {@link module:ol/MapBrowserEvent map browser event}. + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @api + */ + Interaction.prototype.handleEvent = function handleEvent (mapBrowserEvent) { + return true; + }; + + /** + * Activate or deactivate the interaction. + * @param {boolean} active Active. + * @observable + * @api + */ + Interaction.prototype.setActive = function setActive (active) { + this.set(interaction_Property.ACTIVE, active); + }; + + /** + * Remove the interaction from its current map and attach it to the new map. + * Subclasses may set up event handlers to get notified about changes to + * the map here. + * @param {import("../PluggableMap.js").default} map Map. + */ + Interaction.prototype.setMap = function setMap (map) { + this.map_ = map; + }; + + return Interaction; +}(ol_Object)); + + +/** + * @param {import("../View.js").default} view View. + * @param {import("../coordinate.js").Coordinate} delta Delta. + * @param {number=} opt_duration Duration. + */ +function pan(view, delta, opt_duration) { + var currentCenter = view.getCenter(); + if (currentCenter) { + var center = view.constrainCenter( + [currentCenter[0] + delta[0], currentCenter[1] + delta[1]]); + if (opt_duration) { + view.animate({ + duration: opt_duration, + easing: linear, + center: center + }); + } else { + view.setCenter(center); + } + } +} + + +/** + * @param {import("../View.js").default} view View. + * @param {number|undefined} rotation Rotation. + * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +function Interaction_rotate(view, rotation, opt_anchor, opt_duration) { + rotation = view.constrainRotation(rotation, 0); + rotateWithoutConstraints(view, rotation, opt_anchor, opt_duration); +} + + +/** + * @param {import("../View.js").default} view View. + * @param {number|undefined} rotation Rotation. + * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +function rotateWithoutConstraints(view, rotation, opt_anchor, opt_duration) { + if (rotation !== undefined) { + var currentRotation = view.getRotation(); + var currentCenter = view.getCenter(); + if (currentRotation !== undefined && currentCenter && opt_duration > 0) { + view.animate({ + rotation: rotation, + anchor: opt_anchor, + duration: opt_duration, + easing: easeOut + }); + } else { + view.rotate(rotation, opt_anchor); + } + } +} + + +/** + * @param {import("../View.js").default} view View. + * @param {number|undefined} resolution Resolution to go to. + * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + * @param {number=} opt_direction Zooming direction; > 0 indicates + * zooming out, in which case the constraints system will select + * the largest nearest resolution; < 0 indicates zooming in, in + * which case the constraints system will select the smallest + * nearest resolution; == 0 indicates that the zooming direction + * is unknown/not relevant, in which case the constraints system + * will select the nearest resolution. If not defined 0 is + * assumed. + */ +function zoom(view, resolution, opt_anchor, opt_duration, opt_direction) { + resolution = view.constrainResolution(resolution, 0, opt_direction); + zoomWithoutConstraints(view, resolution, opt_anchor, opt_duration); +} + + +/** + * @param {import("../View.js").default} view View. + * @param {number} delta Delta from previous zoom level. + * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +function zoomByDelta(view, delta, opt_anchor, opt_duration) { + var currentResolution = view.getResolution(); + var resolution = view.constrainResolution(currentResolution, delta, 0); + + if (resolution !== undefined) { + var resolutions = view.getResolutions(); + resolution = clamp( + resolution, + view.getMinResolution() || resolutions[resolutions.length - 1], + view.getMaxResolution() || resolutions[0]); + } + + // If we have a constraint on center, we need to change the anchor so that the + // new center is within the extent. We first calculate the new center, apply + // the constraint to it, and then calculate back the anchor + if (opt_anchor && resolution !== undefined && resolution !== currentResolution) { + var currentCenter = view.getCenter(); + var center = view.calculateCenterZoom(resolution, opt_anchor); + center = view.constrainCenter(center); + + opt_anchor = [ + (resolution * currentCenter[0] - currentResolution * center[0]) / + (resolution - currentResolution), + (resolution * currentCenter[1] - currentResolution * center[1]) / + (resolution - currentResolution) + ]; + } + + zoomWithoutConstraints(view, resolution, opt_anchor, opt_duration); +} + + +/** + * @param {import("../View.js").default} view View. + * @param {number|undefined} resolution Resolution to go to. + * @param {import("../coordinate.js").Coordinate=} opt_anchor Anchor coordinate. + * @param {number=} opt_duration Duration. + */ +function zoomWithoutConstraints(view, resolution, opt_anchor, opt_duration) { + if (resolution) { + var currentResolution = view.getResolution(); + var currentCenter = view.getCenter(); + if (currentResolution !== undefined && currentCenter && + resolution !== currentResolution && opt_duration) { + view.animate({ + resolution: resolution, + anchor: opt_anchor, + duration: opt_duration, + easing: easeOut + }); + } else { + if (opt_anchor) { + var center = view.calculateCenterZoom(resolution, opt_anchor); + view.setCenter(center); + } + view.setResolution(resolution); + } + } +} + +/* harmony default export */ var interaction_Interaction = (Interaction_Interaction); + +//# sourceMappingURL=Interaction.js.map +// CONCATENATED MODULE: ./node_modules/ol/interaction/DoubleClickZoom.js +/** + * @module ol/interaction/DoubleClickZoom + */ + + + + +/** + * @typedef {Object} Options + * @property {number} [duration=250] Animation duration in milliseconds. + * @property {number} [delta=1] The zoom delta applied on each double click. + */ + + +/** + * @classdesc + * Allows the user to zoom by double-clicking on the map. + * @api + */ +var DoubleClickZoom = /*@__PURE__*/(function (Interaction) { + function DoubleClickZoom(opt_options) { + Interaction.call(this, { + handleEvent: DoubleClickZoom_handleEvent + }); + + var options = opt_options ? opt_options : {}; + + /** + * @private + * @type {number} + */ + this.delta_ = options.delta ? options.delta : 1; + + /** + * @private + * @type {number} + */ + this.duration_ = options.duration !== undefined ? options.duration : 250; + + } + + if ( Interaction ) DoubleClickZoom.__proto__ = Interaction; + DoubleClickZoom.prototype = Object.create( Interaction && Interaction.prototype ); + DoubleClickZoom.prototype.constructor = DoubleClickZoom; + + return DoubleClickZoom; +}(interaction_Interaction)); + + +/** + * Handles the {@link module:ol/MapBrowserEvent map browser event} (if it was a + * doubleclick) and eventually zooms the map. + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} `false` to stop event propagation. + * @this {DoubleClickZoom} + */ +function DoubleClickZoom_handleEvent(mapBrowserEvent) { + var stopEvent = false; + if (mapBrowserEvent.type == MapBrowserEventType.DBLCLICK) { + var browserEvent = /** @type {MouseEvent} */ (mapBrowserEvent.originalEvent); + var map = mapBrowserEvent.map; + var anchor = mapBrowserEvent.coordinate; + var delta = browserEvent.shiftKey ? -this.delta_ : this.delta_; + var view = map.getView(); + zoomByDelta(view, delta, anchor, this.duration_); + mapBrowserEvent.preventDefault(); + stopEvent = true; + } + return !stopEvent; +} + +/* harmony default export */ var interaction_DoubleClickZoom = (DoubleClickZoom); + +//# sourceMappingURL=DoubleClickZoom.js.map +// CONCATENATED MODULE: ./node_modules/ol/events/condition.js +/** + * @module ol/events/condition + */ + + + + + + +/** + * A function that takes an {@link module:ol/MapBrowserEvent} and returns a + * `{boolean}`. If the condition is met, true should be returned. + * + * @typedef {function(this: ?, import("../MapBrowserEvent.js").default): boolean} Condition + */ + + +/** + * Return `true` if only the alt-key is pressed, `false` otherwise (e.g. when + * additionally the shift-key is pressed). + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if only the alt key is pressed. + * @api + */ +var altKeyOnly = function(mapBrowserEvent) { + var originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent); + return ( + originalEvent.altKey && + !(originalEvent.metaKey || originalEvent.ctrlKey) && + !originalEvent.shiftKey); +}; + + +/** + * Return `true` if only the alt-key and shift-key is pressed, `false` otherwise + * (e.g. when additionally the platform-modifier-key is pressed). + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if only the alt and shift keys are pressed. + * @api + */ +var altShiftKeysOnly = function(mapBrowserEvent) { + var originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent); + return ( + originalEvent.altKey && + !(originalEvent.metaKey || originalEvent.ctrlKey) && + originalEvent.shiftKey); +}; + + +/** + * Return `true` if the map has the focus. This condition requires a map target + * element with a `tabindex` attribute, e.g. `
`. + * + * @param {import("../MapBrowserEvent.js").default} event Map browser event. + * @return {boolean} The map has the focus. + * @api + */ +var condition_focus = function(event) { + return event.target.getTargetElement() === document.activeElement; +}; + + +/** + * Return always true. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True. + * @api + */ +var always = TRUE; + + +/** + * Return `true` if the event is a `click` event, `false` otherwise. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if the event is a map `click` event. + * @api + */ +var click = function(mapBrowserEvent) { + return mapBrowserEvent.type == MapBrowserEventType.CLICK; +}; + + +/** + * Return `true` if the event has an "action"-producing mouse button. + * + * By definition, this includes left-click on windows/linux, and left-click + * without the ctrl key on Macs. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} The result. + */ +var mouseActionButton = function(mapBrowserEvent) { + var originalEvent = /** @type {MouseEvent} */ (mapBrowserEvent.originalEvent); + return originalEvent.button == 0 && + !(WEBKIT && MAC && originalEvent.ctrlKey); +}; + + +/** + * Return always false. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} False. + * @api + */ +var never = FALSE; + + +/** + * Return `true` if the browser event is a `pointermove` event, `false` + * otherwise. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if the browser event is a `pointermove` event. + * @api + */ +var condition_pointerMove = function(mapBrowserEvent) { + return mapBrowserEvent.type == 'pointermove'; +}; + + +/** + * Return `true` if the event is a map `singleclick` event, `false` otherwise. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if the event is a map `singleclick` event. + * @api + */ +var singleClick = function(mapBrowserEvent) { + return mapBrowserEvent.type == MapBrowserEventType.SINGLECLICK; +}; + + +/** + * Return `true` if the event is a map `dblclick` event, `false` otherwise. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if the event is a map `dblclick` event. + * @api + */ +var doubleClick = function(mapBrowserEvent) { + return mapBrowserEvent.type == MapBrowserEventType.DBLCLICK; +}; + + +/** + * Return `true` if no modifier key (alt-, shift- or platform-modifier-key) is + * pressed. + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True only if there no modifier keys are pressed. + * @api + */ +var noModifierKeys = function(mapBrowserEvent) { + var originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent); + return ( + !originalEvent.altKey && + !(originalEvent.metaKey || originalEvent.ctrlKey) && + !originalEvent.shiftKey); +}; + + +/** + * Return `true` if only the platform-modifier-key (the meta-key on Mac, + * ctrl-key otherwise) is pressed, `false` otherwise (e.g. when additionally + * the shift-key is pressed). + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if only the platform modifier key is pressed. + * @api + */ +var platformModifierKeyOnly = function(mapBrowserEvent) { + var originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent); + return !originalEvent.altKey && + (MAC ? originalEvent.metaKey : originalEvent.ctrlKey) && + !originalEvent.shiftKey; +}; + + +/** + * Return `true` if only the shift-key is pressed, `false` otherwise (e.g. when + * additionally the alt-key is pressed). + * + * @param {import("../MapBrowserEvent.js").default} mapBrowserEvent Map browser event. + * @return {boolean} True if only the shift key is pressed. + * @api + */ +var shiftKeyOnly = function(mapBrowserEvent) { + var originalEvent = /** @type {KeyboardEvent|MouseEvent|TouchEvent} */ (mapBrowserEvent.originalEvent); + return ( + !originalEvent.altKey && + !(originalEvent.metaKey || originalEvent.ctrlKey) && + originalEvent.shiftKey); +}; + + +/** + * Return `true` if the target element is not editable, i.e. not a ``-, + * `