From cc4343cd5aefeee1804c2bcd30084fcc1bfe7690 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Velarde?= Date: Sat, 11 Nov 2017 22:37:16 +0100 Subject: [PATCH] Preparing new v1.4.0 --- CHANGELOG.md | 9 +- README.md | 3 +- dist/leaflet.canvaslayer.field.js | 2718 +------------------------ dist/leaflet.canvaslayer.field.js.map | 2 +- docs/example_ScalarField_Mask.html | 96 + src/_main.js | 2 +- 6 files changed, 106 insertions(+), 2724 deletions(-) create mode 100644 docs/example_ScalarField_Mask.html diff --git a/CHANGELOG.md b/CHANGELOG.md index ebb7c40..a53b545 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,7 +47,8 @@ #v1.3.5 - Added CI testing with travis, thanks to @sirreal (https://github.com/IHCantabria/Leaflet.CanvasLayer.Field/pull/12) -#v1.4.0 in progress... -- Added an optional parameter `spatialMask` to layers. The mask defines a region for which the raster values will be considered (for rendering and identifying operations). - - +#v1.4.0 +- Added an optional parameter `spatialMask` (+ `setSpatialMask` method) to apply a Clip on `ScalarField`. The mask defines a Polygon as a GeoJSON Feature for which the raster values will be considered (for rendering and identifying operations). See `example_ScalarField_Mask`. This feature uses `@turf/inside`. +- Minor: + - examples have been updated to work with Leaflet 1.2.0 + - added a little npm badge in README file diff --git a/README.md b/README.md index ec36984..5fe15e4 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,7 @@ A plugin for [LeafletJS](http://www.leafletjs.com) that adds layers to visualize **[Leaflet.CanvasLayer.Field EXAMPLES](https://ihcantabria.github.io/Leaflet.CanvasLayer.Field/)** ![Travis CI](https://travis-ci.org/IHCantabria/Leaflet.CanvasLayer.Field.svg?branch=master) +[![npm version](https://badge.fury.io/js/leaflet-canvaslayer-field.svg)](https://badge.fury.io/js/leaflet-canvaslayer-field) It includes: * `L.CanvasLayer.ScalarField` - a "typical" raster layer (from scalars such as DTM, temperature...) that can be rendered with different color scales and arrows. @@ -35,7 +36,7 @@ If you want to have a quick testing environment, have a look at these **snippets 2. Include the JavaScript dependencies in your page: ```html - + diff --git a/dist/leaflet.canvaslayer.field.js b/dist/leaflet.canvaslayer.field.js index 4dbbc14..71d3f7b 100644 --- a/dist/leaflet.canvaslayer.field.js +++ b/dist/leaflet.canvaslayer.field.js @@ -1,2718 +1,2 @@ -/******/ (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; -/******/ -/******/ // identity function for calling harmony imports with the correct context -/******/ __webpack_require__.i = function(value) { return value; }; -/******/ -/******/ // define getter function for harmony exports -/******/ __webpack_require__.d = function(exports, name, getter) { -/******/ if(!__webpack_require__.o(exports, name)) { -/******/ Object.defineProperty(exports, name, { -/******/ configurable: false, -/******/ enumerable: true, -/******/ get: getter -/******/ }); -/******/ } -/******/ }; -/******/ -/******/ // 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 = 13); -/******/ }) -/************************************************************************/ -/******/ ([ -/* 0 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * Simple regular cell in a raster - */ -var Cell = function () { - /** - * A simple cell with a numerical value - * @param {L.LatLng} center - * @param {Number|Vector} value - * @param {Number} xSize - * @param {Number} ySize - */ - function Cell(center, value, xSize) { - var ySize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : xSize; - - _classCallCheck(this, Cell); - - this.center = center; - this.value = value; - this.xSize = xSize; - this.ySize = ySize; - } - - _createClass(Cell, [{ - key: "equals", - value: function equals(anotherCell) { - return this.center.equals(anotherCell.center) && this._equalValues(this.value, anotherCell.value) && this.xSize === anotherCell.xSize && this.ySize === anotherCell.ySize; - } - }, { - key: "_equalValues", - value: function _equalValues(value, anotherValue) { - var type = value.constructor.name; - var answerFor = { - Number: value === anotherValue, - Vector: value.u === anotherValue.u && value.v === anotherValue.v - }; - return answerFor[type]; - } - - /** - * Bounds for the cell - * @returns {LatLngBounds} - */ - - }, { - key: "getBounds", - value: function getBounds() { - var halfX = this.xSize / 2.0; - var halfY = this.ySize / 2.0; - var cLat = this.center.lat; - var cLng = this.center.lng; - var ul = L.latLng([cLat + halfY, cLng - halfX]); - var lr = L.latLng([cLat - halfY, cLng + halfX]); - - return L.latLngBounds(L.latLng(lr.lat, ul.lng), L.latLng(ul.lat, lr.lng)); - } - }]); - - return Cell; -}(); - -/* harmony default export */ __webpack_exports__["a"] = (Cell); - -/***/ }), -/* 1 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Cell__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__turf_inside__ = __webpack_require__(11); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__turf_inside___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__turf_inside__); -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - - - - -/** - * Abstract class for a set of values (Vector | Scalar) - * assigned to a regular 2D-grid (lon-lat), aka 'a Raster source' - */ - -var Field = function () { - function Field(params) { - _classCallCheck(this, Field); - - this.params = params; - - this.nCols = params['nCols']; - this.nRows = params['nRows']; - - // alias - this.width = params['nCols']; - this.height = params['nRows']; - - // ll = lower-left - this.xllCorner = params['xllCorner']; - this.yllCorner = params['yllCorner']; - - // ur = upper-right - this.xurCorner = params['xllCorner'] + params['nCols'] * params['cellXSize']; - this.yurCorner = params['yllCorner'] + params['nRows'] * params['cellYSize']; - - this.cellXSize = params['cellXSize']; - this.cellYSize = params['cellYSize']; - - this.grid = null; // to be defined by subclasses - this.isContinuous = this.xurCorner - this.xllCorner >= 360; - this.longitudeNeedsToBeWrapped = this.xurCorner > 180; // [0, 360] --> [-180, 180] - - this._inFilter = null; - this._spatialMask = null; - } - - /** - * Builds a grid with a value at each point (either Vector or Number) - * Original params must include the required input values, following - * x-ascending & y-descending order (same as in ASCIIGrid) - * @abstract - * @private - * @returns {Array.>} - grid[row][column]--> Vector|Number - */ - - - _createClass(Field, [{ - key: '_buildGrid', - value: function _buildGrid() { - throw new TypeError('Must be overriden'); - } - }, { - key: '_updateRange', - value: function _updateRange() { - this.range = this._calculateRange(); - } - - /** - * Number of cells in the grid (rows * cols) - * @returns {Number} - */ - - }, { - key: 'numCells', - value: function numCells() { - return this.nRows * this.nCols; - } - - /** - * A list with every cell - * @returns {Array} - cells (x-ascending & y-descending order) - */ - - }, { - key: 'getCells', - value: function getCells() { - var stride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1; - - var cells = []; - for (var j = 0; j < this.nRows; j = j + stride) { - for (var i = 0; i < this.nCols; i = i + stride) { - var _lonLatAtIndexes2 = this._lonLatAtIndexes(i, j), - _lonLatAtIndexes3 = _slicedToArray(_lonLatAtIndexes2, 2), - lon = _lonLatAtIndexes3[0], - lat = _lonLatAtIndexes3[1]; - - var center = L.latLng(lat, lon); - var value = this._valueAtIndexes(i, j); - var c = new __WEBPACK_IMPORTED_MODULE_0__Cell__["a" /* default */](center, value, this.cellXSize, this.cellYSize); - cells.push(c); // << - } - } - return cells; - } - - /** - * Apply a filter function to field values - * @param {Function} f - boolean function - */ - - }, { - key: 'setFilter', - value: function setFilter(f) { - this._inFilter = f; - this._updateRange(); - } - - /** - * Apply a spatial mask to field values - * @param {L.GeoJSON} m - */ - - }, { - key: 'setSpatialMask', - value: function setSpatialMask(m) { - this._spatialMask = m; - } - - /** - * Grid extent - * @returns {Number[]} [xmin, ymin, xmax, ymax] - */ - - }, { - key: 'extent', - value: function extent() { - var _getWrappedLongitudes2 = this._getWrappedLongitudes(), - _getWrappedLongitudes3 = _slicedToArray(_getWrappedLongitudes2, 2), - xmin = _getWrappedLongitudes3[0], - xmax = _getWrappedLongitudes3[1]; - - return [xmin, this.yllCorner, xmax, this.yurCorner]; - } - - /** - * [xmin, xmax] in [-180, 180] range - */ - - }, { - key: '_getWrappedLongitudes', - value: function _getWrappedLongitudes() { - var xmin = this.xllCorner; - var xmax = this.xurCorner; - - if (this.longitudeNeedsToBeWrapped) { - if (this.isContinuous) { - xmin = -180; - xmax = 180; - } else { - // not sure about this (just one particular case, but others...?) - xmax = this.xurCorner - 360; - xmin = this.xllCorner - 360; - /* eslint-disable no-console */ - // console.warn(`are these xmin: ${xmin} & xmax: ${xmax} OK?`); - // TODO: Better throw an exception on no-controlled situations. - /* eslint-enable no-console */ - } - } - return [xmin, xmax]; - } - - /** - * Returns whether or not the grid contains the point, considering - * the spatialMask if it has been previously set - * @param {Number} lon - longitude - * @param {Number} lat - latitude - * @returns {Boolean} - */ - - }, { - key: 'contains', - value: function contains(lon, lat) { - if (this._spatialMask) { - return this._pointInMask(lon, lat); - } - return this._pointInExtent(lon, lat); - } - - /** - * Checks if coordinates are inside the Extent (considering wrapped longitudes if needed) - * @param {Number} lon - * @param {Number} lat - */ - - }, { - key: '_pointInExtent', - value: function _pointInExtent(lon, lat) { - var _getWrappedLongitudes4 = this._getWrappedLongitudes(), - _getWrappedLongitudes5 = _slicedToArray(_getWrappedLongitudes4, 2), - xmin = _getWrappedLongitudes5[0], - xmax = _getWrappedLongitudes5[1]; - - var longitudeIn = lon >= xmin && lon <= xmax; - var latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner; - return longitudeIn && latitudeIn; - } - - /** - * Check if coordinates are inside the spatialMask (Point in Polygon analysis) - * @param {Number} lon - * @param {Number} lat - */ - - }, { - key: '_pointInMask', - value: function _pointInMask(lon, lat) { - var pt = { - type: 'Feature', - geometry: { - type: 'Point', - coordinates: [lon, lat] // geojson, lon-lat order ! - }, - properties: {} - }; - var poly = this._spatialMask; - return __WEBPACK_IMPORTED_MODULE_1__turf_inside___default()(pt, poly); - } - - /** - * Returns if the grid doesn't contain the point - * @param {Number} lon - longitude - * @param {Number} lat - latitude - * @returns {Boolean} - */ - - }, { - key: 'notContains', - value: function notContains(lon, lat) { - return !this.contains(lon, lat); - } - - /** - * Interpolated value at lon-lat coordinates (bilinear method) - * @param {Number} longitude - * @param {Number} latitude - * @returns {Vector|Number} [u, v, magnitude] - * - * Source: https://github.com/cambecc/earth > product.js - */ - - }, { - key: 'interpolatedValueAt', - value: function interpolatedValueAt(lon, lat) { - if (this.notContains(lon, lat)) return null; - - var _getDecimalIndexes2 = this._getDecimalIndexes(lon, lat), - _getDecimalIndexes3 = _slicedToArray(_getDecimalIndexes2, 2), - i = _getDecimalIndexes3[0], - j = _getDecimalIndexes3[1]; - - return this.interpolatedValueAtIndexes(i, j); - } - - /** - * Interpolated value at i-j indexes (bilinear method) - * @param {Number} i - * @param {Number} j - * @returns {Vector|Number} [u, v, magnitude] - * - * Source: https://github.com/cambecc/earth > product.js - */ - - }, { - key: 'interpolatedValueAtIndexes', - value: function interpolatedValueAtIndexes(i, j) { - // 1 2 After converting λ and φ to fractional grid indexes i and j, we find the - // fi i ci four points 'G' that enclose point (i, j). These points are at the four - // | =1.4 | corners specified by the floor and ceiling of i and j. For example, given - // ---G--|---G--- fj 8 i = 1.4 and j = 8.3, the four surrounding grid points are (1, 8), (2, 8), - // j ___|_ . | (1, 9) and (2, 9). - // =8.3 | | - // ---G------G--- cj 9 Note that for wrapped grids, the first column is duplicated as the last - // | | column, so the index ci can be used without taking a modulo. - - var indexes = this._getFourSurroundingIndexes(i, j); - - var _indexes = _slicedToArray(indexes, 4), - fi = _indexes[0], - ci = _indexes[1], - fj = _indexes[2], - cj = _indexes[3]; - - var values = this._getFourSurroundingValues(fi, ci, fj, cj); - if (values) { - var _values = _slicedToArray(values, 4), - g00 = _values[0], - g10 = _values[1], - g01 = _values[2], - g11 = _values[3]; - - return this._doInterpolation(i - fi, j - fj, g00, g10, g01, g11); - } - return null; - } - - /** - * Get decimal indexes - * @private - * @param {Number} lon - * @param {Number} lat - * @returns {Array} [[Description]] - */ - - }, { - key: '_getDecimalIndexes', - value: function _getDecimalIndexes(lon, lat) { - if (this.longitudeNeedsToBeWrapped && lon < this.xllCorner) { - lon = lon + 360; - } - var i = (lon - this.xllCorner) / this.cellXSize; - var j = (this.yurCorner - lat) / this.cellYSize; - return [i, j]; - } - - /** - * Get surrounding indexes (integer), clampling on borders - * @private - * @param {Number} i - decimal index - * @param {Number} j - decimal index - * @returns {Array} [fi, ci, fj, cj] - */ - - }, { - key: '_getFourSurroundingIndexes', - value: function _getFourSurroundingIndexes(i, j) { - var fi = Math.floor(i); - var ci = fi + 1; - // duplicate colum to simplify interpolation logic (wrapped value) - if (this.isContinuous && ci >= this.nCols) { - ci = 0; - } - ci = this._clampColumnIndex(ci); - - var fj = this._clampRowIndex(Math.floor(j)); - var cj = this._clampRowIndex(fj + 1); - - return [fi, ci, fj, cj]; - } - - /** - * Get four surrounding values or null if not available, - * from 4 integer indexes - * @private - * @param {Number} fi - * @param {Number} ci - * @param {Number} fj - * @param {Number} cj - * @returns {Array} - */ - - }, { - key: '_getFourSurroundingValues', - value: function _getFourSurroundingValues(fi, ci, fj, cj) { - var row; - if (row = this.grid[fj]) { - // upper row ^^ - var g00 = row[fi]; // << left - var g10 = row[ci]; // right >> - if (this._isValid(g00) && this._isValid(g10) && (row = this.grid[cj])) { - // lower row vv - var g01 = row[fi]; // << left - var g11 = row[ci]; // right >> - if (this._isValid(g01) && this._isValid(g11)) { - return [g00, g10, g01, g11]; // 4 values found! - } - } - } - return null; - } - - /** - * Nearest value at lon-lat coordinates - * @param {Number} longitude - * @param {Number} latitude - * @returns {Vector|Number} - */ - - }, { - key: 'valueAt', - value: function valueAt(lon, lat) { - if (this.notContains(lon, lat)) return null; - - var _getDecimalIndexes4 = this._getDecimalIndexes(lon, lat), - _getDecimalIndexes5 = _slicedToArray(_getDecimalIndexes4, 2), - i = _getDecimalIndexes5[0], - j = _getDecimalIndexes5[1]; - - var ii = Math.floor(i); - var jj = Math.floor(j); - - var ci = this._clampColumnIndex(ii); - var cj = this._clampRowIndex(jj); - - var value = this._valueAtIndexes(ci, cj); - if (this._inFilter) { - if (!this._inFilter(value)) return null; - } - - return value; - } - - /** - * Returns whether or not the field has a value at the point - * @param {Number} lon - longitude - * @param {Number} lat - latitude - * @returns {Boolean} - */ - - }, { - key: 'hasValueAt', - value: function hasValueAt(lon, lat) { - var value = this.valueAt(lon, lat); - var hasValue = value !== null; - - var included = true; - if (this._inFilter) { - included = this._inFilter(value); - } - return hasValue && included; - } - - /** - * Returns if the grid has no value at the point - * @param {Number} lon - longitude - * @param {Number} lat - latitude - * @returns {Boolean} - */ - - }, { - key: 'notHasValueAt', - value: function notHasValueAt(lon, lat) { - return !this.hasValueAt(lon, lat); - } - - /** - * Gives a random position to 'o' inside the grid - * @param {Object} [o] - an object (eg. a particle) - * @returns {{x: Number, y: Number}} - object with x, y (lon, lat) - */ - - }, { - key: 'randomPosition', - value: function randomPosition() { - var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; - - var i = Math.random() * this.nCols | 0; - var j = Math.random() * this.nRows | 0; - - o.x = this._longitudeAtX(i); - o.y = this._latitudeAtY(j); - - return o; - } - - /** - * Value for grid indexes - * @param {Number} i - column index (integer) - * @param {Number} j - row index (integer) - * @returns {Vector|Number} - */ - - }, { - key: '_valueAtIndexes', - value: function _valueAtIndexes(i, j) { - return this.grid[j][i]; // <-- j,i !! - } - - /** - * Lon-Lat for grid indexes - * @param {Number} i - column index (integer) - * @param {Number} j - row index (integer) - * @returns {Number[]} [lon, lat] - */ - - }, { - key: '_lonLatAtIndexes', - value: function _lonLatAtIndexes(i, j) { - var lon = this._longitudeAtX(i); - var lat = this._latitudeAtY(j); - - return [lon, lat]; - } - - /** - * Longitude for grid-index - * @param {Number} i - column index (integer) - * @returns {Number} longitude at the center of the cell - */ - - }, { - key: '_longitudeAtX', - value: function _longitudeAtX(i) { - var halfXPixel = this.cellXSize / 2.0; - var lon = this.xllCorner + halfXPixel + i * this.cellXSize; - if (this.longitudeNeedsToBeWrapped) { - lon = lon > 180 ? lon - 360 : lon; - } - return lon; - } - - /** - * Latitude for grid-index - * @param {Number} j - row index (integer) - * @returns {Number} latitude at the center of the cell - */ - - }, { - key: '_latitudeAtY', - value: function _latitudeAtY(j) { - var halfYPixel = this.cellYSize / 2.0; - return this.yurCorner - halfYPixel - j * this.cellYSize; - } - - /** - * Apply the interpolation - * @abstract - * @private - */ - /* eslint-disable no-unused-vars */ - - }, { - key: '_doInterpolation', - value: function _doInterpolation(x, y, g00, g10, g01, g11) { - throw new TypeError('Must be overriden'); - } - /* eslint-disable no-unused-vars */ - - /** - * Check the column index is inside the field, - * adjusting to min or max when needed - * @private - * @param {Number} ii - index - * @returns {Number} i - inside the allowed indexes - */ - - }, { - key: '_clampColumnIndex', - value: function _clampColumnIndex(ii) { - var i = ii; - if (ii < 0) { - i = 0; - } - var maxCol = this.nCols - 1; - if (ii > maxCol) { - i = maxCol; - } - return i; - } - - /** - * Check the row index is inside the field, - * adjusting to min or max when needed - * @private - * @param {Number} jj index - * @returns {Number} j - inside the allowed indexes - */ - - }, { - key: '_clampRowIndex', - value: function _clampRowIndex(jj) { - var j = jj; - if (jj < 0) { - j = 0; - } - var maxRow = this.nRows - 1; - if (jj > maxRow) { - j = maxRow; - } - return j; - } - - /** - * Is valid (not 'null' nor 'undefined') - * @private - * @param {Object} x object - * @returns {Boolean} - */ - - }, { - key: '_isValid', - value: function _isValid(x) { - return x !== null && x !== undefined; - } - }]); - - return Field; -}(); - -/* harmony default export */ __webpack_exports__["a"] = (Field); - -/***/ }), -/* 2 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Field__ = __webpack_require__(1); -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); - -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - - -/** - * Scalar Field - */ - -var ScalarField = function (_Field) { - _inherits(ScalarField, _Field); - - _createClass(ScalarField, null, [{ - key: 'fromASCIIGrid', - - /** - * Creates a ScalarField from the content of an ASCIIGrid file - * @param {String} asc - * @returns {ScalarField} - */ - value: function fromASCIIGrid(asc) { - var scaleFactor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1; - - //console.time('ScalarField from ASC'); - - var lines = asc.split('\n'); - - // Header - ScalarField._checkIsValidASCIIGridHeader(lines); - - var n = /-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/; // any number - - var cellSize = parseFloat(lines[4].match(n)); // right now, no different x-y size is allowed - var p = { - nCols: parseInt(lines[0].match(n)), - nRows: parseInt(lines[1].match(n)), - xllCorner: parseFloat(lines[2].match(n)), - yllCorner: parseFloat(lines[3].match(n)), - cellXSize: cellSize, - cellYSize: cellSize - }; - var noDataValue = lines[5].toUpperCase().replace('NODATA_VALUE', '').trim(); - - // Data (left-right and top-down) - var zs = []; // TODO Consider using TypedArray (& manage NO_DATA) - for (var i = 6; i < lines.length; i++) { - var line = lines[i].trim(); - if (line === '') break; - - var items = line.split(' '); - items.forEach(function (it) { - var v = it !== noDataValue ? parseFloat(it * scaleFactor) : null; - zs.push(v); - }); - } - p.zs = zs; - - //console.timeEnd('ScalarField from ASC'); - return new ScalarField(p); - } - }, { - key: '_checkIsValidASCIIGridHeader', - value: function _checkIsValidASCIIGridHeader(lines) { - var upperCasesLines = lines.map(function (lin) { - return lin.toUpperCase(); - }); - - var parameters = ['NCOLS', 'NROWS', 'XLLCORNER', 'YLLCORNER', 'CELLSIZE', 'NODATA_VALUE']; - - var i = 0; - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = parameters[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var expected = _step.value; - - var line = upperCasesLines[i]; - var found = line.indexOf(expected) != -1; - if (!found) { - throw 'Not valid ASCIIGrid: expected \'' + expected + '\' at line \'' + line + '\' [lin. n\xBA ' + i + ']'; - } - i++; - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - } - - /** - * Creates a ScalarField from the content of a GeoTIFF file, as read by geotiff.js - * @param {ArrayBuffer} data - * @param {Number} bandIndex - * @returns {ScalarField} - */ - - }, { - key: 'fromGeoTIFF', - value: function fromGeoTIFF(data) { - var bandIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0; - - //console.time('ScalarField from GeoTIFF'); - - var tiff = GeoTIFF.parse(data); // geotiff.js - var image = tiff.getImage(); - var rasters = image.readRasters(); - var tiepoint = image.getTiePoints()[0]; - var fileDirectory = image.getFileDirectory(); - - var _fileDirectory$ModelP = _slicedToArray(fileDirectory.ModelPixelScale, 2), - xScale = _fileDirectory$ModelP[0], - yScale = _fileDirectory$ModelP[1]; - - var zs = rasters[bandIndex]; // left-right and top-down order - - if (fileDirectory.GDAL_NODATA) { - var noData = parseFloat(fileDirectory.GDAL_NODATA); - // console.log(noData); - var simpleZS = Array.from(zs); // to simple array, so null is allowed | TODO efficiency?? - zs = simpleZS.map(function (z) { - return z === noData ? null : z; - }); - } - - var p = { - nCols: image.getWidth(), - nRows: image.getHeight(), - xllCorner: tiepoint.x, - yllCorner: tiepoint.y - image.getHeight() * yScale, - cellXSize: xScale, - cellYSize: yScale, - zs: zs - }; - - //console.timeEnd('ScalarField from GeoTIFF'); - return new ScalarField(p); - } - }]); - - function ScalarField(params) { - _classCallCheck(this, ScalarField); - - var _this = _possibleConstructorReturn(this, (ScalarField.__proto__ || Object.getPrototypeOf(ScalarField)).call(this, params)); - - _this.zs = params['zs']; - - _this.grid = _this._buildGrid(); - _this._updateRange(); - //console.log(`ScalarField created (${this.nCols} x ${this.nRows})`); - return _this; - } - - /** - * Builds a grid with a Number at each point, from an array - * 'zs' following x-ascending & y-descending order - * (same as in ASCIIGrid) - * @private - * @returns {Array.>} - grid[row][column]--> Number - */ - - - _createClass(ScalarField, [{ - key: '_buildGrid', - value: function _buildGrid() { - var grid = this._arrayTo2d(this.zs, this.nRows, this.nCols); - return grid; - } - }, { - key: '_arrayTo2d', - value: function _arrayTo2d(array, nRows, nCols) { - var grid = []; - var p = 0; - for (var j = 0; j < nRows; j++) { - var row = []; - for (var i = 0; i < nCols; i++, p++) { - var z = array[p]; - row[i] = this._isValid(z) ? z : null; // <<< - } - grid[j] = row; - } - return grid; - } - }, { - key: '_newDataArrays', - value: function _newDataArrays(params) { - params['zs'] = []; - } - }, { - key: '_pushValueToArrays', - value: function _pushValueToArrays(params, value) { - params['zs'].push(value); - } - }, { - key: '_makeNewFrom', - value: function _makeNewFrom(params) { - return new ScalarField(params); - } - - /** - * Calculate min & max values - * @private - * @returns {Array} - [min, max] - */ - - }, { - key: '_calculateRange', - value: function _calculateRange() { - var data = this.zs; - if (this._inFilter) { - data = data.filter(this._inFilter); - } - return [d3.min(data), d3.max(data)]; - } - - /** - * Bilinear interpolation for Number - * https://en.wikipedia.org/wiki/Bilinear_interpolation - * @param {Number} x - * @param {Number} y - * @param {Number} g00 - * @param {Number} g10 - * @param {Number} g01 - * @param {Number} g11 - * @returns {Number} - */ - - }, { - key: '_doInterpolation', - value: function _doInterpolation(x, y, g00, g10, g01, g11) { - var rx = 1 - x; - var ry = 1 - y; - return g00 * rx * ry + g10 * x * ry + g01 * rx * y + g11 * x * y; - } - }]); - - return ScalarField; -}(__WEBPACK_IMPORTED_MODULE_0__Field__["a" /* default */]); - -/* harmony default export */ __webpack_exports__["a"] = (ScalarField); - -/***/ }), -/* 3 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -/** - * 2D Vector - */ -var Vector = function () { - function Vector(u, v) { - _classCallCheck(this, Vector); - - this.u = u; - this.v = v; - } - - /** - * Magnitude - * @returns {Number} - */ - - - _createClass(Vector, [{ - key: "magnitude", - value: function magnitude() { - return Math.sqrt(this.u * this.u + this.v * this.v); - } - - /** - * Angle in degrees (0 to 360º) --> Towards - * N is 0º and E is 90º - * @returns {Number} - */ - - }, { - key: "directionTo", - value: function directionTo() { - var verticalAngle = Math.atan2(this.u, this.v); - var inDegrees = verticalAngle * (180.0 / Math.PI); - if (inDegrees < 0) { - inDegrees = inDegrees + 360.0; - } - return inDegrees; - } - - /** - * Angle in degrees (0 to 360º) From x--> - * N is 0º and E is 90º - * @returns {Number} - */ - - }, { - key: "directionFrom", - value: function directionFrom() { - var a = this.directionTo(); - var opposite = (a + 180.0) % 360.0; - return opposite; - } - - /* - Degrees --> text - new Dictionary - { - //{0, 23, 45, 68, 90, 113, 135, 158, 180, 203, 225, 248, 270, 293, 315, 338, 360}; - {0, 'N'}, - {23, 'NNE'}, - {45, 'NE'}, - {68, 'ENE'}, - {90, 'E'}, - {113, 'ESE'}, - {135, 'SE'}, - {158, 'SSE'}, - {180, 'S'}, - {203, 'SSW'}, - {225, 'SW'}, - {248, 'WSW'}, - {270, 'W'}, - {293, 'WNW'}, - {315, 'NW'}, - {338, 'NNW'}, - {360, 'N'} - }; - */ - - }]); - - return Vector; -}(); - -/* harmony default export */ __webpack_exports__["a"] = (Vector); - -/***/ }), -/* 4 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector__ = __webpack_require__(3); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Field__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__ScalarField__ = __webpack_require__(2); -var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } - -function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } - -function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } - - - - - -/** - * A set of vectors assigned to a regular 2D-grid (lon-lat) - * (e.g. a raster representing winds for a region) - */ - -var VectorField = function (_Field) { - _inherits(VectorField, _Field); - - _createClass(VectorField, null, [{ - key: 'fromASCIIGrids', - - /** - * Creates a VectorField from the content of two ASCIIGrid files - * @param {String} ascU - with u-component - * @param {String} ascV - with v-component - * @returns {VectorField} - */ - value: function fromASCIIGrids(ascU, ascV) { - var scaleFactor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1; - - var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromASCIIGrid(ascU, scaleFactor); - var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromASCIIGrid(ascV, scaleFactor); - var p = VectorField._paramsFromScalarFields(u, v); - - return new VectorField(p); - } - - /** - * Creates a VectorField from the content of two different Geotiff files - * @param {ArrayBuffer} gtU - geotiff data with u-component (band 0) - * @param {ArrayBuffer} gtV - geotiff data with v-component (band 0) - * @returns {VectorField} - */ - - }, { - key: 'fromGeoTIFFs', - value: function fromGeoTIFFs(gtU, gtV) { - var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromGeoTIFF(gtU); - var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromGeoTIFF(gtV); - var p = VectorField._paramsFromScalarFields(u, v); - - return new VectorField(p); - } - - /** - * Creates a VectorField from the content of Multiband Geotiff - * @param {ArrayBuffer} geotiffData - multiband - * @param {Array} bandIndexesForUV - * @returns {VectorField} - */ - - }, { - key: 'fromMultibandGeoTIFF', - value: function fromMultibandGeoTIFF(geotiffData) { - var bandIndexesForUV = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 1]; - - var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromGeoTIFF(geotiffData, bandIndexesForUV[0]); - var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */].fromGeoTIFF(geotiffData, bandIndexesForUV[1]); - var p = VectorField._paramsFromScalarFields(u, v); - - return new VectorField(p); - } - - /** - * Build parameters for VectorField, from 2 ScalarFields. - * No validation at all (nor interpolation) is applied, so u and v - * must be 'compatible' from the source - * @param {ScalarField} u - * @param {ScalarField} v - * @returns {Object} - parameters to build VectorField - */ - - }, { - key: '_paramsFromScalarFields', - value: function _paramsFromScalarFields(u, v) { - // TODO check u & v compatibility (cellSize...) - var p = { - nCols: u.nCols, - nRows: u.nRows, - xllCorner: u.xllCorner, - yllCorner: u.yllCorner, - cellXSize: u.cellXSize, - cellYSize: u.cellYSize, - us: u.zs, - vs: v.zs - }; - return p; - } - }]); - - function VectorField(params) { - _classCallCheck(this, VectorField); - - var _this = _possibleConstructorReturn(this, (VectorField.__proto__ || Object.getPrototypeOf(VectorField)).call(this, params)); - - _this.us = params['us']; - _this.vs = params['vs']; - _this.grid = _this._buildGrid(); - _this.range = _this._calculateRange(); - return _this; - } - - /** - * Get a derived field, from a computation on - * the VectorField - * @param {String} type ['magnitude' | 'directionTo' | 'directionFrom'] - * @returns {ScalarField} - */ - - - _createClass(VectorField, [{ - key: 'getScalarField', - value: function getScalarField(type) { - var f = this._getFunctionFor(type); - var p = { - nCols: this.params.nCols, - nRows: this.params.nRows, - xllCorner: this.params.xllCorner, - yllCorner: this.params.yllCorner, - cellXSize: this.params.cellXSize, - cellYSize: this.params.cellYSize, - zs: this._applyOnField(f) - }; - return new __WEBPACK_IMPORTED_MODULE_2__ScalarField__["a" /* default */](p); - } - }, { - key: '_getFunctionFor', - value: function _getFunctionFor(type) { - return function (u, v) { - var uv = new __WEBPACK_IMPORTED_MODULE_0__Vector__["a" /* default */](u, v); - return uv[type](); // magnitude, directionTo, directionFrom - }; - } - }, { - key: '_applyOnField', - value: function _applyOnField(func) { - var zs = []; - var n = this.numCells(); - for (var i = 0; i < n; i++) { - var u = this.us[i]; - var v = this.vs[i]; - if (this._isValid(u) && this._isValid(v)) { - zs.push(func(u, v)); - } else { - zs.push(null); - } - } - return zs; - } - - /** - * Builds a grid with a Vector at each point, from two arrays - * 'us' and 'vs' following x-ascending & y-descending order - * (same as in ASCIIGrid) - * @returns {Array.>} - grid[row][column]--> Vector - */ - - }, { - key: '_buildGrid', - value: function _buildGrid() { - var grid = this._arraysTo2d(this.us, this.vs, this.nRows, this.nCols); - return grid; - } - }, { - key: '_arraysTo2d', - value: function _arraysTo2d(us, vs, nRows, nCols) { - var grid = []; - var p = 0; - - for (var j = 0; j < nRows; j++) { - var row = []; - for (var i = 0; i < nCols; i++, p++) { - var u = us[p], - v = vs[p]; - var valid = this._isValid(u) && this._isValid(v); - row[i] = valid ? new __WEBPACK_IMPORTED_MODULE_0__Vector__["a" /* default */](u, v) : null; // <<< - } - grid[j] = row; - } - return grid; - } - }, { - key: '_newDataArrays', - value: function _newDataArrays(params) { - params['us'] = []; - params['vs'] = []; - } - }, { - key: '_pushValueToArrays', - value: function _pushValueToArrays(params, value) { - //console.log(value); - params['us'].push(value.u); - params['vs'].push(value.v); - } - }, { - key: '_makeNewFrom', - value: function _makeNewFrom(params) { - return new VectorField(params); - } - - /** - * Calculate min & max values (magnitude) - * @private - * @returns {Array} - */ - - }, { - key: '_calculateRange', - value: function _calculateRange() { - // TODO make a clearer method for getting these vectors... - var vectors = this.getCells().map(function (pt) { - return pt.value; - }).filter(function (v) { - return v !== null; - }); - - if (this._inFilter) { - vectors = vectors.filter(this._inFilter); - } - - // TODO check memory crash with high num of vectors! - var magnitudes = vectors.map(function (v) { - return v.magnitude(); - }); - var min = d3.min(magnitudes); - var max = d3.max(magnitudes); - - return [min, max]; - } - - /** - * Bilinear interpolation for Vector - * https://en.wikipedia.org/wiki/Bilinear_interpolation - * @param {Number} x - * @param {Number} y - * @param {Number[]} g00 - * @param {Number[]} g10 - * @param {Number[]} g01 - * @param {Number[]} g11 - * @returns {Vector} - */ - - }, { - key: '_doInterpolation', - value: function _doInterpolation(x, y, g00, g10, g01, g11) { - var rx = 1 - x; - var ry = 1 - y; - var a = rx * ry, - b = x * ry, - c = rx * y, - d = x * y; - var u = g00.u * a + g10.u * b + g01.u * c + g11.u * d; - var v = g00.v * a + g10.v * b + g01.v * c + g11.v * d; - return new __WEBPACK_IMPORTED_MODULE_0__Vector__["a" /* default */](u, v); - } - - /** - * Is valid (not 'null' nor 'undefined') - * @private - * @param {Object} x object - * @returns {Boolean} - */ - - }, { - key: '_isValid', - value: function _isValid(x) { - return x !== null && x !== undefined; - } - }]); - - return VectorField; -}(__WEBPACK_IMPORTED_MODULE_1__Field__["a" /* default */]); - -/* harmony default export */ __webpack_exports__["a"] = (VectorField); - -/***/ }), -/* 5 */ -/***/ (function(module, exports) { - -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); - -/** - * Control for a simple legend with a colorbar - * References: - * - http://jsfiddle.net/ramnathv/g8stqcf6/ - * - http://jsfiddle.net/vis4/cYLZH/ - */ -L.Control.ColorBar = L.Control.extend({ - options: { - position: 'bottomleft', - width: 300, // for colorbar itself (control is wider) - height: 15, - margin: 15, - background: '#fff', - textColor: 'black', - steps: 100, - decimals: 2, - units: 'uds', // ej: m/s - title: 'Legend', // ej: Ocean Currents - labels: [], // empty for no labels - labelFontSize: 10, - labelTextPosition: 'middle' // start | middle | end - }, - - initialize: function initialize(color, range, options) { - this.color = color; // 'chromajs' scale function - this.range = range; // [min, max] - L.Util.setOptions(this, options); - }, - - onAdd: function onAdd(map) { - this._map = map; - var div = L.DomUtil.create('div', 'leaflet-control-colorBar leaflet-bar leaflet-control'); - div.style.padding = '10px'; - - L.DomEvent.addListener(div, 'click', L.DomEvent.stopPropagation).addListener(div, 'click', L.DomEvent.preventDefault); - div.style.backgroundColor = this.options.background; - div.style.cursor = 'text'; - div.innerHTML = this.title() + this.palette(); - return div; - }, - - title: function title() { - var d = document.createElement('div'); - d3.select(d).append('span').style('color', this.options.textColor).style('display', 'block').style('margin-bottom', '5px').attr('class', 'leaflet-control-colorBar-title').text(this.options.title); - return d.innerHTML; - }, - - palette: function palette() { - var d = document.createElement('div'); - var svg = this._createSvgIn(d); - - this._appendColorBarTo(svg); - - if (this.options.labels) { - this._appendLabelsTo(svg); - } - - return d.innerHTML; - }, - - _createSvgIn: function _createSvgIn(d) { - var spaceForLabels = this.options.labels ? this.options.margin : 0; - var svg = d3.select(d).append('svg').attr('width', this.options.width + this.options.margin * 2).attr('height', this.options.height + spaceForLabels); - return svg; - }, - - _appendColorBarTo: function _appendColorBarTo(svg) { - var _this = this; - - var colorPerValue = this._getColorPerValue(); - var w = this.options.width / colorPerValue.length; - - var groupBars = svg.append('g').attr('id', 'colorBar-buckets'); - var buckets = groupBars.selectAll('rect').data(colorPerValue).enter().append('rect'); - buckets.attr('x', function (d, i) { - return i * w + _this.options.margin; - }).attr('y', function () { - return 0; - }).attr('height', function () { - return _this.options.height; - } /*w * 4*/).attr('width', function () { - return w; - }).attr('stroke-width', 2).attr('stroke-linecap', 'butt').attr('stroke', function (d) { - return d.color.hex(); - }).attr('fill', function (d) { - return d.color.hex(); - }); - buckets.append('title').text(function (d) { - return d.value.toFixed(_this.options.decimals) + ' ' + _this.options.units; - }); - }, - - _appendLabelsTo: function _appendLabelsTo(svg) { - var _this2 = this; - - var positionPerLabelValue = this._getPositionPerLabelValue(); - //const w = this.options.width / colorPerValue.length; - var groupLabels = svg.append('g').attr('id', 'colorBar-labels'); - var labels = groupLabels.selectAll('text').data(positionPerLabelValue).enter().append('text'); - labels.attr('x', function (d) { - return d.position + _this2.options.margin; - }).attr('y', this.options.height + this.options.margin).attr('font-size', this.options.labelFontSize + 'px').attr('text-anchor', this.options.labelTextPosition).attr('fill', this.options.textColor).attr('class', 'leaflet-control-colorBar-label').text(function (d) { - return '' + d.value.toFixed(_this2.options.decimals); - }); - }, - - _getColorPerValue: function _getColorPerValue() { - var _this3 = this; - - var _range = _slicedToArray(this.range, 2), - min = _range[0], - max = _range[1]; - - var delta = (max - min) / this.options.steps; - var data = d3.range(min, max + delta, delta); - var colorPerValue = data.map(function (d) { - return { - value: d, - color: _this3.color(d) - }; - }); - return colorPerValue; - }, - - _getPositionPerLabelValue: function _getPositionPerLabelValue() { - var xPositionFor = d3.scaleLinear().range([0, this.options.width]).domain(this.range); - var data = this.options.labels; - var positionPerLabel = data.map(function (d) { - return { - value: d, - position: xPositionFor(d) - }; - }); - return positionPerLabel; - } -}); - -L.control.colorBar = function (color, range, options) { - return new L.Control.ColorBar(color, range, options); -}; - -/***/ }), -/* 6 */ -/***/ (function(module, exports) { - -/** - * Abstract class for a Field layer on canvas, aka 'a Raster layer' - * (ScalarField or a VectorField) - */ -L.CanvasLayer.Field = L.CanvasLayer.extend({ - options: { - mouseMoveCursor: { - value: 'pointer', - noValue: 'default' - }, - opacity: 1, - onClick: null, - onMouseMove: null, - inFilter: null - }, - - initialize: function initialize(field, options) { - L.Util.setOptions(this, options); - this._visible = true; - if (field) { - this.setData(field); - } - }, - - getEvents: function getEvents() { - var events = L.CanvasLayer.prototype.getEvents.call(this); - events.zoomstart = this._hideCanvas.bind(this); - events.zoomend = this._showCanvas.bind(this); - return events; - }, - - onLayerDidMount: function onLayerDidMount() { - this._enableIdentify(); - this._ensureCanvasAlignment(); - }, - - show: function show() { - this._visible = true; - this._showCanvas(); - this._enableIdentify(); - }, - hide: function hide() { - this._visible = false; - this._hideCanvas(); - this._disableIdentify(); - }, - isVisible: function isVisible() { - return this._visible; - }, - _showCanvas: function _showCanvas() { - if (this._canvas && this._visible) { - this._canvas.style.visibility = 'visible'; - } - }, - _hideCanvas: function _hideCanvas() { - if (this._canvas) { - this._canvas.style.visibility = 'hidden'; - } - }, - _enableIdentify: function _enableIdentify() { - this._map.on('click', this._onClick, this); - this._map.on('mousemove', this._onMouseMove, this); - - this.options.onClick && this.on('click', this.options.onClick, this); - this.options.onMouseMove && this.on('mousemove', this.options.onMouseMove, this); - }, - _disableIdentify: function _disableIdentify() { - this._map.off('click', this._onClick, this); - this._map.off('mousemove', this._onMouseMove, this); - - this.options.onClick && this.off('click', this.options.onClick, this); - this.options.onMouseMove && this.off('mousemove', this.options.onMouseMove, this); - }, - _ensureCanvasAlignment: function _ensureCanvasAlignment() { - var topLeft = this._map.containerPointToLayerPoint([0, 0]); - L.DomUtil.setPosition(this._canvas, topLeft); - }, - - - onLayerWillUnmount: function onLayerWillUnmount() { - this._disableIdentify(); - }, - - needRedraw: function needRedraw() { - if (this._map && this._field) { - L.CanvasLayer.prototype.needRedraw.call(this); - } - }, - - - /* eslint-disable no-unused-vars */ - onDrawLayer: function onDrawLayer(viewInfo) { - throw new TypeError('Must be overriden'); - }, - /* eslint-enable no-unused-vars */ - - setData: function setData(field) { - this.options.inFilter && field.setFilter(this.options.inFilter); - this._field = field; - this.needRedraw(); - this.fire('load'); - }, - - setFilter: function setFilter(f) { - this.options.inFilter = f; - this._field && this._field.setFilter(f); - this.needRedraw(); - }, - - setOpacity: function setOpacity(opacity) { - this.options.opacity = opacity; - - if (this._canvas) { - this._updateOpacity(); - } - return this; - }, - - getBounds: function getBounds() { - var bb = this._field.extent(); - - var southWest = L.latLng(bb[1], bb[0]), - northEast = L.latLng(bb[3], bb[2]); - var bounds = L.latLngBounds(southWest, northEast); - return bounds; - }, - - _onClick: function _onClick(e) { - var v = this._queryValue(e); - this.fire('click', v); - }, - - _onMouseMove: function _onMouseMove(e) { - var v = this._queryValue(e); - this._changeCursorOn(v); - this.fire('mousemove', v); - }, - - _changeCursorOn: function _changeCursorOn(v) { - if (!this.options.mouseMoveCursor) return; - - var _options$mouseMoveCur = this.options.mouseMoveCursor, - value = _options$mouseMoveCur.value, - noValue = _options$mouseMoveCur.noValue; - - var style = this._map.getContainer().style; - style.cursor = v.value !== null ? value : noValue; - }, - - _updateOpacity: function _updateOpacity() { - L.DomUtil.setOpacity(this._canvas, this.options.opacity); - }, - - _queryValue: function _queryValue(e) { - var v = this._field ? this._field.valueAt(e.latlng.lng, e.latlng.lat) : null; - var result = { - latlng: e.latlng, - value: v - }; - return result; - }, - - _getDrawingContext: function _getDrawingContext() { - var g = this._canvas.getContext('2d'); - g.clearRect(0, 0, this._canvas.width, this._canvas.height); - return g; - } -}); - -/***/ }), -/* 7 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Cell__ = __webpack_require__(0); -var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); - - - -/** - * ScalarField on canvas (a 'Raster') - */ -L.CanvasLayer.ScalarField = L.CanvasLayer.Field.extend({ - options: { - type: 'colormap', // [colormap|vector] - color: null, // function colorFor(value) [e.g. chromajs.scale], - interpolate: false, // Change to use interpolation - vectorSize: 20, // only used if 'vector' - arrowDirection: 'from' // [from|towards] - }, - - initialize: function initialize(scalarField, options) { - L.CanvasLayer.Field.prototype.initialize.call(this, scalarField, options); - L.Util.setOptions(this, options); - }, - - _defaultColorScale: function _defaultColorScale() { - return chroma.scale(['white', 'black']).domain(this._field.range); - }, - - setColor: function setColor(f) { - this.options.color = f; - this.needRedraw(); - }, - - - /* eslint-disable no-unused-vars */ - onDrawLayer: function onDrawLayer(viewInfo) { - if (!this.isVisible()) return; - this._updateOpacity(); - - var r = this._getRendererMethod(); - //console.time('onDrawLayer'); - r(); - //console.timeEnd('onDrawLayer'); - }, - /* eslint-enable no-unused-vars */ - - _getRendererMethod: function _getRendererMethod() { - switch (this.options.type) { - case 'colormap': - return this._drawImage.bind(this); - case 'vector': - return this._drawArrows.bind(this); - default: - throw Error('Unkwown renderer type: ' + this.options.type); - } - }, - - _ensureColor: function _ensureColor() { - if (this.options.color === null) { - this.setColor(this._defaultColorScale()); - } - }, - - _showCanvas: function _showCanvas() { - L.CanvasLayer.Field.prototype._showCanvas.call(this); - this.needRedraw(); // TODO check spurious redraw (e.g. hide/show without moving map) - }, - - - /** - * Draws the field in an ImageData and applying it with putImageData. - * Used as a reference: http://geoexamples.com/d3-raster-tools-docs/code_samples/raster-pixels-page.html - */ - _drawImage: function _drawImage() { - this._ensureColor(); - - var ctx = this._getDrawingContext(); - var width = this._canvas.width; - var height = this._canvas.height; - - var img = ctx.createImageData(width, height); - var data = img.data; - - this._prepareImageIn(data, width, height); - ctx.putImageData(img, 0, 0); - }, - - /** - * Prepares the image in data, as array with RGBAs - * [R1, G1, B1, A1, R2, G2, B2, A2...] - * @private - * @param {[[Type]]} data [[Description]] - * @param {Numver} width - * @param {Number} height - */ - _prepareImageIn: function _prepareImageIn(data, width, height) { - var f = this.options.interpolate ? 'interpolatedValueAt' : 'valueAt'; - - var pos = 0; - for (var j = 0; j < height; j++) { - for (var i = 0; i < width; i++) { - var pointCoords = this._map.containerPointToLatLng([i, j]); - var lon = pointCoords.lng; - var lat = pointCoords.lat; - - var v = this._field[f](lon, lat); // 'valueAt' | 'interpolatedValueAt' || TODO check some 'artifacts' - if (v !== null) { - var color = this._getColorFor(v); - - var _color$rgba = color.rgba(), - _color$rgba2 = _slicedToArray(_color$rgba, 4), - R = _color$rgba2[0], - G = _color$rgba2[1], - B = _color$rgba2[2], - A = _color$rgba2[3]; - - data[pos] = R; - data[pos + 1] = G; - data[pos + 2] = B; - data[pos + 3] = parseInt(A * 255); // not percent in alpha but hex 0-255 - } - pos = pos + 4; - } - } - }, - - - /** - * Draws the field as a set of arrows. Direction from 0 to 360 is assumed. - */ - _drawArrows: function _drawArrows() { - var bounds = this._pixelBounds(); - var pixelSize = (bounds.max.x - bounds.min.x) / this._field.nCols; - - var stride = Math.max(1, Math.floor(1.2 * this.options.vectorSize / pixelSize)); - - var ctx = this._getDrawingContext(); - ctx.strokeStyle = this.options.color; - - var currentBounds = this._map.getBounds(); - - for (var y = 0; y < this._field.height; y = y + stride) { - for (var x = 0; x < this._field.width; x = x + stride) { - var _field$_lonLatAtIndex = this._field._lonLatAtIndexes(x, y), - _field$_lonLatAtIndex2 = _slicedToArray(_field$_lonLatAtIndex, 2), - lon = _field$_lonLatAtIndex2[0], - lat = _field$_lonLatAtIndex2[1]; - - var v = this._field.valueAt(lon, lat); - var center = L.latLng(lat, lon); - if (v !== null && currentBounds.contains(center)) { - var cell = new __WEBPACK_IMPORTED_MODULE_0__Cell__["a" /* default */](center, v, this.cellXSize, this.cellYSize); - this._drawArrow(cell, ctx); - } - } - } - }, - - _pixelBounds: function _pixelBounds() { - var bounds = this.getBounds(); - var northWest = this._map.latLngToContainerPoint(bounds.getNorthWest()); - var southEast = this._map.latLngToContainerPoint(bounds.getSouthEast()); - var pixelBounds = L.bounds(northWest, southEast); - return pixelBounds; - }, - - _drawArrow: function _drawArrow(cell, ctx) { - var projected = this._map.latLngToContainerPoint(cell.center); - - // colormap vs. simple color - var color = this.options.color; - if (typeof color === 'function') { - ctx.strokeStyle = color(cell.value); - } - - var size = this.options.vectorSize; - ctx.save(); - - ctx.translate(projected.x, projected.y); - - var rotationRads = (90 + cell.value) * Math.PI / 180; // from, by default - if (this.options.arrowDirection === 'towards') { - rotationRads = rotationRads + Math.PI; - } - ctx.rotate(rotationRads); - - ctx.beginPath(); - ctx.moveTo(-size / 2, 0); - ctx.lineTo(+size / 2, 0); - ctx.moveTo(size * 0.25, -size * 0.25); - ctx.lineTo(+size / 2, 0); - ctx.lineTo(size * 0.25, size * 0.25); - ctx.stroke(); - ctx.restore(); - }, - - /** - * Gets a chroma color for a pixel value, according to 'options.color' - */ - _getColorFor: function _getColorFor(v) { - var c = this.options.color; // e.g. for a constant 'red' - if (typeof c === 'function') { - c = this.options.color(v); - } - var color = chroma(c); // to be more flexible, a chroma color object is always created || TODO improve efficiency - return color; - } -}); - -L.canvasLayer.scalarField = function (scalarField, options) { - return new L.CanvasLayer.ScalarField(scalarField, options); -}; - -/***/ }), -/* 8 */ -/***/ (function(module, exports) { - -function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } } - -/** - * Simple layer with lon-lat points - * - * TODO rename to SimplePoint? - */ -L.CanvasLayer.SimpleLonLat = L.CanvasLayer.extend({ - options: { - color: 'gray' - }, - - initialize: function initialize(points, options) { - this.points = points; - L.Util.setOptions(this, options); - }, - - onLayerDidMount: function onLayerDidMount() { - // -- prepare custom drawing - }, - - onLayerWillUnmount: function onLayerWillUnmount() { - // -- custom cleanup - }, - - /* eslint-disable no-unused-vars */ - setData: function setData(data) { - // -- custom data set - this.needRedraw(); // -- call to drawLayer - }, - /* eslint-enable no-unused-vars */ - - onDrawLayer: function onDrawLayer(viewInfo) { - // canvas preparation - var g = viewInfo.canvas.getContext('2d'); - g.clearRect(0, 0, viewInfo.canvas.width, viewInfo.canvas.height); - g.fillStyle = this.options.color; - - var _iteratorNormalCompletion = true; - var _didIteratorError = false; - var _iteratorError = undefined; - - try { - for (var _iterator = this.points[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { - var point = _step.value; - - var p = viewInfo.layer._map.latLngToContainerPoint(point); - g.beginPath(); - //g.arc(p.x, p.y, 1, 0, Math.PI * 2); // circle | TODO style 'function' as parameter? - g.fillRect(p.x, p.y, 2, 2); //simple point - g.fill(); - g.closePath(); - g.stroke(); - } - } catch (err) { - _didIteratorError = true; - _iteratorError = err; - } finally { - try { - if (!_iteratorNormalCompletion && _iterator.return) { - _iterator.return(); - } - } finally { - if (_didIteratorError) { - throw _iteratorError; - } - } - } - }, - - getBounds: function getBounds() { - // TODO: bounding with points... - var xs = this.points.map(function (pt) { - return pt.lng; - }); - var ys = this.points.map(function (pt) { - return pt.lat; - }); - - var xmin = Math.min.apply(Math, _toConsumableArray(xs)); - var ymin = Math.min.apply(Math, _toConsumableArray(ys)); - var xmax = Math.max.apply(Math, _toConsumableArray(xs)); - var ymax = Math.max.apply(Math, _toConsumableArray(ys)); - - var southWest = L.latLng(ymin, xmin), - northEast = L.latLng(ymax, xmax); - var bounds = L.latLngBounds(southWest, northEast); // TODO FIX ERROR ? half-pixel? - return bounds; - } -}); - -L.canvasLayer.simpleLonLat = function (lonslats, options) { - return new L.CanvasLayer.SimpleLonLat(lonslats, options); -}; - -/***/ }), -/* 9 */ -/***/ (function(module, exports) { - -/** - * Animated VectorField on canvas - */ -L.CanvasLayer.VectorFieldAnim = L.CanvasLayer.Field.extend({ - options: { - paths: 800, - color: 'white', // html-color | function colorFor(value) [e.g. chromajs.scale] - width: 1.0, // number | function widthFor(value) - fade: 0.96, // 0 to 1 - duration: 20, // milliseconds per 'frame' - maxAge: 200, // number of maximum frames per path - velocityScale: 1 / 5000 - }, - - initialize: function initialize(vectorField, options) { - L.CanvasLayer.Field.prototype.initialize.call(this, vectorField, options); - L.Util.setOptions(this, options); - - this.timer = null; - }, - - onLayerDidMount: function onLayerDidMount() { - L.CanvasLayer.Field.prototype.onLayerDidMount.call(this); - this._map.on('move resize', this._stopAnimation, this); - }, - - onLayerWillUnmount: function onLayerWillUnmount() { - L.CanvasLayer.Field.prototype.onLayerWillUnmount.call(this); - this._map.off('move resize', this._stopAnimation, this); - this._stopAnimation(); - }, - - _hideCanvas: function _showCanvas() { - L.CanvasLayer.Field.prototype._hideCanvas.call(this); - this._stopAnimation(); - }, - - onDrawLayer: function onDrawLayer(viewInfo) { - if (!this._field || !this.isVisible()) return; - - this._updateOpacity(); - - var ctx = this._getDrawingContext(); - var paths = this._prepareParticlePaths(); - - this.timer = d3.timer(function () { - _moveParticles(); - _drawParticles(); - }, this.options.duration); - - var self = this; - - /** - * Builds the paths, adding 'particles' on each animation step, considering - * their properties (age / position source > target) - */ - function _moveParticles() { - // let screenFactor = 1 / self._map.getZoom(); // consider using a 'screenFactor' to ponderate velocityScale - paths.forEach(function (par) { - if (par.age > self.options.maxAge) { - // restart, on a random x,y - par.age = 0; - self._field.randomPosition(par); - } - - var vector = self._field.valueAt(par.x, par.y); - if (vector === null) { - par.age = self.options.maxAge; - } else { - // the next point will be... - var xt = par.x + vector.u * self.options.velocityScale; //* screenFactor; - var yt = par.y + vector.v * self.options.velocityScale; //* screenFactor; - - if (self._field.hasValueAt(xt, yt)) { - par.xt = xt; - par.yt = yt; - par.m = vector.magnitude(); - } else { - // not visible anymore... - par.age = self.options.maxAge; - } - } - par.age += 1; - }); - } - - /** - * Draws the paths on each step - */ - function _drawParticles() { - // Previous paths... - var prev = ctx.globalCompositeOperation; - ctx.globalCompositeOperation = 'destination-in'; - ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height); - //ctx.globalCompositeOperation = 'source-over'; - ctx.globalCompositeOperation = prev; - - // fading paths... - ctx.fillStyle = 'rgba(0, 0, 0, ' + self.options.fade + ')'; - ctx.lineWidth = self.options.width; - ctx.strokeStyle = self.options.color; - - // New paths - paths.forEach(function (par) { - self._drawParticle(viewInfo, ctx, par); - }); - } - }, - - _drawParticle: function _drawParticle(viewInfo, ctx, par) { - var source = new L.latLng(par.y, par.x); - var target = new L.latLng(par.yt, par.xt); - - if (viewInfo.bounds.contains(source) && par.age <= this.options.maxAge) { - var pA = viewInfo.layer._map.latLngToContainerPoint(source); - var pB = viewInfo.layer._map.latLngToContainerPoint(target); - - ctx.beginPath(); - ctx.moveTo(pA.x, pA.y); - ctx.lineTo(pB.x, pB.y); - - // next-step movement - par.x = par.xt; - par.y = par.yt; - - // colormap vs. simple color - var color = this.options.color; - if (typeof color === 'function') { - ctx.strokeStyle = color(par.m); - } - - var width = this.options.width; - if (typeof width === 'function') { - ctx.lineWidth = width(par.m); - } - - ctx.stroke(); - } - }, - - - _prepareParticlePaths: function _prepareParticlePaths() { - var paths = []; - - for (var i = 0; i < this.options.paths; i++) { - var p = this._field.randomPosition(); - p.age = this._randomAge(); - paths.push(p); - } - return paths; - }, - - _randomAge: function _randomAge() { - return Math.floor(Math.random() * this.options.maxAge); - }, - - _stopAnimation: function _stopAnimation() { - if (this.timer) { - this.timer.stop(); - } - } -}); - -L.canvasLayer.vectorFieldAnim = function (vectorField, options) { - return new L.CanvasLayer.VectorFieldAnim(vectorField, options); -}; - -/***/ }), -/* 10 */ -/***/ (function(module, exports) { - -/* - 1.0.1 (downloaded from https://github.com/Sumbera/gLayers.Leaflet/releases/tag/v1.0.1) - - Generic Canvas Layer for leaflet 0.7 and 1.0-rc, - copyright Stanislav Sumbera, 2016 , sumbera.com , license MIT - originally created and motivated by L.CanvasOverlay available here: https://gist.github.com/Sumbera/11114288 -*/ - -L.CanvasLayer = L.Layer.extend({ - // -- initialized is called on prototype - initialize: function initialize(options) { - this._map = null; - this._canvas = null; - this._frame = null; - this._delegate = null; - L.setOptions(this, options); - }, - - delegate: function delegate(del) { - this._delegate = del; - return this; - }, - - needRedraw: function needRedraw() { - if (!this._frame) { - this._frame = L.Util.requestAnimFrame(this.drawLayer, this); - } - return this; - }, - - //------------------------------------------------------------- - _onLayerDidResize: function _onLayerDidResize(resizeEvent) { - this._canvas.width = resizeEvent.newSize.x; - this._canvas.height = resizeEvent.newSize.y; - }, - //------------------------------------------------------------- - _onLayerDidMove: function _onLayerDidMove() { - var topLeft = this._map.containerPointToLayerPoint([0, 0]); - L.DomUtil.setPosition(this._canvas, topLeft); - this.drawLayer(); - }, - //------------------------------------------------------------- - getEvents: function getEvents() { - var events = { - resize: this._onLayerDidResize, - moveend: this._onLayerDidMove - }; - if (this._map.options.zoomAnimation && L.Browser.any3d) { - events.zoomanim = this._animateZoom; - } - - return events; - }, - //------------------------------------------------------------- - onAdd: function onAdd(map) { - this._map = map; - this._canvas = L.DomUtil.create('canvas', 'leaflet-layer'); - this.tiles = {}; - - var size = this._map.getSize(); - this._canvas.width = size.x; - this._canvas.height = size.y; - - var animated = this._map.options.zoomAnimation && L.Browser.any3d; - L.DomUtil.addClass(this._canvas, 'leaflet-zoom-' + (animated ? 'animated' : 'hide')); - - map._panes.overlayPane.appendChild(this._canvas); - - map.on(this.getEvents(), this); - - var del = this._delegate || this; - del.onLayerDidMount && del.onLayerDidMount(); // -- callback - - this.needRedraw(); - }, - - //------------------------------------------------------------- - onRemove: function onRemove(map) { - var del = this._delegate || this; - del.onLayerWillUnmount && del.onLayerWillUnmount(); // -- callback - - - map.getPanes().overlayPane.removeChild(this._canvas); - - map.off(this.getEvents(), this); - - this._canvas = null; - }, - - //------------------------------------------------------------ - addTo: function addTo(map) { - map.addLayer(this); - return this; - }, - // -------------------------------------------------------------------------------- - LatLonToMercator: function LatLonToMercator(latlon) { - return { - x: latlon.lng * 6378137 * Math.PI / 180, - y: Math.log(Math.tan((90 + latlon.lat) * Math.PI / 360)) * 6378137 - }; - }, - - //------------------------------------------------------------------------------ - drawLayer: function drawLayer() { - // -- todo make the viewInfo properties flat objects. - var size = this._map.getSize(); - var bounds = this._map.getBounds(); - var zoom = this._map.getZoom(); - - var center = this.LatLonToMercator(this._map.getCenter()); - var corner = this.LatLonToMercator(this._map.containerPointToLatLng(this._map.getSize())); - - var del = this._delegate || this; - del.onDrawLayer && del.onDrawLayer({ - layer: this, - canvas: this._canvas, - bounds: bounds, - size: size, - zoom: zoom, - center: center, - corner: corner - }); - this._frame = null; - }, - - //------------------------------------------------------------------------------ - _animateZoom: function _animateZoom(e) { - var scale = this._map.getZoomScale(e.zoom); - var offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), e.zoom, e.center); - - L.DomUtil.setTransform(this._canvas, offset, scale); - } -}); - -L.canvasLayer = function () { - return new L.CanvasLayer(); -}; - -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { - -var invariant = __webpack_require__(12); -var getCoord = invariant.getCoord; -var getCoords = invariant.getCoords; - -// http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule -// modified from: https://github.com/substack/point-in-polygon/blob/master/index.js -// which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html - -/** - * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can - * be convex or concave. The function accounts for holes. - * - * @name inside - * @param {Feature} point input point - * @param {Feature} polygon input polygon or multipolygon - * @param {boolean} [ignoreBoundary=false] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false. - * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon - * @example - * var pt = turf.point([-77, 44]); - * var poly = turf.polygon([[ - * [-81, 41], - * [-81, 47], - * [-72, 47], - * [-72, 41], - * [-81, 41] - * ]]); - * - * turf.inside(pt, poly); - * //= true - */ -module.exports = function (point, polygon, ignoreBoundary) { - // validation - if (!point) throw new Error('point is required'); - if (!polygon) throw new Error('polygon is required'); - - var pt = getCoord(point); - var polys = getCoords(polygon); - var type = (polygon.geometry) ? polygon.geometry.type : polygon.type; - var bbox = polygon.bbox; - - // Quick elimination if point is not inside bbox - if (bbox && inBBox(pt, bbox) === false) return false; - - // normalize to multipolygon - if (type === 'Polygon') polys = [polys]; - - for (var i = 0, insidePoly = false; i < polys.length && !insidePoly; i++) { - // check if it is in the outer ring first - if (inRing(pt, polys[i][0], ignoreBoundary)) { - var inHole = false; - var k = 1; - // check for the point in any of the holes - while (k < polys[i].length && !inHole) { - if (inRing(pt, polys[i][k], !ignoreBoundary)) { - inHole = true; - } - k++; - } - if (!inHole) insidePoly = true; - } - } - return insidePoly; -}; - -/** - * inRing - * - * @private - * @param {[number, number]} pt [x,y] - * @param {Array<[number, number]>} ring [[x,y], [x,y],..] - * @param {boolean} ignoreBoundary ignoreBoundary - * @returns {boolean} inRing - */ -function inRing(pt, ring, ignoreBoundary) { - var isInside = false; - if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1); - - for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) { - var xi = ring[i][0], yi = ring[i][1]; - var xj = ring[j][0], yj = ring[j][1]; - var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) && - ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0); - if (onBoundary) return !ignoreBoundary; - var intersect = ((yi > pt[1]) !== (yj > pt[1])) && - (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi); - if (intersect) isInside = !isInside; - } - return isInside; -} - -/** - * inBBox - * - * @private - * @param {[number, number]} pt point [x,y] - * @param {[number, number, number, number]} bbox BBox [west, south, east, north] - * @returns {boolean} true/false if point is inside BBox - */ -function inBBox(pt, bbox) { - return bbox[0] <= pt[0] && - bbox[1] <= pt[1] && - bbox[2] >= pt[0] && - bbox[3] >= pt[1]; -} - - -/***/ }), -/* 12 */ -/***/ (function(module, exports) { - -/** - * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate. - * - * @name getCoord - * @param {Array|Geometry|Feature} obj Object - * @returns {Array} coordinates - * @example - * var pt = turf.point([10, 10]); - * - * var coord = turf.getCoord(pt); - * //= [10, 10] - */ -function getCoord(obj) { - if (!obj) throw new Error('obj is required'); - - var coordinates = getCoords(obj); - - // getCoord() must contain at least two numbers (Point) - if (coordinates.length > 1 && - typeof coordinates[0] === 'number' && - typeof coordinates[1] === 'number') { - return coordinates; - } else { - throw new Error('Coordinate is not a valid Point'); - } -} - -/** - * Unwrap coordinates from a Feature, Geometry Object or an Array of numbers - * - * @name getCoords - * @param {Array|Geometry|Feature} obj Object - * @returns {Array} coordinates - * @example - * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]); - * - * var coord = turf.getCoords(poly); - * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]] - */ -function getCoords(obj) { - if (!obj) throw new Error('obj is required'); - var coordinates; - - // Array of numbers - if (obj.length) { - coordinates = obj; - - // Geometry Object - } else if (obj.coordinates) { - coordinates = obj.coordinates; - - // Feature - } else if (obj.geometry && obj.geometry.coordinates) { - coordinates = obj.geometry.coordinates; - } - // Checks if coordinates contains a number - if (coordinates) { - containsNumber(coordinates); - return coordinates; - } - throw new Error('No valid coordinates'); -} - -/** - * Checks if coordinates contains a number - * - * @name containsNumber - * @param {Array} coordinates GeoJSON Coordinates - * @returns {boolean} true if Array contains a number - */ -function containsNumber(coordinates) { - if (coordinates.length > 1 && - typeof coordinates[0] === 'number' && - typeof coordinates[1] === 'number') { - return true; - } - - if (Array.isArray(coordinates[0]) && coordinates[0].length) { - return containsNumber(coordinates[0]); - } - throw new Error('coordinates must only contain numbers'); -} - -/** - * Enforce expectations about types of GeoJSON objects for Turf. - * - * @name geojsonType - * @param {GeoJSON} value any GeoJSON object - * @param {string} type expected GeoJSON type - * @param {string} name name of calling function - * @throws {Error} if value is not the expected type. - */ -function geojsonType(value, type, name) { - if (!type || !name) throw new Error('type and name required'); - - if (!value || value.type !== type) { - throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + value.type); - } -} - -/** - * Enforce expectations about types of {@link Feature} inputs for Turf. - * Internally this uses {@link geojsonType} to judge geometry types. - * - * @name featureOf - * @param {Feature} feature a feature with an expected geometry type - * @param {string} type expected GeoJSON type - * @param {string} name name of calling function - * @throws {Error} error if value is not the expected type. - */ -function featureOf(feature, type, name) { - if (!feature) throw new Error('No feature passed'); - if (!name) throw new Error('.featureOf() requires a name'); - if (!feature || feature.type !== 'Feature' || !feature.geometry) { - throw new Error('Invalid input to ' + name + ', Feature with geometry required'); - } - if (!feature.geometry || feature.geometry.type !== type) { - throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type); - } -} - -/** - * Enforce expectations about types of {@link FeatureCollection} inputs for Turf. - * Internally this uses {@link geojsonType} to judge geometry types. - * - * @name collectionOf - * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged - * @param {string} type expected GeoJSON type - * @param {string} name name of calling function - * @throws {Error} if value is not the expected type. - */ -function collectionOf(featureCollection, type, name) { - if (!featureCollection) throw new Error('No featureCollection passed'); - if (!name) throw new Error('.collectionOf() requires a name'); - if (!featureCollection || featureCollection.type !== 'FeatureCollection') { - throw new Error('Invalid input to ' + name + ', FeatureCollection required'); - } - for (var i = 0; i < featureCollection.features.length; i++) { - var feature = featureCollection.features[i]; - if (!feature || feature.type !== 'Feature' || !feature.geometry) { - throw new Error('Invalid input to ' + name + ', Feature with geometry required'); - } - if (!feature.geometry || feature.geometry.type !== type) { - throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type); - } - } -} - -/** - * Get Geometry from Feature or Geometry Object - * - * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object - * @returns {Geometry|null} GeoJSON Geometry Object - * @throws {Error} if geojson is not a Feature or Geometry Object - * @example - * var point = { - * "type": "Feature", - * "properties": {}, - * "geometry": { - * "type": "Point", - * "coordinates": [110, 40] - * } - * } - * var geom = turf.getGeom(point) - * //={"type": "Point", "coordinates": [110, 40]} - */ -function getGeom(geojson) { - if (!geojson) throw new Error('geojson is required'); - if (geojson.geometry !== undefined) return geojson.geometry; - if (geojson.coordinates || geojson.geometries) return geojson; - throw new Error('geojson must be a valid Feature or Geometry Object'); -} - -/** - * Get Geometry Type from Feature or Geometry Object - * - * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object - * @returns {string} GeoJSON Geometry Type - * @throws {Error} if geojson is not a Feature or Geometry Object - * @example - * var point = { - * "type": "Feature", - * "properties": {}, - * "geometry": { - * "type": "Point", - * "coordinates": [110, 40] - * } - * } - * var geom = turf.getGeomType(point) - * //="Point" - */ -function getGeomType(geojson) { - if (!geojson) throw new Error('geojson is required'); - var geom = getGeom(geojson); - if (geom) return geom.type; -} - -module.exports = { - geojsonType: geojsonType, - collectionOf: collectionOf, - featureOf: featureOf, - getCoord: getCoord, - getCoords: getCoords, - containsNumber: containsNumber, - getGeom: getGeom, - getGeomType: getGeomType -}; - - -/***/ }), -/* 13 */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { - -"use strict"; -Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector_js__ = __webpack_require__(3); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Cell_js__ = __webpack_require__(0); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Field_js__ = __webpack_require__(1); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__ScalarField_js__ = __webpack_require__(2); -/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__VectorField_js__ = __webpack_require__(4); -// base - -window.L.Vector = __WEBPACK_IMPORTED_MODULE_0__Vector_js__["a" /* default */]; - - -window.L.Cell = __WEBPACK_IMPORTED_MODULE_1__Cell_js__["a" /* default */]; - - -window.L.Field = __WEBPACK_IMPORTED_MODULE_2__Field_js__["a" /* default */]; - - -window.L.ScalarField = __WEBPACK_IMPORTED_MODULE_3__ScalarField_js__["a" /* default */]; - - -window.L.VectorField = __WEBPACK_IMPORTED_MODULE_4__VectorField_js__["a" /* default */]; - -// layer -__webpack_require__(10); -__webpack_require__(8); -__webpack_require__(6); -__webpack_require__(7); -__webpack_require__(9); - -// control -__webpack_require__(5); - -/* eslint-disable no-console */ -console.log('leaflet.canvaslayer.field v1.4.0 in progress...'); -/* eslint-enable no-console */ - -/***/ }) -/******/ ]); +!function(t){function e(i){if(n[i])return n[i].exports;var r=n[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,e),r.l=!0,r.exports}var n={};e.m=t,e.c=n,e.i=function(t){return t},e.d=function(t,n,i){e.o(t,n)||Object.defineProperty(t,n,{configurable:!1,enumerable:!0,get:i})},e.n=function(t){var n=t&&t.__esModule?function(){return t.default}:function(){return t};return e.d(n,"a",n),n},e.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},e.p="",e(e.s=13)}([function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var r=function(){function t(t,e){for(var n=0;n3&&void 0!==arguments[3]?arguments[3]:r;i(this,t),this.center=e,this.value=n,this.xSize=r,this.ySize=o}return r(t,[{key:"equals",value:function(t){return this.center.equals(t.center)&&this._equalValues(this.value,t.value)&&this.xSize===t.xSize&&this.ySize===t.ySize}},{key:"_equalValues",value:function(t,e){var n=t.constructor.name;return{Number:t===e,Vector:t.u===e.u&&t.v===e.v}[n]}},{key:"getBounds",value:function(){var t=this.xSize/2,e=this.ySize/2,n=this.center.lat,i=this.center.lng,r=L.latLng([n+e,i-t]),o=L.latLng([n-e,i+t]);return L.latLngBounds(L.latLng(o.lat,r.lng),L.latLng(r.lat,o.lng))}}]),t}();e.a=o},function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}var r=n(0),o=n(11),a=n.n(o),s=function(){function t(t,e){var n=[],i=!0,r=!1,o=void 0;try{for(var a,s=t[Symbol.iterator]();!(i=(a=s.next()).done)&&(n.push(a.value),!e||n.length!==e);i=!0);}catch(t){r=!0,o=t}finally{try{!i&&s.return&&s.return()}finally{if(r)throw o}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),l=function(){function t(t,e){for(var n=0;n=360,this.longitudeNeedsToBeWrapped=this.xurCorner>180,this._inFilter=null,this._spatialMask=null}return l(t,[{key:"_buildGrid",value:function(){throw new TypeError("Must be overriden")}},{key:"_updateRange",value:function(){this.range=this._calculateRange()}},{key:"numCells",value:function(){return this.nRows*this.nCols}},{key:"getCells",value:function(){for(var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:1,e=[],n=0;n=r&&t<=o,l=e>=this.yllCorner&&e<=this.yurCorner;return a&&l}},{key:"_pointInMask",value:function(t,e){var n={type:"Feature",geometry:{type:"Point",coordinates:[t,e]},properties:{}},i=this._spatialMask;return a()(n,i)}},{key:"notContains",value:function(t,e){return!this.contains(t,e)}},{key:"interpolatedValueAt",value:function(t,e){if(this.notContains(t,e))return null;var n=this._getDecimalIndexes(t,e),i=s(n,2),r=i[0],o=i[1];return this.interpolatedValueAtIndexes(r,o)}},{key:"interpolatedValueAtIndexes",value:function(t,e){var n=this._getFourSurroundingIndexes(t,e),i=s(n,4),r=i[0],o=i[1],a=i[2],l=i[3],u=this._getFourSurroundingValues(r,o,a,l);if(u){var h=s(u,4),c=h[0],f=h[1],d=h[2],p=h[3];return this._doInterpolation(t-r,e-a,c,f,d,p)}return null}},{key:"_getDecimalIndexes",value:function(t,e){return this.longitudeNeedsToBeWrapped&&t=this.nCols&&(i=0),i=this._clampColumnIndex(i);var r=this._clampRowIndex(Math.floor(e));return[n,i,r,this._clampRowIndex(r+1)]}},{key:"_getFourSurroundingValues",value:function(t,e,n,i){var r;if(r=this.grid[n]){var o=r[t],a=r[e];if(this._isValid(o)&&this._isValid(a)&&(r=this.grid[i])){var s=r[t],l=r[e];if(this._isValid(s)&&this._isValid(l))return[o,a,s,l]}}return null}},{key:"valueAt",value:function(t,e){if(this.notContains(t,e))return null;var n=this._getDecimalIndexes(t,e),i=s(n,2),r=i[0],o=i[1],a=Math.floor(r),l=Math.floor(o),u=this._clampColumnIndex(a),h=this._clampRowIndex(l),c=this._valueAtIndexes(u,h);return this._inFilter&&!this._inFilter(c)?null:c}},{key:"hasValueAt",value:function(t,e){var n=this.valueAt(t,e),i=null!==n,r=!0;return this._inFilter&&(r=this._inFilter(n)),i&&r}},{key:"notHasValueAt",value:function(t,e){return!this.hasValueAt(t,e)}},{key:"randomPosition",value:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=Math.random()*this.nCols|0,n=Math.random()*this.nRows|0;return t.x=this._longitudeAtX(e),t.y=this._latitudeAtY(n),t}},{key:"_valueAtIndexes",value:function(t,e){return this.grid[e][t]}},{key:"_lonLatAtIndexes",value:function(t,e){return[this._longitudeAtX(t),this._latitudeAtY(e)]}},{key:"_longitudeAtX",value:function(t){var e=this.cellXSize/2,n=this.xllCorner+e+t*this.cellXSize;return this.longitudeNeedsToBeWrapped&&(n=n>180?n-360:n),n}},{key:"_latitudeAtY",value:function(t){var e=this.cellYSize/2;return this.yurCorner-e-t*this.cellYSize}},{key:"_doInterpolation",value:function(t,e,n,i,r,o){throw new TypeError("Must be overriden")}},{key:"_clampColumnIndex",value:function(t){var e=t;t<0&&(e=0);var n=this.nCols-1;return t>n&&(e=n),e}},{key:"_clampRowIndex",value:function(t){var e=t;t<0&&(e=0);var n=this.nRows-1;return t>n&&(e=n),e}},{key:"_isValid",value:function(t){return null!==t&&void 0!==t}}]),t}();e.a=u},function(t,e,n){"use strict";function i(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}function r(t,e){if(!t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!e||"object"!=typeof e&&"function"!=typeof e?t:e}function o(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function, not "+typeof e);t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),e&&(Object.setPrototypeOf?Object.setPrototypeOf(t,e):t.__proto__=e)}var a=n(1),s=function(){function t(t,e){var n=[],i=!0,r=!1,o=void 0;try{for(var a,s=t[Symbol.iterator]();!(i=(a=s.next()).done)&&(n.push(a.value),!e||n.length!==e);i=!0);}catch(t){r=!0,o=t}finally{try{!i&&s.return&&s.return()}finally{if(r)throw o}}return n}return function(e,n){if(Array.isArray(e))return e;if(Symbol.iterator in Object(e))return t(e,n);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}(),l=function(){function t(t,e){for(var n=0;n1&&void 0!==arguments[1]?arguments[1]:1,i=t.split("\n");e._checkIsValidASCIIGridHeader(i);for(var r=/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/,o=parseFloat(i[4].match(r)),a={nCols:parseInt(i[0].match(r)),nRows:parseInt(i[1].match(r)),xllCorner:parseFloat(i[2].match(r)),yllCorner:parseFloat(i[3].match(r)),cellXSize:o,cellYSize:o},s=i[5].toUpperCase().replace("NODATA_VALUE","").trim(),l=[],u=6;u1&&void 0!==arguments[1]?arguments[1]:0,i=GeoTIFF.parse(t),r=i.getImage(),o=r.readRasters(),a=r.getTiePoints()[0],l=r.getFileDirectory(),u=s(l.ModelPixelScale,2),h=u[0],c=u[1],f=o[n];if(l.GDAL_NODATA){var d=parseFloat(l.GDAL_NODATA);f=Array.from(f).map(function(t){return t===d?null:t})}return new e({nCols:r.getWidth(),nRows:r.getHeight(),xllCorner:a.x,yllCorner:a.y-r.getHeight()*c,cellXSize:h,cellYSize:c,zs:f})}}]),l(e,[{key:"_buildGrid",value:function(){return this._arrayTo2d(this.zs,this.nRows,this.nCols)}},{key:"_arrayTo2d",value:function(t,e,n){for(var i=[],r=0,o=0;o2&&void 0!==arguments[2]?arguments[2]:1,r=l.a.fromASCIIGrid(t,i),o=l.a.fromASCIIGrid(n,i);return new e(e._paramsFromScalarFields(r,o))}},{key:"fromGeoTIFFs",value:function(t,n){var i=l.a.fromGeoTIFF(t),r=l.a.fromGeoTIFF(n);return new e(e._paramsFromScalarFields(i,r))}},{key:"fromMultibandGeoTIFF",value:function(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:[0,1],i=l.a.fromGeoTIFF(t,n[0]),r=l.a.fromGeoTIFF(t,n[1]);return new e(e._paramsFromScalarFields(i,r))}},{key:"_paramsFromScalarFields",value:function(t,e){return{nCols:t.nCols,nRows:t.nRows,xllCorner:t.xllCorner,yllCorner:t.yllCorner,cellXSize:t.cellXSize,cellYSize:t.cellYSize,us:t.zs,vs:e.zs}}}]),u(e,[{key:"getScalarField",value:function(t){var e=this._getFunctionFor(t),n={nCols:this.params.nCols,nRows:this.params.nRows,xllCorner:this.params.xllCorner,yllCorner:this.params.yllCorner,cellXSize:this.params.cellXSize,cellYSize:this.params.cellYSize,zs:this._applyOnField(e)};return new l.a(n)}},{key:"_getFunctionFor",value:function(t){return function(e,n){return new a.a(e,n)[t]()}}},{key:"_applyOnField",value:function(t){for(var e=[],n=this.numCells(),i=0;io.options.maxAge&&(t.age=0,o._field.randomPosition(t));var e=o._field.valueAt(t.x,t.y);if(null===e)t.age=o.options.maxAge;else{var n=t.x+e.u*o.options.velocityScale,i=t.y+e.v*o.options.velocityScale;o._field.hasValueAt(n,i)?(t.xt=n,t.yt=i,t.m=e.magnitude()):t.age=o.options.maxAge}t.age+=1})}function n(){var e=i.globalCompositeOperation;i.globalCompositeOperation="destination-in",i.fillRect(0,0,i.canvas.width,i.canvas.height),i.globalCompositeOperation=e,i.fillStyle="rgba(0, 0, 0, "+o.options.fade+")",i.lineWidth=o.options.width,i.strokeStyle=o.options.color,r.forEach(function(e){o._drawParticle(t,i,e)})}if(this._field&&this.isVisible()){this._updateOpacity();var i=this._getDrawingContext(),r=this._prepareParticlePaths();this.timer=d3.timer(function(){e(),n()},this.options.duration);var o=this}},_drawParticle:function(t,e,n){var i=new L.latLng(n.y,n.x),r=new L.latLng(n.yt,n.xt);if(t.bounds.contains(i)&&n.age<=this.options.maxAge){var o=t.layer._map.latLngToContainerPoint(i),a=t.layer._map.latLngToContainerPoint(r);e.beginPath(),e.moveTo(o.x,o.y),e.lineTo(a.x,a.y),n.x=n.xt,n.y=n.yt;var s=this.options.color;"function"==typeof s&&(e.strokeStyle=s(n.m));var l=this.options.width;"function"==typeof l&&(e.lineWidth=l(n.m)),e.stroke()}},_prepareParticlePaths:function(){for(var t=[],e=0;et[1]!=u>t[1]&&t[0]<(l-a)*(t[1]-s)/(u-s)+a&&(i=!i)}return i}function r(t,e){return e[0]<=t[0]&&e[1]<=t[1]&&e[2]>=t[0]&&e[3]>=t[1]}var o=n(12),a=o.getCoord,s=o.getCoords;t.exports=function(t,e,n){if(!t)throw new Error("point is required");if(!e)throw new Error("polygon is required");var o=a(t),l=s(e),u=e.geometry?e.geometry.type:e.type,h=e.bbox;if(h&&!1===r(o,h))return!1;"Polygon"===u&&(l=[l]);for(var c=0,f=!1;c1&&"number"==typeof e[0]&&"number"==typeof e[1])return e;throw new Error("Coordinate is not a valid Point")}function i(t){if(!t)throw new Error("obj is required");var e;if(t.length?e=t:t.coordinates?e=t.coordinates:t.geometry&&t.geometry.coordinates&&(e=t.geometry.coordinates),e)return r(e),e;throw new Error("No valid coordinates")}function r(t){if(t.length>1&&"number"==typeof t[0]&&"number"==typeof t[1])return!0;if(Array.isArray(t[0])&&t[0].length)return r(t[0]);throw new Error("coordinates must only contain numbers")}function o(t,e,n){if(!e||!n)throw new Error("type and name required");if(!t||t.type!==e)throw new Error("Invalid input to "+n+": must be a "+e+", given "+t.type)}function a(t,e,n){if(!t)throw new Error("No feature passed");if(!n)throw new Error(".featureOf() requires a name");if(!t||"Feature"!==t.type||!t.geometry)throw new Error("Invalid input to "+n+", Feature with geometry required");if(!t.geometry||t.geometry.type!==e)throw new Error("Invalid input to "+n+": must be a "+e+", given "+t.geometry.type)}function s(t,e,n){if(!t)throw new Error("No featureCollection passed");if(!n)throw new Error(".collectionOf() requires a name");if(!t||"FeatureCollection"!==t.type)throw new Error("Invalid input to "+n+", FeatureCollection required");for(var i=0;i= 360;\n this.longitudeNeedsToBeWrapped = this.xurCorner > 180; // [0, 360] --> [-180, 180]\n\n this._inFilter = null;\n this._spatialMask = null;\n }\n\n /**\n * Builds a grid with a value at each point (either Vector or Number)\n * Original params must include the required input values, following\n * x-ascending & y-descending order (same as in ASCIIGrid)\n * @abstract\n * @private\n * @returns {Array.>} - grid[row][column]--> Vector|Number\n */\n _buildGrid() {\n throw new TypeError('Must be overriden');\n }\n\n _updateRange() {\n this.range = this._calculateRange();\n }\n\n /**\n * Number of cells in the grid (rows * cols)\n * @returns {Number}\n */\n numCells() {\n return this.nRows * this.nCols;\n }\n\n /**\n * A list with every cell\n * @returns {Array} - cells (x-ascending & y-descending order)\n */\n getCells(stride = 1) {\n let cells = [];\n for (let j = 0; j < this.nRows; j = j + stride) {\n for (let i = 0; i < this.nCols; i = i + stride) {\n let [lon, lat] = this._lonLatAtIndexes(i, j);\n let center = L.latLng(lat, lon);\n let value = this._valueAtIndexes(i, j);\n let c = new Cell(center, value, this.cellXSize, this.cellYSize);\n cells.push(c); // <<\n }\n }\n return cells;\n }\n\n /**\n * Apply a filter function to field values\n * @param {Function} f - boolean function\n */\n setFilter(f) {\n this._inFilter = f;\n this._updateRange();\n }\n\n /**\n * Apply a spatial mask to field values\n * @param {L.GeoJSON} m \n */\n setSpatialMask(m) {\n this._spatialMask = m;\n }\n\n /**\n * Grid extent\n * @returns {Number[]} [xmin, ymin, xmax, ymax]\n */\n extent() {\n let [xmin, xmax] = this._getWrappedLongitudes();\n return [xmin, this.yllCorner, xmax, this.yurCorner];\n }\n\n /**\n * [xmin, xmax] in [-180, 180] range\n */\n _getWrappedLongitudes() {\n let xmin = this.xllCorner;\n let xmax = this.xurCorner;\n\n if (this.longitudeNeedsToBeWrapped) {\n if (this.isContinuous) {\n xmin = -180;\n xmax = 180;\n } else {\n // not sure about this (just one particular case, but others...?)\n xmax = this.xurCorner - 360;\n xmin = this.xllCorner - 360;\n /* eslint-disable no-console */\n // console.warn(`are these xmin: ${xmin} & xmax: ${xmax} OK?`);\n // TODO: Better throw an exception on no-controlled situations.\n /* eslint-enable no-console */\n }\n }\n return [xmin, xmax];\n }\n\n /**\n * Returns whether or not the grid contains the point, considering\n * the spatialMask if it has been previously set\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n contains(lon, lat) {\n if (this._spatialMask) {\n return this._pointInMask(lon, lat);\n }\n return this._pointInExtent(lon, lat);\n }\n\n /**\n * Checks if coordinates are inside the Extent (considering wrapped longitudes if needed)\n * @param {Number} lon \n * @param {Number} lat \n */\n _pointInExtent(lon, lat) {\n let [xmin, xmax] = this._getWrappedLongitudes();\n let longitudeIn = lon >= xmin && lon <= xmax;\n let latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n return longitudeIn && latitudeIn;\n }\n\n /**\n * Check if coordinates are inside the spatialMask (Point in Polygon analysis)\n * @param {Number} lon \n * @param {Number} lat \n */\n _pointInMask(lon, lat) {\n const pt = {\n type: 'Feature',\n geometry: {\n type: 'Point',\n coordinates: [lon, lat] // geojson, lon-lat order !\n },\n properties: {}\n };\n const poly = this._spatialMask;\n return inside(pt, poly);\n }\n\n /**\n * Returns if the grid doesn't contain the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n notContains(lon, lat) {\n return !this.contains(lon, lat);\n }\n\n /**\n * Interpolated value at lon-lat coordinates (bilinear method)\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number} [u, v, magnitude]\n * \n * Source: https://github.com/cambecc/earth > product.js\n */\n interpolatedValueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n let [i, j] = this._getDecimalIndexes(lon, lat);\n return this.interpolatedValueAtIndexes(i, j);\n }\n\n /**\n * Interpolated value at i-j indexes (bilinear method)\n * @param {Number} i\n * @param {Number} j\n * @returns {Vector|Number} [u, v, magnitude]\n *\n * Source: https://github.com/cambecc/earth > product.js\n */\n interpolatedValueAtIndexes(i, j) {\n // 1 2 After converting λ and φ to fractional grid indexes i and j, we find the\n // fi i ci four points 'G' that enclose point (i, j). These points are at the four\n // | =1.4 | corners specified by the floor and ceiling of i and j. For example, given\n // ---G--|---G--- fj 8 i = 1.4 and j = 8.3, the four surrounding grid points are (1, 8), (2, 8),\n // j ___|_ . | (1, 9) and (2, 9).\n // =8.3 | |\n // ---G------G--- cj 9 Note that for wrapped grids, the first column is duplicated as the last\n // | | column, so the index ci can be used without taking a modulo.\n\n let indexes = this._getFourSurroundingIndexes(i, j);\n let [fi, ci, fj, cj] = indexes;\n let values = this._getFourSurroundingValues(fi, ci, fj, cj);\n if (values) {\n let [g00, g10, g01, g11] = values;\n return this._doInterpolation(i - fi, j - fj, g00, g10, g01, g11);\n }\n return null;\n }\n\n /**\n * Get decimal indexes\n * @private\n * @param {Number} lon\n * @param {Number} lat\n * @returns {Array} [[Description]]\n */\n _getDecimalIndexes(lon, lat) {\n if (this.longitudeNeedsToBeWrapped && lon < this.xllCorner) {\n lon = lon + 360;\n }\n let i = (lon - this.xllCorner) / this.cellXSize;\n let j = (this.yurCorner - lat) / this.cellYSize;\n return [i, j];\n }\n\n /**\n * Get surrounding indexes (integer), clampling on borders\n * @private\n * @param {Number} i - decimal index\n * @param {Number} j - decimal index\n * @returns {Array} [fi, ci, fj, cj]\n */\n _getFourSurroundingIndexes(i, j) {\n let fi = Math.floor(i);\n let ci = fi + 1;\n // duplicate colum to simplify interpolation logic (wrapped value)\n if (this.isContinuous && ci >= this.nCols) {\n ci = 0;\n }\n ci = this._clampColumnIndex(ci);\n\n let fj = this._clampRowIndex(Math.floor(j));\n let cj = this._clampRowIndex(fj + 1);\n\n return [fi, ci, fj, cj];\n }\n\n /**\n * Get four surrounding values or null if not available,\n * from 4 integer indexes\n * @private\n * @param {Number} fi\n * @param {Number} ci\n * @param {Number} fj\n * @param {Number} cj\n * @returns {Array} \n */\n _getFourSurroundingValues(fi, ci, fj, cj) {\n var row;\n if ((row = this.grid[fj])) {\n // upper row ^^\n var g00 = row[fi]; // << left\n var g10 = row[ci]; // right >>\n if (\n this._isValid(g00) &&\n this._isValid(g10) &&\n (row = this.grid[cj])\n ) {\n // lower row vv\n var g01 = row[fi]; // << left\n var g11 = row[ci]; // right >>\n if (this._isValid(g01) && this._isValid(g11)) {\n return [g00, g10, g01, g11]; // 4 values found!\n }\n }\n }\n return null;\n }\n\n /**\n * Nearest value at lon-lat coordinates\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number}\n */\n valueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n let [i, j] = this._getDecimalIndexes(lon, lat);\n let ii = Math.floor(i);\n let jj = Math.floor(j);\n\n const ci = this._clampColumnIndex(ii);\n const cj = this._clampRowIndex(jj);\n\n let value = this._valueAtIndexes(ci, cj);\n if (this._inFilter) {\n if (!this._inFilter(value)) return null;\n }\n\n return value;\n }\n\n /**\n * Returns whether or not the field has a value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n hasValueAt(lon, lat) {\n let value = this.valueAt(lon, lat);\n let hasValue = value !== null;\n\n let included = true;\n if (this._inFilter) {\n included = this._inFilter(value);\n }\n return hasValue && included;\n }\n\n /**\n * Returns if the grid has no value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n notHasValueAt(lon, lat) {\n return !this.hasValueAt(lon, lat);\n }\n\n /**\n * Gives a random position to 'o' inside the grid\n * @param {Object} [o] - an object (eg. a particle)\n * @returns {{x: Number, y: Number}} - object with x, y (lon, lat)\n */\n randomPosition(o = {}) {\n let i = (Math.random() * this.nCols) | 0;\n let j = (Math.random() * this.nRows) | 0;\n\n o.x = this._longitudeAtX(i);\n o.y = this._latitudeAtY(j);\n\n return o;\n }\n\n /**\n * Value for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Vector|Number}\n */\n _valueAtIndexes(i, j) {\n return this.grid[j][i]; // <-- j,i !!\n }\n\n /**\n * Lon-Lat for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Number[]} [lon, lat]\n */\n _lonLatAtIndexes(i, j) {\n let lon = this._longitudeAtX(i);\n let lat = this._latitudeAtY(j);\n\n return [lon, lat];\n }\n\n /**\n * Longitude for grid-index\n * @param {Number} i - column index (integer)\n * @returns {Number} longitude at the center of the cell\n */\n _longitudeAtX(i) {\n let halfXPixel = this.cellXSize / 2.0;\n let lon = this.xllCorner + halfXPixel + i * this.cellXSize;\n if (this.longitudeNeedsToBeWrapped) {\n lon = lon > 180 ? lon - 360 : lon;\n }\n return lon;\n }\n\n /**\n * Latitude for grid-index\n * @param {Number} j - row index (integer)\n * @returns {Number} latitude at the center of the cell\n */\n _latitudeAtY(j) {\n let halfYPixel = this.cellYSize / 2.0;\n return this.yurCorner - halfYPixel - j * this.cellYSize;\n }\n\n /**\n * Apply the interpolation\n * @abstract\n * @private\n */\n /* eslint-disable no-unused-vars */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n throw new TypeError('Must be overriden');\n }\n /* eslint-disable no-unused-vars */\n\n /**\n * Check the column index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} ii - index\n * @returns {Number} i - inside the allowed indexes\n */\n _clampColumnIndex(ii) {\n let i = ii;\n if (ii < 0) {\n i = 0;\n }\n let maxCol = this.nCols - 1;\n if (ii > maxCol) {\n i = maxCol;\n }\n return i;\n }\n\n /**\n * Check the row index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} jj index\n * @returns {Number} j - inside the allowed indexes\n */\n _clampRowIndex(jj) {\n let j = jj;\n if (jj < 0) {\n j = 0;\n }\n let maxRow = this.nRows - 1;\n if (jj > maxRow) {\n j = maxRow;\n }\n return j;\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n _isValid(x) {\n return x !== null && x !== undefined;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./Field.js","import Field from './Field';\n\n/**\n * Scalar Field\n */\nexport default class ScalarField extends Field {\n /**\n * Creates a ScalarField from the content of an ASCIIGrid file\n * @param {String} asc\n * @returns {ScalarField}\n */\n static fromASCIIGrid(asc, scaleFactor = 1) {\n //console.time('ScalarField from ASC');\n\n let lines = asc.split('\\n');\n\n // Header\n ScalarField._checkIsValidASCIIGridHeader(lines);\n\n let n = /-?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/; // any number\n\n const cellSize = parseFloat(lines[4].match(n)); // right now, no different x-y size is allowed\n let p = {\n nCols: parseInt(lines[0].match(n)),\n nRows: parseInt(lines[1].match(n)),\n xllCorner: parseFloat(lines[2].match(n)),\n yllCorner: parseFloat(lines[3].match(n)),\n cellXSize: cellSize,\n cellYSize: cellSize\n };\n let noDataValue = lines[5]\n .toUpperCase()\n .replace('NODATA_VALUE', '')\n .trim();\n\n // Data (left-right and top-down)\n let zs = []; // TODO Consider using TypedArray (& manage NO_DATA)\n for (let i = 6; i < lines.length; i++) {\n let line = lines[i].trim();\n if (line === '') break;\n\n let items = line.split(' ');\n items.forEach(it => {\n const v =\n it !== noDataValue ? parseFloat(it * scaleFactor) : null;\n zs.push(v);\n });\n }\n p.zs = zs;\n\n //console.timeEnd('ScalarField from ASC');\n return new ScalarField(p);\n }\n\n static _checkIsValidASCIIGridHeader(lines) {\n const upperCasesLines = lines.map(lin => lin.toUpperCase());\n\n const parameters = [\n 'NCOLS',\n 'NROWS',\n 'XLLCORNER',\n 'YLLCORNER',\n 'CELLSIZE',\n 'NODATA_VALUE'\n ];\n\n let i = 0;\n for (let expected of parameters) {\n let line = upperCasesLines[i];\n let found = line.indexOf(expected) != -1;\n if (!found) {\n throw `Not valid ASCIIGrid: expected '${expected}' at line '${line}' [lin. nº ${i}]`;\n }\n i++;\n }\n }\n\n /**\n * Creates a ScalarField from the content of a GeoTIFF file, as read by geotiff.js\n * @param {ArrayBuffer} data\n * @param {Number} bandIndex\n * @returns {ScalarField}\n */\n static fromGeoTIFF(data, bandIndex = 0) {\n //console.time('ScalarField from GeoTIFF');\n\n let tiff = GeoTIFF.parse(data); // geotiff.js\n let image = tiff.getImage();\n let rasters = image.readRasters();\n let tiepoint = image.getTiePoints()[0];\n let fileDirectory = image.getFileDirectory();\n let [xScale, yScale] = fileDirectory.ModelPixelScale;\n\n let zs = rasters[bandIndex]; // left-right and top-down order\n\n if (fileDirectory.GDAL_NODATA) {\n let noData = parseFloat(fileDirectory.GDAL_NODATA);\n // console.log(noData);\n let simpleZS = Array.from(zs); // to simple array, so null is allowed | TODO efficiency??\n zs = simpleZS.map(function(z) {\n return z === noData ? null : z;\n });\n }\n\n let p = {\n nCols: image.getWidth(),\n nRows: image.getHeight(),\n xllCorner: tiepoint.x,\n yllCorner: tiepoint.y - image.getHeight() * yScale,\n cellXSize: xScale,\n cellYSize: yScale,\n zs: zs\n };\n\n //console.timeEnd('ScalarField from GeoTIFF');\n return new ScalarField(p);\n }\n\n constructor(params) {\n super(params);\n this.zs = params['zs'];\n\n this.grid = this._buildGrid();\n this._updateRange();\n //console.log(`ScalarField created (${this.nCols} x ${this.nRows})`);\n }\n\n /**\n * Builds a grid with a Number at each point, from an array\n * 'zs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @private\n * @returns {Array.>} - grid[row][column]--> Number\n */\n _buildGrid() {\n let grid = this._arrayTo2d(this.zs, this.nRows, this.nCols);\n return grid;\n }\n\n _arrayTo2d(array, nRows, nCols) {\n let grid = [];\n let p = 0;\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n let z = array[p];\n row[i] = this._isValid(z) ? z : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n\n _newDataArrays(params) {\n params['zs'] = [];\n }\n\n _pushValueToArrays(params, value) {\n params['zs'].push(value);\n }\n\n _makeNewFrom(params) {\n return new ScalarField(params);\n }\n\n /**\n * Calculate min & max values\n * @private\n * @returns {Array} - [min, max]\n */\n _calculateRange() {\n var data = this.zs;\n if (this._inFilter) {\n data = data.filter(this._inFilter);\n }\n return [d3.min(data), d3.max(data)];\n }\n\n /**\n * Bilinear interpolation for Number\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number} g00\n * @param {Number} g10\n * @param {Number} g01\n * @param {Number} g11\n * @returns {Number}\n */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n return g00 * rx * ry + g10 * x * ry + g01 * rx * y + g11 * x * y;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./ScalarField.js","/**\n * 2D Vector\n */\nexport default class Vector {\n\n constructor(u, v) {\n this.u = u;\n this.v = v;\n }\n\n /**\n * Magnitude\n * @returns {Number}\n */\n magnitude() {\n return Math.sqrt(this.u * this.u + this.v * this.v);\n }\n\n /**\n * Angle in degrees (0 to 360º) --> Towards\n * N is 0º and E is 90º\n * @returns {Number}\n */\n directionTo() {\n let verticalAngle = Math.atan2(this.u, this.v);\n let inDegrees = verticalAngle * (180.0 / Math.PI);\n if (inDegrees < 0) {\n inDegrees = inDegrees + 360.0;\n }\n return inDegrees;\n }\n\n /**\n * Angle in degrees (0 to 360º) From x-->\n * N is 0º and E is 90º\n * @returns {Number}\n */\n directionFrom() {\n let a = this.directionTo();\n let opposite = (a + 180.0) % 360.0;\n return opposite;\n }\n\n /*\n Degrees --> text\n new Dictionary\n {\n //{0, 23, 45, 68, 90, 113, 135, 158, 180, 203, 225, 248, 270, 293, 315, 338, 360};\n {0, 'N'},\n {23, 'NNE'},\n {45, 'NE'},\n {68, 'ENE'},\n {90, 'E'},\n {113, 'ESE'},\n {135, 'SE'},\n {158, 'SSE'},\n {180, 'S'},\n {203, 'SSW'},\n {225, 'SW'},\n {248, 'WSW'},\n {270, 'W'},\n {293, 'WNW'},\n {315, 'NW'},\n {338, 'NNW'},\n {360, 'N'}\n };\n */\n}\n\n\n\n// WEBPACK FOOTER //\n// ./Vector.js","import Vector from './Vector';\nimport Field from './Field';\nimport ScalarField from './ScalarField';\n\n/**\n * A set of vectors assigned to a regular 2D-grid (lon-lat)\n * (e.g. a raster representing winds for a region)\n */\nexport default class VectorField extends Field {\n /**\n * Creates a VectorField from the content of two ASCIIGrid files\n * @param {String} ascU - with u-component\n * @param {String} ascV - with v-component\n * @returns {VectorField}\n */\n static fromASCIIGrids(ascU, ascV, scaleFactor = 1) {\n let u = ScalarField.fromASCIIGrid(ascU, scaleFactor);\n let v = ScalarField.fromASCIIGrid(ascV, scaleFactor);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of two different Geotiff files\n * @param {ArrayBuffer} gtU - geotiff data with u-component (band 0)\n * @param {ArrayBuffer} gtV - geotiff data with v-component (band 0)\n * @returns {VectorField}\n */\n static fromGeoTIFFs(gtU, gtV) {\n let u = ScalarField.fromGeoTIFF(gtU);\n let v = ScalarField.fromGeoTIFF(gtV);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of Multiband Geotiff\n * @param {ArrayBuffer} geotiffData - multiband\n * @param {Array} bandIndexesForUV\n * @returns {VectorField}\n */\n static fromMultibandGeoTIFF(geotiffData, bandIndexesForUV = [0, 1]) {\n let u = ScalarField.fromGeoTIFF(geotiffData, bandIndexesForUV[0]);\n let v = ScalarField.fromGeoTIFF(geotiffData, bandIndexesForUV[1]);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Build parameters for VectorField, from 2 ScalarFields.\n * No validation at all (nor interpolation) is applied, so u and v\n * must be 'compatible' from the source\n * @param {ScalarField} u\n * @param {ScalarField} v\n * @returns {Object} - parameters to build VectorField\n */\n static _paramsFromScalarFields(u, v) {\n // TODO check u & v compatibility (cellSize...)\n let p = {\n nCols: u.nCols,\n nRows: u.nRows,\n xllCorner: u.xllCorner,\n yllCorner: u.yllCorner,\n cellXSize: u.cellXSize,\n cellYSize: u.cellYSize,\n us: u.zs,\n vs: v.zs\n };\n return p;\n }\n\n constructor(params) {\n super(params);\n\n this.us = params['us'];\n this.vs = params['vs'];\n this.grid = this._buildGrid();\n this.range = this._calculateRange();\n }\n\n /**\n * Get a derived field, from a computation on \n * the VectorField\n * @param {String} type ['magnitude' | 'directionTo' | 'directionFrom']\n * @returns {ScalarField}\n */\n getScalarField(type) {\n let f = this._getFunctionFor(type);\n let p = {\n nCols: this.params.nCols,\n nRows: this.params.nRows,\n xllCorner: this.params.xllCorner,\n yllCorner: this.params.yllCorner,\n cellXSize: this.params.cellXSize,\n cellYSize: this.params.cellYSize,\n zs: this._applyOnField(f)\n };\n return new ScalarField(p);\n }\n\n _getFunctionFor(type) {\n return function(u, v) {\n let uv = new Vector(u, v);\n return uv[type](); // magnitude, directionTo, directionFrom\n };\n }\n\n _applyOnField(func) {\n let zs = [];\n let n = this.numCells();\n for (var i = 0; i < n; i++) {\n let u = this.us[i];\n let v = this.vs[i];\n if (this._isValid(u) && this._isValid(v)) {\n zs.push(func(u, v));\n } else {\n zs.push(null);\n }\n }\n return zs;\n }\n\n /**\n * Builds a grid with a Vector at each point, from two arrays\n * 'us' and 'vs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @returns {Array.>} - grid[row][column]--> Vector\n */\n _buildGrid() {\n let grid = this._arraysTo2d(this.us, this.vs, this.nRows, this.nCols);\n return grid;\n }\n\n _arraysTo2d(us, vs, nRows, nCols) {\n let grid = [];\n let p = 0;\n\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n let u = us[p],\n v = vs[p];\n let valid = this._isValid(u) && this._isValid(v);\n row[i] = valid ? new Vector(u, v) : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n\n _newDataArrays(params) {\n params['us'] = [];\n params['vs'] = [];\n }\n _pushValueToArrays(params, value) {\n //console.log(value);\n params['us'].push(value.u);\n params['vs'].push(value.v);\n }\n _makeNewFrom(params) {\n return new VectorField(params);\n }\n\n /**\n * Calculate min & max values (magnitude)\n * @private\n * @returns {Array}\n */\n _calculateRange() {\n // TODO make a clearer method for getting these vectors...\n let vectors = this.getCells().map(pt => pt.value).filter(function(v) {\n return v !== null;\n });\n\n if (this._inFilter) {\n vectors = vectors.filter(this._inFilter);\n }\n\n // TODO check memory crash with high num of vectors!\n let magnitudes = vectors.map(v => v.magnitude());\n let min = d3.min(magnitudes);\n let max = d3.max(magnitudes);\n\n return [min, max];\n }\n\n /**\n * Bilinear interpolation for Vector\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number[]} g00\n * @param {Number[]} g10\n * @param {Number[]} g01\n * @param {Number[]} g11\n * @returns {Vector}\n */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n var a = rx * ry,\n b = x * ry,\n c = rx * y,\n d = x * y;\n var u = g00.u * a + g10.u * b + g01.u * c + g11.u * d;\n var v = g00.v * a + g10.v * b + g01.v * c + g11.v * d;\n return new Vector(u, v);\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n _isValid(x) {\n return x !== null && x !== undefined;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./VectorField.js","/**\n * Control for a simple legend with a colorbar\n * References:\n * - http://jsfiddle.net/ramnathv/g8stqcf6/\n * - http://jsfiddle.net/vis4/cYLZH/\n */\nL.Control.ColorBar = L.Control.extend({\n options: {\n position: 'bottomleft',\n width: 300, // for colorbar itself (control is wider)\n height: 15,\n margin: 15,\n background: '#fff',\n textColor: 'black',\n steps: 100,\n decimals: 2,\n units: 'uds', // ej: m/s\n title: 'Legend', // ej: Ocean Currents\n labels: [], // empty for no labels\n labelFontSize: 10,\n labelTextPosition: 'middle' // start | middle | end\n },\n\n initialize: function(color, range, options) {\n this.color = color; // 'chromajs' scale function\n this.range = range; // [min, max]\n L.Util.setOptions(this, options);\n },\n\n onAdd: function(map) {\n this._map = map;\n let div = L.DomUtil.create(\n 'div',\n 'leaflet-control-colorBar leaflet-bar leaflet-control'\n );\n div.style.padding = '10px';\n\n L.DomEvent\n .addListener(div, 'click', L.DomEvent.stopPropagation)\n .addListener(div, 'click', L.DomEvent.preventDefault);\n div.style.backgroundColor = this.options.background;\n div.style.cursor = 'text';\n div.innerHTML = this.title() + this.palette();\n return div;\n },\n\n title: function() {\n let d = document.createElement('div');\n d3\n .select(d)\n .append('span')\n .style('color', this.options.textColor)\n .style('display', 'block')\n .style('margin-bottom', '5px')\n .attr('class', 'leaflet-control-colorBar-title')\n .text(this.options.title);\n return d.innerHTML;\n },\n\n palette: function() {\n let d = document.createElement('div');\n let svg = this._createSvgIn(d);\n\n this._appendColorBarTo(svg);\n\n if (this.options.labels) {\n this._appendLabelsTo(svg);\n }\n\n return d.innerHTML;\n },\n\n _createSvgIn: function(d) {\n let spaceForLabels = this.options.labels ? this.options.margin : 0;\n let svg = d3\n .select(d)\n .append('svg')\n .attr('width', this.options.width + this.options.margin * 2)\n .attr('height', this.options.height + spaceForLabels);\n return svg;\n },\n\n _appendColorBarTo: function(svg) {\n const colorPerValue = this._getColorPerValue();\n const w = this.options.width / colorPerValue.length;\n\n let groupBars = svg.append('g').attr('id', 'colorBar-buckets');\n let buckets = groupBars\n .selectAll('rect')\n .data(colorPerValue)\n .enter()\n .append('rect');\n buckets\n .attr('x', (d, i) => i * w + this.options.margin)\n .attr('y', () => 0)\n .attr('height', () => this.options.height /*w * 4*/)\n .attr('width', () => w)\n .attr('stroke-width', 2)\n .attr('stroke-linecap', 'butt')\n .attr('stroke', d => d.color.hex())\n .attr('fill', d => d.color.hex());\n buckets\n .append('title')\n .text(\n d =>\n `${d.value.toFixed(this.options.decimals)} ${this.options\n .units}`\n );\n },\n\n _appendLabelsTo: function(svg) {\n const positionPerLabelValue = this._getPositionPerLabelValue();\n //const w = this.options.width / colorPerValue.length;\n let groupLabels = svg.append('g').attr('id', 'colorBar-labels');\n let labels = groupLabels\n .selectAll('text')\n .data(positionPerLabelValue)\n .enter()\n .append('text');\n labels\n .attr('x', d => d.position + this.options.margin)\n .attr('y', this.options.height + this.options.margin)\n .attr('font-size', `${this.options.labelFontSize}px`)\n .attr('text-anchor', this.options.labelTextPosition)\n .attr('fill', this.options.textColor)\n .attr('class', 'leaflet-control-colorBar-label')\n .text(d => `${d.value.toFixed(this.options.decimals)}`);\n },\n\n _getColorPerValue: function() {\n const [min, max] = this.range;\n let delta = (max - min) / this.options.steps;\n let data = d3.range(min, max + delta, delta);\n let colorPerValue = data.map(d => {\n return {\n value: d,\n color: this.color(d)\n };\n });\n return colorPerValue;\n },\n\n _getPositionPerLabelValue: function() {\n var xPositionFor = d3\n .scaleLinear()\n .range([0, this.options.width])\n .domain(this.range);\n let data = this.options.labels;\n let positionPerLabel = data.map(d => {\n return {\n value: d,\n position: xPositionFor(d)\n };\n });\n return positionPerLabel;\n }\n});\n\nL.control.colorBar = function(color, range, options) {\n return new L.Control.ColorBar(color, range, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./control/L.Control.ColorBar.js","/**\n * Abstract class for a Field layer on canvas, aka 'a Raster layer'\n * (ScalarField or a VectorField)\n */\nL.CanvasLayer.Field = L.CanvasLayer.extend({\n options: {\n mouseMoveCursor: {\n value: 'pointer',\n noValue: 'default'\n },\n opacity: 1,\n onClick: null,\n onMouseMove: null,\n inFilter: null\n },\n\n initialize: function(field, options) {\n L.Util.setOptions(this, options);\n this._visible = true;\n if (field) {\n this.setData(field);\n }\n },\n\n getEvents: function() {\n var events = L.CanvasLayer.prototype.getEvents.call(this);\n events.zoomstart = this._hideCanvas.bind(this);\n events.zoomend = this._showCanvas.bind(this);\n return events;\n },\n\n onLayerDidMount: function() {\n this._enableIdentify();\n this._ensureCanvasAlignment();\n },\n\n show() {\n this._visible = true;\n this._showCanvas();\n this._enableIdentify();\n },\n\n hide() {\n this._visible = false;\n this._hideCanvas();\n this._disableIdentify();\n },\n\n isVisible() {\n return this._visible;\n },\n\n _showCanvas() {\n if (this._canvas && this._visible) {\n this._canvas.style.visibility = 'visible';\n }\n },\n\n _hideCanvas() {\n if (this._canvas) {\n this._canvas.style.visibility = 'hidden';\n }\n },\n\n _enableIdentify() {\n this._map.on('click', this._onClick, this);\n this._map.on('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.on('click', this.options.onClick, this);\n this.options.onMouseMove &&\n this.on('mousemove', this.options.onMouseMove, this);\n },\n\n _disableIdentify() {\n this._map.off('click', this._onClick, this);\n this._map.off('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.off('click', this.options.onClick, this);\n this.options.onMouseMove &&\n this.off('mousemove', this.options.onMouseMove, this);\n },\n\n _ensureCanvasAlignment() {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n },\n\n onLayerWillUnmount: function() {\n this._disableIdentify();\n },\n\n needRedraw() {\n if (this._map && this._field) {\n L.CanvasLayer.prototype.needRedraw.call(this);\n }\n },\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function(viewInfo) {\n throw new TypeError('Must be overriden');\n },\n /* eslint-enable no-unused-vars */\n\n setData: function(field) {\n this.options.inFilter && field.setFilter(this.options.inFilter);\n this._field = field;\n this.needRedraw();\n this.fire('load');\n },\n\n setFilter: function(f) {\n this.options.inFilter = f;\n this._field && this._field.setFilter(f);\n this.needRedraw();\n },\n\n setOpacity: function(opacity) {\n this.options.opacity = opacity;\n\n if (this._canvas) {\n this._updateOpacity();\n }\n return this;\n },\n\n getBounds: function() {\n let bb = this._field.extent();\n\n let southWest = L.latLng(bb[1], bb[0]),\n northEast = L.latLng(bb[3], bb[2]);\n let bounds = L.latLngBounds(southWest, northEast);\n return bounds;\n },\n\n _onClick: function(e) {\n let v = this._queryValue(e);\n this.fire('click', v);\n },\n\n _onMouseMove: function(e) {\n let v = this._queryValue(e);\n this._changeCursorOn(v);\n this.fire('mousemove', v);\n },\n\n _changeCursorOn: function(v) {\n if (!this.options.mouseMoveCursor) return;\n\n let { value, noValue } = this.options.mouseMoveCursor;\n let style = this._map.getContainer().style;\n style.cursor = v.value !== null ? value : noValue;\n },\n\n _updateOpacity: function() {\n L.DomUtil.setOpacity(this._canvas, this.options.opacity);\n },\n\n _queryValue: function(e) {\n let v = this._field\n ? this._field.valueAt(e.latlng.lng, e.latlng.lat)\n : null;\n let result = {\n latlng: e.latlng,\n value: v\n };\n return result;\n },\n\n _getDrawingContext: function() {\n let g = this._canvas.getContext('2d');\n g.clearRect(0, 0, this._canvas.width, this._canvas.height);\n return g;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.Field.js","import Cell from '../Cell';\n\n/**\n * ScalarField on canvas (a 'Raster')\n */\nL.CanvasLayer.ScalarField = L.CanvasLayer.Field.extend({\n options: {\n type: 'colormap', // [colormap|vector]\n color: null, // function colorFor(value) [e.g. chromajs.scale],\n interpolate: false, // Change to use interpolation\n vectorSize: 20, // only used if 'vector'\n arrowDirection: 'from' // [from|towards]\n },\n\n initialize: function(scalarField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(\n this,\n scalarField,\n options\n );\n L.Util.setOptions(this, options);\n },\n\n _defaultColorScale: function() {\n return chroma.scale(['white', 'black']).domain(this._field.range);\n },\n\n setColor(f) {\n this.options.color = f;\n this.needRedraw();\n },\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function(viewInfo) {\n if (!this.isVisible()) return;\n this._updateOpacity();\n\n let r = this._getRendererMethod();\n //console.time('onDrawLayer');\n r();\n //console.timeEnd('onDrawLayer');\n },\n /* eslint-enable no-unused-vars */\n\n _getRendererMethod: function() {\n switch (this.options.type) {\n case 'colormap':\n return this._drawImage.bind(this);\n case 'vector':\n return this._drawArrows.bind(this);\n default:\n throw Error(`Unkwown renderer type: ${this.options.type}`);\n }\n },\n\n _ensureColor: function() {\n if (this.options.color === null) {\n this.setColor(this._defaultColorScale());\n }\n },\n\n _showCanvas() {\n L.CanvasLayer.Field.prototype._showCanvas.call(this);\n this.needRedraw(); // TODO check spurious redraw (e.g. hide/show without moving map)\n },\n\n /**\n * Draws the field in an ImageData and applying it with putImageData.\n * Used as a reference: http://geoexamples.com/d3-raster-tools-docs/code_samples/raster-pixels-page.html\n */\n _drawImage: function() {\n this._ensureColor();\n\n let ctx = this._getDrawingContext();\n let width = this._canvas.width;\n let height = this._canvas.height;\n\n let img = ctx.createImageData(width, height);\n let data = img.data;\n\n this._prepareImageIn(data, width, height);\n ctx.putImageData(img, 0, 0);\n },\n\n /**\n * Prepares the image in data, as array with RGBAs\n * [R1, G1, B1, A1, R2, G2, B2, A2...]\n * @private\n * @param {[[Type]]} data [[Description]]\n * @param {Numver} width\n * @param {Number} height\n */\n _prepareImageIn(data, width, height) {\n let f = this.options.interpolate ? 'interpolatedValueAt' : 'valueAt';\n\n let pos = 0;\n for (let j = 0; j < height; j++) {\n for (let i = 0; i < width; i++) {\n let pointCoords = this._map.containerPointToLatLng([i, j]);\n let lon = pointCoords.lng;\n let lat = pointCoords.lat;\n\n let v = this._field[f](lon, lat); // 'valueAt' | 'interpolatedValueAt' || TODO check some 'artifacts'\n if (v !== null) {\n let color = this._getColorFor(v);\n let [R, G, B, A] = color.rgba();\n data[pos] = R;\n data[pos + 1] = G;\n data[pos + 2] = B;\n data[pos + 3] = parseInt(A * 255); // not percent in alpha but hex 0-255\n }\n pos = pos + 4;\n }\n }\n },\n\n /**\n * Draws the field as a set of arrows. Direction from 0 to 360 is assumed.\n */\n _drawArrows: function() {\n const bounds = this._pixelBounds();\n const pixelSize = (bounds.max.x - bounds.min.x) / this._field.nCols;\n\n var stride = Math.max(\n 1,\n Math.floor(1.2 * this.options.vectorSize / pixelSize)\n );\n\n const ctx = this._getDrawingContext();\n ctx.strokeStyle = this.options.color;\n\n var currentBounds = this._map.getBounds();\n\n for (var y = 0; y < this._field.height; y = y + stride) {\n for (var x = 0; x < this._field.width; x = x + stride) {\n let [lon, lat] = this._field._lonLatAtIndexes(x, y);\n let v = this._field.valueAt(lon, lat);\n let center = L.latLng(lat, lon);\n if (v !== null && currentBounds.contains(center)) {\n let cell = new Cell(\n center,\n v,\n this.cellXSize,\n this.cellYSize\n );\n this._drawArrow(cell, ctx);\n }\n }\n }\n },\n\n _pixelBounds: function() {\n const bounds = this.getBounds();\n const northWest = this._map.latLngToContainerPoint(\n bounds.getNorthWest()\n );\n const southEast = this._map.latLngToContainerPoint(\n bounds.getSouthEast()\n );\n var pixelBounds = L.bounds(northWest, southEast);\n return pixelBounds;\n },\n\n _drawArrow: function(cell, ctx) {\n var projected = this._map.latLngToContainerPoint(cell.center);\n\n // colormap vs. simple color\n let color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(cell.value);\n }\n\n const size = this.options.vectorSize;\n ctx.save();\n\n ctx.translate(projected.x, projected.y);\n\n let rotationRads = (90 + cell.value) * Math.PI / 180; // from, by default\n if (this.options.arrowDirection === 'towards') {\n rotationRads = rotationRads + Math.PI;\n }\n ctx.rotate(rotationRads);\n\n ctx.beginPath();\n ctx.moveTo(-size / 2, 0);\n ctx.lineTo(+size / 2, 0);\n ctx.moveTo(size * 0.25, -size * 0.25);\n ctx.lineTo(+size / 2, 0);\n ctx.lineTo(size * 0.25, size * 0.25);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Gets a chroma color for a pixel value, according to 'options.color'\n */\n _getColorFor(v) {\n let c = this.options.color; // e.g. for a constant 'red'\n if (typeof c === 'function') {\n c = this.options.color(v);\n }\n let color = chroma(c); // to be more flexible, a chroma color object is always created || TODO improve efficiency\n return color;\n }\n});\n\nL.canvasLayer.scalarField = function(scalarField, options) {\n return new L.CanvasLayer.ScalarField(scalarField, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.ScalarField.js","/**\n * Simple layer with lon-lat points\n *\n * TODO rename to SimplePoint?\n */\nL.CanvasLayer.SimpleLonLat = L.CanvasLayer.extend({\n options: {\n color: 'gray'\n },\n\n initialize: function(points, options) {\n this.points = points;\n L.Util.setOptions(this, options);\n },\n\n onLayerDidMount: function() {\n // -- prepare custom drawing\n },\n\n onLayerWillUnmount: function() {\n // -- custom cleanup\n },\n\n /* eslint-disable no-unused-vars */\n setData: function(data) {\n // -- custom data set\n this.needRedraw(); // -- call to drawLayer\n },\n /* eslint-enable no-unused-vars */\n\n onDrawLayer: function(viewInfo) {\n // canvas preparation\n let g = viewInfo.canvas.getContext('2d');\n g.clearRect(0, 0, viewInfo.canvas.width, viewInfo.canvas.height);\n g.fillStyle = this.options.color;\n\n for (let point of this.points) {\n let p = viewInfo.layer._map.latLngToContainerPoint(point);\n g.beginPath();\n //g.arc(p.x, p.y, 1, 0, Math.PI * 2); // circle | TODO style 'function' as parameter?\n g.fillRect(p.x, p.y, 2, 2); //simple point\n g.fill();\n g.closePath();\n g.stroke();\n }\n },\n\n getBounds: function() {\n // TODO: bounding with points...\n let xs = this.points.map(pt => pt.lng);\n let ys = this.points.map(pt => pt.lat);\n\n let xmin = Math.min(...xs);\n let ymin = Math.min(...ys);\n let xmax = Math.max(...xs);\n let ymax = Math.max(...ys);\n\n let southWest = L.latLng(ymin, xmin),\n northEast = L.latLng(ymax, xmax);\n let bounds = L.latLngBounds(southWest, northEast); // TODO FIX ERROR ? half-pixel?\n return bounds;\n }\n});\n\nL.canvasLayer.simpleLonLat = function(lonslats, options) {\n return new L.CanvasLayer.SimpleLonLat(lonslats, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.SimpleLonLat.js","/**\n * Animated VectorField on canvas\n */\nL.CanvasLayer.VectorFieldAnim = L.CanvasLayer.Field.extend({\n options: {\n paths: 800,\n color: 'white', // html-color | function colorFor(value) [e.g. chromajs.scale]\n width: 1.0, // number | function widthFor(value)\n fade: 0.96, // 0 to 1\n duration: 20, // milliseconds per 'frame'\n maxAge: 200, // number of maximum frames per path\n velocityScale: 1 / 5000\n },\n\n initialize: function(vectorField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(\n this,\n vectorField,\n options\n );\n L.Util.setOptions(this, options);\n\n this.timer = null;\n },\n\n onLayerDidMount: function() {\n L.CanvasLayer.Field.prototype.onLayerDidMount.call(this);\n this._map.on('move resize', this._stopAnimation, this);\n },\n\n onLayerWillUnmount: function() {\n L.CanvasLayer.Field.prototype.onLayerWillUnmount.call(this);\n this._map.off('move resize', this._stopAnimation, this);\n this._stopAnimation();\n },\n\n _hideCanvas: function _showCanvas() {\n L.CanvasLayer.Field.prototype._hideCanvas.call(this);\n this._stopAnimation();\n },\n\n onDrawLayer: function(viewInfo) {\n if (!this._field || !this.isVisible()) return;\n\n this._updateOpacity();\n\n let ctx = this._getDrawingContext();\n let paths = this._prepareParticlePaths();\n\n this.timer = d3.timer(function() {\n _moveParticles();\n _drawParticles();\n }, this.options.duration);\n\n let self = this;\n\n /**\n * Builds the paths, adding 'particles' on each animation step, considering\n * their properties (age / position source > target)\n */\n function _moveParticles() {\n // let screenFactor = 1 / self._map.getZoom(); // consider using a 'screenFactor' to ponderate velocityScale\n paths.forEach(function(par) {\n if (par.age > self.options.maxAge) {\n // restart, on a random x,y\n par.age = 0;\n self._field.randomPosition(par);\n }\n\n let vector = self._field.valueAt(par.x, par.y);\n if (vector === null) {\n par.age = self.options.maxAge;\n } else {\n // the next point will be...\n let xt = par.x + vector.u * self.options.velocityScale; //* screenFactor;\n let yt = par.y + vector.v * self.options.velocityScale; //* screenFactor;\n\n if (self._field.hasValueAt(xt, yt)) {\n par.xt = xt;\n par.yt = yt;\n par.m = vector.magnitude();\n } else {\n // not visible anymore...\n par.age = self.options.maxAge;\n }\n }\n par.age += 1;\n });\n }\n\n /**\n * Draws the paths on each step\n */\n function _drawParticles() {\n // Previous paths...\n let prev = ctx.globalCompositeOperation;\n ctx.globalCompositeOperation = 'destination-in';\n ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n //ctx.globalCompositeOperation = 'source-over';\n ctx.globalCompositeOperation = prev;\n\n // fading paths...\n ctx.fillStyle = `rgba(0, 0, 0, ${self.options.fade})`;\n ctx.lineWidth = self.options.width;\n ctx.strokeStyle = self.options.color;\n\n // New paths\n paths.forEach(function(par) {\n self._drawParticle(viewInfo, ctx, par);\n });\n }\n },\n\n _drawParticle(viewInfo, ctx, par) {\n let source = new L.latLng(par.y, par.x);\n let target = new L.latLng(par.yt, par.xt);\n\n if (\n viewInfo.bounds.contains(source) &&\n par.age <= this.options.maxAge\n ) {\n let pA = viewInfo.layer._map.latLngToContainerPoint(source);\n let pB = viewInfo.layer._map.latLngToContainerPoint(target);\n\n ctx.beginPath();\n ctx.moveTo(pA.x, pA.y);\n ctx.lineTo(pB.x, pB.y);\n\n // next-step movement\n par.x = par.xt;\n par.y = par.yt;\n\n // colormap vs. simple color\n let color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(par.m);\n }\n\n let width = this.options.width;\n if (typeof width === 'function') {\n ctx.lineWidth = width(par.m);\n }\n\n ctx.stroke();\n }\n },\n\n _prepareParticlePaths: function() {\n let paths = [];\n\n for (var i = 0; i < this.options.paths; i++) {\n let p = this._field.randomPosition();\n p.age = this._randomAge();\n paths.push(p);\n }\n return paths;\n },\n\n _randomAge: function() {\n return Math.floor(Math.random() * this.options.maxAge);\n },\n\n _stopAnimation: function() {\n if (this.timer) {\n this.timer.stop();\n }\n }\n});\n\nL.canvasLayer.vectorFieldAnim = function(vectorField, options) {\n return new L.CanvasLayer.VectorFieldAnim(vectorField, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.VectorFieldAnim.js","/*\n 1.0.1 (downloaded from https://github.com/Sumbera/gLayers.Leaflet/releases/tag/v1.0.1)\n\n Generic Canvas Layer for leaflet 0.7 and 1.0-rc,\n copyright Stanislav Sumbera, 2016 , sumbera.com , license MIT\n originally created and motivated by L.CanvasOverlay available here: https://gist.github.com/Sumbera/11114288\n*/\n\nL.CanvasLayer = L.Layer.extend({\n // -- initialized is called on prototype\n initialize: function (options) {\n this._map = null;\n this._canvas = null;\n this._frame = null;\n this._delegate = null;\n L.setOptions(this, options);\n },\n\n delegate: function (del) {\n this._delegate = del;\n return this;\n },\n\n needRedraw: function () {\n if (!this._frame) {\n this._frame = L.Util.requestAnimFrame(this.drawLayer, this);\n }\n return this;\n },\n\n //-------------------------------------------------------------\n _onLayerDidResize: function (resizeEvent) {\n this._canvas.width = resizeEvent.newSize.x;\n this._canvas.height = resizeEvent.newSize.y;\n },\n //-------------------------------------------------------------\n _onLayerDidMove: function () {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n this.drawLayer();\n },\n //-------------------------------------------------------------\n getEvents: function () {\n var events = {\n resize: this._onLayerDidResize,\n moveend: this._onLayerDidMove\n };\n if (this._map.options.zoomAnimation && L.Browser.any3d) {\n events.zoomanim = this._animateZoom;\n }\n\n return events;\n },\n //-------------------------------------------------------------\n onAdd: function (map) {\n this._map = map;\n this._canvas = L.DomUtil.create('canvas', 'leaflet-layer');\n this.tiles = {};\n\n var size = this._map.getSize();\n this._canvas.width = size.x;\n this._canvas.height = size.y;\n\n var animated = this._map.options.zoomAnimation && L.Browser.any3d;\n L.DomUtil.addClass(this._canvas, 'leaflet-zoom-' + (animated ? 'animated' : 'hide'));\n\n\n map._panes.overlayPane.appendChild(this._canvas);\n\n map.on(this.getEvents(), this);\n\n var del = this._delegate || this;\n del.onLayerDidMount && del.onLayerDidMount(); // -- callback\n\n this.needRedraw();\n },\n\n //-------------------------------------------------------------\n onRemove: function (map) {\n var del = this._delegate || this;\n del.onLayerWillUnmount && del.onLayerWillUnmount(); // -- callback\n\n\n map.getPanes().overlayPane.removeChild(this._canvas);\n\n map.off(this.getEvents(), this);\n\n this._canvas = null;\n\n },\n\n //------------------------------------------------------------\n addTo: function (map) {\n map.addLayer(this);\n return this;\n },\n // --------------------------------------------------------------------------------\n LatLonToMercator: function (latlon) {\n return {\n x: latlon.lng * 6378137 * Math.PI / 180,\n y: Math.log(Math.tan((90 + latlon.lat) * Math.PI / 360)) * 6378137\n };\n },\n\n //------------------------------------------------------------------------------\n drawLayer: function () {\n // -- todo make the viewInfo properties flat objects.\n var size = this._map.getSize();\n var bounds = this._map.getBounds();\n var zoom = this._map.getZoom();\n\n var center = this.LatLonToMercator(this._map.getCenter());\n var corner = this.LatLonToMercator(this._map.containerPointToLatLng(this._map.getSize()));\n\n var del = this._delegate || this;\n del.onDrawLayer && del.onDrawLayer({\n layer: this,\n canvas: this._canvas,\n bounds: bounds,\n size: size,\n zoom: zoom,\n center: center,\n corner: corner\n });\n this._frame = null;\n },\n\n //------------------------------------------------------------------------------\n _animateZoom: function (e) {\n var scale = this._map.getZoomScale(e.zoom);\n var offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), e.zoom, e.center);\n\n L.DomUtil.setTransform(this._canvas, offset, scale);\n }\n});\n\nL.canvasLayer = function () {\n return new L.CanvasLayer();\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.js","var invariant = require('@turf/invariant');\nvar getCoord = invariant.getCoord;\nvar getCoords = invariant.getCoords;\n\n// http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule\n// modified from: https://github.com/substack/point-in-polygon/blob/master/index.js\n// which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n\n/**\n * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can\n * be convex or concave. The function accounts for holes.\n *\n * @name inside\n * @param {Feature} point input point\n * @param {Feature} polygon input polygon or multipolygon\n * @param {boolean} [ignoreBoundary=false] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false.\n * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon\n * @example\n * var pt = turf.point([-77, 44]);\n * var poly = turf.polygon([[\n * [-81, 41],\n * [-81, 47],\n * [-72, 47],\n * [-72, 41],\n * [-81, 41]\n * ]]);\n *\n * turf.inside(pt, poly);\n * //= true\n */\nmodule.exports = function (point, polygon, ignoreBoundary) {\n // validation\n if (!point) throw new Error('point is required');\n if (!polygon) throw new Error('polygon is required');\n\n var pt = getCoord(point);\n var polys = getCoords(polygon);\n var type = (polygon.geometry) ? polygon.geometry.type : polygon.type;\n var bbox = polygon.bbox;\n\n // Quick elimination if point is not inside bbox\n if (bbox && inBBox(pt, bbox) === false) return false;\n\n // normalize to multipolygon\n if (type === 'Polygon') polys = [polys];\n\n for (var i = 0, insidePoly = false; i < polys.length && !insidePoly; i++) {\n // check if it is in the outer ring first\n if (inRing(pt, polys[i][0], ignoreBoundary)) {\n var inHole = false;\n var k = 1;\n // check for the point in any of the holes\n while (k < polys[i].length && !inHole) {\n if (inRing(pt, polys[i][k], !ignoreBoundary)) {\n inHole = true;\n }\n k++;\n }\n if (!inHole) insidePoly = true;\n }\n }\n return insidePoly;\n};\n\n/**\n * inRing\n *\n * @private\n * @param {[number, number]} pt [x,y]\n * @param {Array<[number, number]>} ring [[x,y], [x,y],..]\n * @param {boolean} ignoreBoundary ignoreBoundary\n * @returns {boolean} inRing\n */\nfunction inRing(pt, ring, ignoreBoundary) {\n var isInside = false;\n if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1);\n\n for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n var xi = ring[i][0], yi = ring[i][1];\n var xj = ring[j][0], yj = ring[j][1];\n var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) &&\n ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0);\n if (onBoundary) return !ignoreBoundary;\n var intersect = ((yi > pt[1]) !== (yj > pt[1])) &&\n (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi);\n if (intersect) isInside = !isInside;\n }\n return isInside;\n}\n\n/**\n * inBBox\n *\n * @private\n * @param {[number, number]} pt point [x,y]\n * @param {[number, number, number, number]} bbox BBox [west, south, east, north]\n * @returns {boolean} true/false if point is inside BBox\n */\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] &&\n bbox[1] <= pt[1] &&\n bbox[2] >= pt[0] &&\n bbox[3] >= pt[1];\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/@turf/inside/index.js\n// module id = 11\n// module chunks = 0","/**\n * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.\n *\n * @name getCoord\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var pt = turf.point([10, 10]);\n *\n * var coord = turf.getCoord(pt);\n * //= [10, 10]\n */\nfunction getCoord(obj) {\n if (!obj) throw new Error('obj is required');\n\n var coordinates = getCoords(obj);\n\n // getCoord() must contain at least two numbers (Point)\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return coordinates;\n } else {\n throw new Error('Coordinate is not a valid Point');\n }\n}\n\n/**\n * Unwrap coordinates from a Feature, Geometry Object or an Array of numbers\n *\n * @name getCoords\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]);\n *\n * var coord = turf.getCoords(poly);\n * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]\n */\nfunction getCoords(obj) {\n if (!obj) throw new Error('obj is required');\n var coordinates;\n\n // Array of numbers\n if (obj.length) {\n coordinates = obj;\n\n // Geometry Object\n } else if (obj.coordinates) {\n coordinates = obj.coordinates;\n\n // Feature\n } else if (obj.geometry && obj.geometry.coordinates) {\n coordinates = obj.geometry.coordinates;\n }\n // Checks if coordinates contains a number\n if (coordinates) {\n containsNumber(coordinates);\n return coordinates;\n }\n throw new Error('No valid coordinates');\n}\n\n/**\n * Checks if coordinates contains a number\n *\n * @name containsNumber\n * @param {Array} coordinates GeoJSON Coordinates\n * @returns {boolean} true if Array contains a number\n */\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return true;\n }\n\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error('coordinates must only contain numbers');\n}\n\n/**\n * Enforce expectations about types of GeoJSON objects for Turf.\n *\n * @name geojsonType\n * @param {GeoJSON} value any GeoJSON object\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction geojsonType(value, type, name) {\n if (!type || !name) throw new Error('type and name required');\n\n if (!value || value.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + value.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link Feature} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name featureOf\n * @param {Feature} feature a feature with an expected geometry type\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} error if value is not the expected type.\n */\nfunction featureOf(feature, type, name) {\n if (!feature) throw new Error('No feature passed');\n if (!name) throw new Error('.featureOf() requires a name');\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link FeatureCollection} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name collectionOf\n * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) throw new Error('No featureCollection passed');\n if (!name) throw new Error('.collectionOf() requires a name');\n if (!featureCollection || featureCollection.type !== 'FeatureCollection') {\n throw new Error('Invalid input to ' + name + ', FeatureCollection required');\n }\n for (var i = 0; i < featureCollection.features.length; i++) {\n var feature = featureCollection.features[i];\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n }\n}\n\n/**\n * Get Geometry from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {Geometry|null} GeoJSON Geometry Object\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeom(point)\n * //={\"type\": \"Point\", \"coordinates\": [110, 40]}\n */\nfunction getGeom(geojson) {\n if (!geojson) throw new Error('geojson is required');\n if (geojson.geometry !== undefined) return geojson.geometry;\n if (geojson.coordinates || geojson.geometries) return geojson;\n throw new Error('geojson must be a valid Feature or Geometry Object');\n}\n\n/**\n * Get Geometry Type from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {string} GeoJSON Geometry Type\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeomType(point)\n * //=\"Point\"\n */\nfunction getGeomType(geojson) {\n if (!geojson) throw new Error('geojson is required');\n var geom = getGeom(geojson);\n if (geom) return geom.type;\n}\n\nmodule.exports = {\n geojsonType: geojsonType,\n collectionOf: collectionOf,\n featureOf: featureOf,\n getCoord: getCoord,\n getCoords: getCoords,\n containsNumber: containsNumber,\n getGeom: getGeom,\n getGeomType: getGeomType\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/@turf/invariant/index.js\n// module id = 12\n// module chunks = 0","// base\nimport Vector from './Vector.js';\nwindow.L.Vector = Vector;\n\nimport Cell from './Cell.js';\nwindow.L.Cell = Cell;\n\nimport Field from './Field.js';\nwindow.L.Field = Field;\n\nimport ScalarField from './ScalarField.js';\nwindow.L.ScalarField = ScalarField;\n\nimport VectorField from './VectorField.js';\nwindow.L.VectorField = VectorField;\n\n// layer\nrequire('./layer/L.CanvasLayer.js');\nrequire('./layer/L.CanvasLayer.SimpleLonLat.js');\nrequire('./layer/L.CanvasLayer.Field.js');\nrequire('./layer/L.CanvasLayer.ScalarField.js');\nrequire('./layer/L.CanvasLayer.VectorFieldAnim.js');\n\n// control\nrequire('./control/L.Control.ColorBar.js');\n\n/* eslint-disable no-console */\nconsole.log('leaflet.canvaslayer.field v1.4.0 in progress...');\n/* eslint-enable no-console */\n\n\n\n// WEBPACK FOOTER //\n// ./_main.js"],"sourceRoot":""} \ No newline at end of file +{"version":3,"sources":["webpack:///leaflet.canvaslayer.field.js","webpack:///webpack/bootstrap 82891af380a66293e679","webpack:///./Cell.js","webpack:///./Field.js","webpack:///./ScalarField.js","webpack:///./Vector.js","webpack:///./VectorField.js","webpack:///./control/L.Control.ColorBar.js","webpack:///./layer/L.CanvasLayer.Field.js","webpack:///./layer/L.CanvasLayer.ScalarField.js","webpack:///./layer/L.CanvasLayer.SimpleLonLat.js","webpack:///./layer/L.CanvasLayer.VectorFieldAnim.js","webpack:///./layer/L.CanvasLayer.js","webpack:///../~/@turf/inside/index.js","webpack:///../~/@turf/invariant/index.js","webpack:///./_main.js"],"names":["modules","__webpack_require__","moduleId","installedModules","exports","module","i","l","call","m","c","value","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","__webpack_exports__","_classCallCheck","instance","Constructor","TypeError","_createClass","defineProperties","target","props","length","descriptor","writable","key","protoProps","staticProps","Cell","center","xSize","ySize","arguments","undefined","this","anotherCell","equals","_equalValues","anotherValue","type","constructor","Number","Vector","u","v","halfX","halfY","cLat","lat","cLng","lng","ul","L","latLng","lr","latLngBounds","__WEBPACK_IMPORTED_MODULE_0__Cell__","__WEBPACK_IMPORTED_MODULE_1__turf_inside__","__WEBPACK_IMPORTED_MODULE_1__turf_inside___default","_slicedToArray","sliceIterator","arr","_arr","_n","_d","_e","_s","_i","Symbol","iterator","next","done","push","err","Array","isArray","Field","params","nCols","nRows","width","height","xllCorner","yllCorner","xurCorner","yurCorner","cellXSize","cellYSize","grid","isContinuous","longitudeNeedsToBeWrapped","_inFilter","_spatialMask","range","_calculateRange","stride","cells","j","_lonLatAtIndexes2","_lonLatAtIndexes","_lonLatAtIndexes3","lon","_valueAtIndexes","f","_updateRange","_getWrappedLongitudes2","_getWrappedLongitudes","_getWrappedLongitudes3","xmin","xmax","_pointInMask","_pointInExtent","_getWrappedLongitudes4","_getWrappedLongitudes5","longitudeIn","latitudeIn","pt","geometry","coordinates","properties","poly","contains","notContains","_getDecimalIndexes2","_getDecimalIndexes","_getDecimalIndexes3","interpolatedValueAtIndexes","indexes","_getFourSurroundingIndexes","_indexes","fi","ci","fj","cj","values","_getFourSurroundingValues","_values","g00","g10","g01","g11","_doInterpolation","Math","floor","_clampColumnIndex","_clampRowIndex","row","_isValid","_getDecimalIndexes4","_getDecimalIndexes5","ii","jj","valueAt","hasValue","included","hasValueAt","random","x","_longitudeAtX","y","_latitudeAtY","halfXPixel","halfYPixel","maxCol","maxRow","_possibleConstructorReturn","self","ReferenceError","_inherits","subClass","superClass","create","setPrototypeOf","__proto__","__WEBPACK_IMPORTED_MODULE_0__Field__","ScalarField","_Field","_this","getPrototypeOf","zs","_buildGrid","asc","scaleFactor","lines","split","_checkIsValidASCIIGridHeader","cellSize","parseFloat","match","parseInt","noDataValue","toUpperCase","replace","trim","line","forEach","it","upperCasesLines","map","lin","parameters","_iteratorNormalCompletion","_didIteratorError","_iteratorError","_step","_iterator","expected","indexOf","return","data","bandIndex","tiff","GeoTIFF","parse","image","getImage","rasters","readRasters","tiepoint","getTiePoints","fileDirectory","getFileDirectory","_fileDirectory$ModelP","ModelPixelScale","xScale","yScale","GDAL_NODATA","noData","from","z","getWidth","getHeight","_arrayTo2d","array","filter","d3","min","max","rx","ry","sqrt","verticalAngle","atan2","inDegrees","PI","directionTo","__WEBPACK_IMPORTED_MODULE_0__Vector__","__WEBPACK_IMPORTED_MODULE_1__Field__","__WEBPACK_IMPORTED_MODULE_2__ScalarField__","VectorField","us","vs","ascU","ascV","fromASCIIGrid","_paramsFromScalarFields","gtU","gtV","fromGeoTIFF","geotiffData","bandIndexesForUV","_getFunctionFor","_applyOnField","func","numCells","_arraysTo2d","valid","vectors","getCells","magnitudes","magnitude","a","b","Control","ColorBar","extend","options","position","margin","background","textColor","steps","decimals","units","title","labels","labelFontSize","labelTextPosition","initialize","color","Util","setOptions","onAdd","_map","div","DomUtil","style","padding","DomEvent","addListener","stopPropagation","preventDefault","backgroundColor","cursor","innerHTML","palette","document","createElement","select","append","attr","text","svg","_createSvgIn","_appendColorBarTo","_appendLabelsTo","spaceForLabels","colorPerValue","_getColorPerValue","w","groupBars","buckets","selectAll","enter","hex","toFixed","_this2","positionPerLabelValue","_getPositionPerLabelValue","_this3","_range","delta","xPositionFor","scaleLinear","domain","control","colorBar","CanvasLayer","mouseMoveCursor","noValue","opacity","onClick","onMouseMove","inFilter","field","_visible","setData","getEvents","events","zoomstart","_hideCanvas","bind","zoomend","_showCanvas","onLayerDidMount","_enableIdentify","_ensureCanvasAlignment","show","hide","_disableIdentify","isVisible","_canvas","visibility","on","_onClick","_onMouseMove","off","topLeft","containerPointToLayerPoint","setPosition","onLayerWillUnmount","needRedraw","_field","onDrawLayer","viewInfo","setFilter","fire","setOpacity","_updateOpacity","getBounds","bb","extent","southWest","northEast","e","_queryValue","_changeCursorOn","_options$mouseMoveCur","getContainer","latlng","_getDrawingContext","g","getContext","clearRect","interpolate","vectorSize","arrowDirection","scalarField","_defaultColorScale","chroma","scale","setColor","_getRendererMethod","_drawImage","_drawArrows","Error","_ensureColor","ctx","img","createImageData","_prepareImageIn","putImageData","pos","pointCoords","containerPointToLatLng","_getColorFor","_color$rgba","rgba","_color$rgba2","R","G","B","A","bounds","_pixelBounds","pixelSize","strokeStyle","currentBounds","_field$_lonLatAtIndex","_field$_lonLatAtIndex2","cell","_drawArrow","northWest","latLngToContainerPoint","getNorthWest","southEast","getSouthEast","projected","size","save","translate","rotationRads","rotate","beginPath","moveTo","lineTo","stroke","restore","canvasLayer","_toConsumableArray","arr2","SimpleLonLat","points","canvas","fillStyle","point","layer","fillRect","fill","closePath","xs","ys","apply","ymin","ymax","simpleLonLat","lonslats","VectorFieldAnim","paths","fade","duration","maxAge","velocityScale","vectorField","timer","_stopAnimation","_moveParticles","par","age","randomPosition","vector","xt","yt","_drawParticles","prev","globalCompositeOperation","lineWidth","_drawParticle","_prepareParticlePaths","source","pA","pB","_randomAge","stop","vectorFieldAnim","Layer","_frame","_delegate","delegate","del","requestAnimFrame","drawLayer","_onLayerDidResize","resizeEvent","newSize","_onLayerDidMove","resize","moveend","zoomAnimation","Browser","any3d","zoomanim","_animateZoom","tiles","getSize","animated","addClass","_panes","overlayPane","appendChild","onRemove","getPanes","removeChild","addTo","addLayer","LatLonToMercator","latlon","log","tan","zoom","getZoom","getCenter","corner","getZoomScale","offset","_latLngToNewLayerPoint","setTransform","inRing","ring","ignoreBoundary","isInside","slice","xi","yi","xj","yj","inBBox","bbox","invariant","getCoord","getCoords","polygon","polys","insidePoly","inHole","k","obj","containsNumber","geojsonType","featureOf","feature","collectionOf","featureCollection","features","getGeom","geojson","geometries","getGeomType","geom","__WEBPACK_IMPORTED_MODULE_0__Vector_js__","__WEBPACK_IMPORTED_MODULE_1__Cell_js__","__WEBPACK_IMPORTED_MODULE_2__Field_js__","__WEBPACK_IMPORTED_MODULE_3__ScalarField_js__","__WEBPACK_IMPORTED_MODULE_4__VectorField_js__","window","console"],"mappings":"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","file":"leaflet.canvaslayer.field.js","sourcesContent":["/******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId]) {\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/ \t\t}\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// identity function for calling harmony imports with the correct context\n/******/ \t__webpack_require__.i = function(value) { return value; };\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 13);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * Simple regular cell in a raster\n */\nvar Cell = function () {\n /**\n * A simple cell with a numerical value\n * @param {L.LatLng} center\n * @param {Number|Vector} value\n * @param {Number} xSize\n * @param {Number} ySize\n */\n function Cell(center, value, xSize) {\n var ySize = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : xSize;\n\n _classCallCheck(this, Cell);\n\n this.center = center;\n this.value = value;\n this.xSize = xSize;\n this.ySize = ySize;\n }\n\n _createClass(Cell, [{\n key: \"equals\",\n value: function equals(anotherCell) {\n return this.center.equals(anotherCell.center) && this._equalValues(this.value, anotherCell.value) && this.xSize === anotherCell.xSize && this.ySize === anotherCell.ySize;\n }\n }, {\n key: \"_equalValues\",\n value: function _equalValues(value, anotherValue) {\n var type = value.constructor.name;\n var answerFor = {\n Number: value === anotherValue,\n Vector: value.u === anotherValue.u && value.v === anotherValue.v\n };\n return answerFor[type];\n }\n\n /**\n * Bounds for the cell\n * @returns {LatLngBounds}\n */\n\n }, {\n key: \"getBounds\",\n value: function getBounds() {\n var halfX = this.xSize / 2.0;\n var halfY = this.ySize / 2.0;\n var cLat = this.center.lat;\n var cLng = this.center.lng;\n var ul = L.latLng([cLat + halfY, cLng - halfX]);\n var lr = L.latLng([cLat - halfY, cLng + halfX]);\n\n return L.latLngBounds(L.latLng(lr.lat, ul.lng), L.latLng(ul.lat, lr.lng));\n }\n }]);\n\n return Cell;\n}();\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (Cell);\n\n/***/ }),\n/* 1 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Cell__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__turf_inside__ = __webpack_require__(11);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__turf_inside___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__turf_inside__);\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n\n\n\n/**\n * Abstract class for a set of values (Vector | Scalar)\n * assigned to a regular 2D-grid (lon-lat), aka 'a Raster source'\n */\n\nvar Field = function () {\n function Field(params) {\n _classCallCheck(this, Field);\n\n this.params = params;\n\n this.nCols = params['nCols'];\n this.nRows = params['nRows'];\n\n // alias\n this.width = params['nCols'];\n this.height = params['nRows'];\n\n // ll = lower-left\n this.xllCorner = params['xllCorner'];\n this.yllCorner = params['yllCorner'];\n\n // ur = upper-right\n this.xurCorner = params['xllCorner'] + params['nCols'] * params['cellXSize'];\n this.yurCorner = params['yllCorner'] + params['nRows'] * params['cellYSize'];\n\n this.cellXSize = params['cellXSize'];\n this.cellYSize = params['cellYSize'];\n\n this.grid = null; // to be defined by subclasses\n this.isContinuous = this.xurCorner - this.xllCorner >= 360;\n this.longitudeNeedsToBeWrapped = this.xurCorner > 180; // [0, 360] --> [-180, 180]\n\n this._inFilter = null;\n this._spatialMask = null;\n }\n\n /**\n * Builds a grid with a value at each point (either Vector or Number)\n * Original params must include the required input values, following\n * x-ascending & y-descending order (same as in ASCIIGrid)\n * @abstract\n * @private\n * @returns {Array.>} - grid[row][column]--> Vector|Number\n */\n\n\n _createClass(Field, [{\n key: '_buildGrid',\n value: function _buildGrid() {\n throw new TypeError('Must be overriden');\n }\n }, {\n key: '_updateRange',\n value: function _updateRange() {\n this.range = this._calculateRange();\n }\n\n /**\n * Number of cells in the grid (rows * cols)\n * @returns {Number}\n */\n\n }, {\n key: 'numCells',\n value: function numCells() {\n return this.nRows * this.nCols;\n }\n\n /**\n * A list with every cell\n * @returns {Array} - cells (x-ascending & y-descending order)\n */\n\n }, {\n key: 'getCells',\n value: function getCells() {\n var stride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n\n var cells = [];\n for (var j = 0; j < this.nRows; j = j + stride) {\n for (var i = 0; i < this.nCols; i = i + stride) {\n var _lonLatAtIndexes2 = this._lonLatAtIndexes(i, j),\n _lonLatAtIndexes3 = _slicedToArray(_lonLatAtIndexes2, 2),\n lon = _lonLatAtIndexes3[0],\n lat = _lonLatAtIndexes3[1];\n\n var center = L.latLng(lat, lon);\n var value = this._valueAtIndexes(i, j);\n var c = new __WEBPACK_IMPORTED_MODULE_0__Cell__[\"a\" /* default */](center, value, this.cellXSize, this.cellYSize);\n cells.push(c); // <<\n }\n }\n return cells;\n }\n\n /**\n * Apply a filter function to field values\n * @param {Function} f - boolean function\n */\n\n }, {\n key: 'setFilter',\n value: function setFilter(f) {\n this._inFilter = f;\n this._updateRange();\n }\n\n /**\n * Apply a spatial mask to field values\n * @param {L.GeoJSON} m \n */\n\n }, {\n key: 'setSpatialMask',\n value: function setSpatialMask(m) {\n this._spatialMask = m;\n }\n\n /**\n * Grid extent\n * @returns {Number[]} [xmin, ymin, xmax, ymax]\n */\n\n }, {\n key: 'extent',\n value: function extent() {\n var _getWrappedLongitudes2 = this._getWrappedLongitudes(),\n _getWrappedLongitudes3 = _slicedToArray(_getWrappedLongitudes2, 2),\n xmin = _getWrappedLongitudes3[0],\n xmax = _getWrappedLongitudes3[1];\n\n return [xmin, this.yllCorner, xmax, this.yurCorner];\n }\n\n /**\n * [xmin, xmax] in [-180, 180] range\n */\n\n }, {\n key: '_getWrappedLongitudes',\n value: function _getWrappedLongitudes() {\n var xmin = this.xllCorner;\n var xmax = this.xurCorner;\n\n if (this.longitudeNeedsToBeWrapped) {\n if (this.isContinuous) {\n xmin = -180;\n xmax = 180;\n } else {\n // not sure about this (just one particular case, but others...?)\n xmax = this.xurCorner - 360;\n xmin = this.xllCorner - 360;\n /* eslint-disable no-console */\n // console.warn(`are these xmin: ${xmin} & xmax: ${xmax} OK?`);\n // TODO: Better throw an exception on no-controlled situations.\n /* eslint-enable no-console */\n }\n }\n return [xmin, xmax];\n }\n\n /**\n * Returns whether or not the grid contains the point, considering\n * the spatialMask if it has been previously set\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n\n }, {\n key: 'contains',\n value: function contains(lon, lat) {\n if (this._spatialMask) {\n return this._pointInMask(lon, lat);\n }\n return this._pointInExtent(lon, lat);\n }\n\n /**\n * Checks if coordinates are inside the Extent (considering wrapped longitudes if needed)\n * @param {Number} lon \n * @param {Number} lat \n */\n\n }, {\n key: '_pointInExtent',\n value: function _pointInExtent(lon, lat) {\n var _getWrappedLongitudes4 = this._getWrappedLongitudes(),\n _getWrappedLongitudes5 = _slicedToArray(_getWrappedLongitudes4, 2),\n xmin = _getWrappedLongitudes5[0],\n xmax = _getWrappedLongitudes5[1];\n\n var longitudeIn = lon >= xmin && lon <= xmax;\n var latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n return longitudeIn && latitudeIn;\n }\n\n /**\n * Check if coordinates are inside the spatialMask (Point in Polygon analysis)\n * @param {Number} lon \n * @param {Number} lat \n */\n\n }, {\n key: '_pointInMask',\n value: function _pointInMask(lon, lat) {\n var pt = {\n type: 'Feature',\n geometry: {\n type: 'Point',\n coordinates: [lon, lat] // geojson, lon-lat order !\n },\n properties: {}\n };\n var poly = this._spatialMask;\n return __WEBPACK_IMPORTED_MODULE_1__turf_inside___default()(pt, poly);\n }\n\n /**\n * Returns if the grid doesn't contain the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n\n }, {\n key: 'notContains',\n value: function notContains(lon, lat) {\n return !this.contains(lon, lat);\n }\n\n /**\n * Interpolated value at lon-lat coordinates (bilinear method)\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number} [u, v, magnitude]\n * \n * Source: https://github.com/cambecc/earth > product.js\n */\n\n }, {\n key: 'interpolatedValueAt',\n value: function interpolatedValueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n var _getDecimalIndexes2 = this._getDecimalIndexes(lon, lat),\n _getDecimalIndexes3 = _slicedToArray(_getDecimalIndexes2, 2),\n i = _getDecimalIndexes3[0],\n j = _getDecimalIndexes3[1];\n\n return this.interpolatedValueAtIndexes(i, j);\n }\n\n /**\n * Interpolated value at i-j indexes (bilinear method)\n * @param {Number} i\n * @param {Number} j\n * @returns {Vector|Number} [u, v, magnitude]\n *\n * Source: https://github.com/cambecc/earth > product.js\n */\n\n }, {\n key: 'interpolatedValueAtIndexes',\n value: function interpolatedValueAtIndexes(i, j) {\n // 1 2 After converting λ and φ to fractional grid indexes i and j, we find the\n // fi i ci four points 'G' that enclose point (i, j). These points are at the four\n // | =1.4 | corners specified by the floor and ceiling of i and j. For example, given\n // ---G--|---G--- fj 8 i = 1.4 and j = 8.3, the four surrounding grid points are (1, 8), (2, 8),\n // j ___|_ . | (1, 9) and (2, 9).\n // =8.3 | |\n // ---G------G--- cj 9 Note that for wrapped grids, the first column is duplicated as the last\n // | | column, so the index ci can be used without taking a modulo.\n\n var indexes = this._getFourSurroundingIndexes(i, j);\n\n var _indexes = _slicedToArray(indexes, 4),\n fi = _indexes[0],\n ci = _indexes[1],\n fj = _indexes[2],\n cj = _indexes[3];\n\n var values = this._getFourSurroundingValues(fi, ci, fj, cj);\n if (values) {\n var _values = _slicedToArray(values, 4),\n g00 = _values[0],\n g10 = _values[1],\n g01 = _values[2],\n g11 = _values[3];\n\n return this._doInterpolation(i - fi, j - fj, g00, g10, g01, g11);\n }\n return null;\n }\n\n /**\n * Get decimal indexes\n * @private\n * @param {Number} lon\n * @param {Number} lat\n * @returns {Array} [[Description]]\n */\n\n }, {\n key: '_getDecimalIndexes',\n value: function _getDecimalIndexes(lon, lat) {\n if (this.longitudeNeedsToBeWrapped && lon < this.xllCorner) {\n lon = lon + 360;\n }\n var i = (lon - this.xllCorner) / this.cellXSize;\n var j = (this.yurCorner - lat) / this.cellYSize;\n return [i, j];\n }\n\n /**\n * Get surrounding indexes (integer), clampling on borders\n * @private\n * @param {Number} i - decimal index\n * @param {Number} j - decimal index\n * @returns {Array} [fi, ci, fj, cj]\n */\n\n }, {\n key: '_getFourSurroundingIndexes',\n value: function _getFourSurroundingIndexes(i, j) {\n var fi = Math.floor(i);\n var ci = fi + 1;\n // duplicate colum to simplify interpolation logic (wrapped value)\n if (this.isContinuous && ci >= this.nCols) {\n ci = 0;\n }\n ci = this._clampColumnIndex(ci);\n\n var fj = this._clampRowIndex(Math.floor(j));\n var cj = this._clampRowIndex(fj + 1);\n\n return [fi, ci, fj, cj];\n }\n\n /**\n * Get four surrounding values or null if not available,\n * from 4 integer indexes\n * @private\n * @param {Number} fi\n * @param {Number} ci\n * @param {Number} fj\n * @param {Number} cj\n * @returns {Array} \n */\n\n }, {\n key: '_getFourSurroundingValues',\n value: function _getFourSurroundingValues(fi, ci, fj, cj) {\n var row;\n if (row = this.grid[fj]) {\n // upper row ^^\n var g00 = row[fi]; // << left\n var g10 = row[ci]; // right >>\n if (this._isValid(g00) && this._isValid(g10) && (row = this.grid[cj])) {\n // lower row vv\n var g01 = row[fi]; // << left\n var g11 = row[ci]; // right >>\n if (this._isValid(g01) && this._isValid(g11)) {\n return [g00, g10, g01, g11]; // 4 values found!\n }\n }\n }\n return null;\n }\n\n /**\n * Nearest value at lon-lat coordinates\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number}\n */\n\n }, {\n key: 'valueAt',\n value: function valueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n var _getDecimalIndexes4 = this._getDecimalIndexes(lon, lat),\n _getDecimalIndexes5 = _slicedToArray(_getDecimalIndexes4, 2),\n i = _getDecimalIndexes5[0],\n j = _getDecimalIndexes5[1];\n\n var ii = Math.floor(i);\n var jj = Math.floor(j);\n\n var ci = this._clampColumnIndex(ii);\n var cj = this._clampRowIndex(jj);\n\n var value = this._valueAtIndexes(ci, cj);\n if (this._inFilter) {\n if (!this._inFilter(value)) return null;\n }\n\n return value;\n }\n\n /**\n * Returns whether or not the field has a value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n\n }, {\n key: 'hasValueAt',\n value: function hasValueAt(lon, lat) {\n var value = this.valueAt(lon, lat);\n var hasValue = value !== null;\n\n var included = true;\n if (this._inFilter) {\n included = this._inFilter(value);\n }\n return hasValue && included;\n }\n\n /**\n * Returns if the grid has no value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n\n }, {\n key: 'notHasValueAt',\n value: function notHasValueAt(lon, lat) {\n return !this.hasValueAt(lon, lat);\n }\n\n /**\n * Gives a random position to 'o' inside the grid\n * @param {Object} [o] - an object (eg. a particle)\n * @returns {{x: Number, y: Number}} - object with x, y (lon, lat)\n */\n\n }, {\n key: 'randomPosition',\n value: function randomPosition() {\n var o = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};\n\n var i = Math.random() * this.nCols | 0;\n var j = Math.random() * this.nRows | 0;\n\n o.x = this._longitudeAtX(i);\n o.y = this._latitudeAtY(j);\n\n return o;\n }\n\n /**\n * Value for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Vector|Number}\n */\n\n }, {\n key: '_valueAtIndexes',\n value: function _valueAtIndexes(i, j) {\n return this.grid[j][i]; // <-- j,i !!\n }\n\n /**\n * Lon-Lat for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Number[]} [lon, lat]\n */\n\n }, {\n key: '_lonLatAtIndexes',\n value: function _lonLatAtIndexes(i, j) {\n var lon = this._longitudeAtX(i);\n var lat = this._latitudeAtY(j);\n\n return [lon, lat];\n }\n\n /**\n * Longitude for grid-index\n * @param {Number} i - column index (integer)\n * @returns {Number} longitude at the center of the cell\n */\n\n }, {\n key: '_longitudeAtX',\n value: function _longitudeAtX(i) {\n var halfXPixel = this.cellXSize / 2.0;\n var lon = this.xllCorner + halfXPixel + i * this.cellXSize;\n if (this.longitudeNeedsToBeWrapped) {\n lon = lon > 180 ? lon - 360 : lon;\n }\n return lon;\n }\n\n /**\n * Latitude for grid-index\n * @param {Number} j - row index (integer)\n * @returns {Number} latitude at the center of the cell\n */\n\n }, {\n key: '_latitudeAtY',\n value: function _latitudeAtY(j) {\n var halfYPixel = this.cellYSize / 2.0;\n return this.yurCorner - halfYPixel - j * this.cellYSize;\n }\n\n /**\n * Apply the interpolation\n * @abstract\n * @private\n */\n /* eslint-disable no-unused-vars */\n\n }, {\n key: '_doInterpolation',\n value: function _doInterpolation(x, y, g00, g10, g01, g11) {\n throw new TypeError('Must be overriden');\n }\n /* eslint-disable no-unused-vars */\n\n /**\n * Check the column index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} ii - index\n * @returns {Number} i - inside the allowed indexes\n */\n\n }, {\n key: '_clampColumnIndex',\n value: function _clampColumnIndex(ii) {\n var i = ii;\n if (ii < 0) {\n i = 0;\n }\n var maxCol = this.nCols - 1;\n if (ii > maxCol) {\n i = maxCol;\n }\n return i;\n }\n\n /**\n * Check the row index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} jj index\n * @returns {Number} j - inside the allowed indexes\n */\n\n }, {\n key: '_clampRowIndex',\n value: function _clampRowIndex(jj) {\n var j = jj;\n if (jj < 0) {\n j = 0;\n }\n var maxRow = this.nRows - 1;\n if (jj > maxRow) {\n j = maxRow;\n }\n return j;\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n\n }, {\n key: '_isValid',\n value: function _isValid(x) {\n return x !== null && x !== undefined;\n }\n }]);\n\n return Field;\n}();\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (Field);\n\n/***/ }),\n/* 2 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Field__ = __webpack_require__(1);\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n\n\n/**\n * Scalar Field\n */\n\nvar ScalarField = function (_Field) {\n _inherits(ScalarField, _Field);\n\n _createClass(ScalarField, null, [{\n key: 'fromASCIIGrid',\n\n /**\n * Creates a ScalarField from the content of an ASCIIGrid file\n * @param {String} asc\n * @returns {ScalarField}\n */\n value: function fromASCIIGrid(asc) {\n var scaleFactor = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;\n\n //console.time('ScalarField from ASC');\n\n var lines = asc.split('\\n');\n\n // Header\n ScalarField._checkIsValidASCIIGridHeader(lines);\n\n var n = /-?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/; // any number\n\n var cellSize = parseFloat(lines[4].match(n)); // right now, no different x-y size is allowed\n var p = {\n nCols: parseInt(lines[0].match(n)),\n nRows: parseInt(lines[1].match(n)),\n xllCorner: parseFloat(lines[2].match(n)),\n yllCorner: parseFloat(lines[3].match(n)),\n cellXSize: cellSize,\n cellYSize: cellSize\n };\n var noDataValue = lines[5].toUpperCase().replace('NODATA_VALUE', '').trim();\n\n // Data (left-right and top-down)\n var zs = []; // TODO Consider using TypedArray (& manage NO_DATA)\n for (var i = 6; i < lines.length; i++) {\n var line = lines[i].trim();\n if (line === '') break;\n\n var items = line.split(' ');\n items.forEach(function (it) {\n var v = it !== noDataValue ? parseFloat(it * scaleFactor) : null;\n zs.push(v);\n });\n }\n p.zs = zs;\n\n //console.timeEnd('ScalarField from ASC');\n return new ScalarField(p);\n }\n }, {\n key: '_checkIsValidASCIIGridHeader',\n value: function _checkIsValidASCIIGridHeader(lines) {\n var upperCasesLines = lines.map(function (lin) {\n return lin.toUpperCase();\n });\n\n var parameters = ['NCOLS', 'NROWS', 'XLLCORNER', 'YLLCORNER', 'CELLSIZE', 'NODATA_VALUE'];\n\n var i = 0;\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = parameters[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var expected = _step.value;\n\n var line = upperCasesLines[i];\n var found = line.indexOf(expected) != -1;\n if (!found) {\n throw 'Not valid ASCIIGrid: expected \\'' + expected + '\\' at line \\'' + line + '\\' [lin. n\\xBA ' + i + ']';\n }\n i++;\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n }\n\n /**\n * Creates a ScalarField from the content of a GeoTIFF file, as read by geotiff.js\n * @param {ArrayBuffer} data\n * @param {Number} bandIndex\n * @returns {ScalarField}\n */\n\n }, {\n key: 'fromGeoTIFF',\n value: function fromGeoTIFF(data) {\n var bandIndex = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;\n\n //console.time('ScalarField from GeoTIFF');\n\n var tiff = GeoTIFF.parse(data); // geotiff.js\n var image = tiff.getImage();\n var rasters = image.readRasters();\n var tiepoint = image.getTiePoints()[0];\n var fileDirectory = image.getFileDirectory();\n\n var _fileDirectory$ModelP = _slicedToArray(fileDirectory.ModelPixelScale, 2),\n xScale = _fileDirectory$ModelP[0],\n yScale = _fileDirectory$ModelP[1];\n\n var zs = rasters[bandIndex]; // left-right and top-down order\n\n if (fileDirectory.GDAL_NODATA) {\n var noData = parseFloat(fileDirectory.GDAL_NODATA);\n // console.log(noData);\n var simpleZS = Array.from(zs); // to simple array, so null is allowed | TODO efficiency??\n zs = simpleZS.map(function (z) {\n return z === noData ? null : z;\n });\n }\n\n var p = {\n nCols: image.getWidth(),\n nRows: image.getHeight(),\n xllCorner: tiepoint.x,\n yllCorner: tiepoint.y - image.getHeight() * yScale,\n cellXSize: xScale,\n cellYSize: yScale,\n zs: zs\n };\n\n //console.timeEnd('ScalarField from GeoTIFF');\n return new ScalarField(p);\n }\n }]);\n\n function ScalarField(params) {\n _classCallCheck(this, ScalarField);\n\n var _this = _possibleConstructorReturn(this, (ScalarField.__proto__ || Object.getPrototypeOf(ScalarField)).call(this, params));\n\n _this.zs = params['zs'];\n\n _this.grid = _this._buildGrid();\n _this._updateRange();\n //console.log(`ScalarField created (${this.nCols} x ${this.nRows})`);\n return _this;\n }\n\n /**\n * Builds a grid with a Number at each point, from an array\n * 'zs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @private\n * @returns {Array.>} - grid[row][column]--> Number\n */\n\n\n _createClass(ScalarField, [{\n key: '_buildGrid',\n value: function _buildGrid() {\n var grid = this._arrayTo2d(this.zs, this.nRows, this.nCols);\n return grid;\n }\n }, {\n key: '_arrayTo2d',\n value: function _arrayTo2d(array, nRows, nCols) {\n var grid = [];\n var p = 0;\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n var z = array[p];\n row[i] = this._isValid(z) ? z : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n }, {\n key: '_newDataArrays',\n value: function _newDataArrays(params) {\n params['zs'] = [];\n }\n }, {\n key: '_pushValueToArrays',\n value: function _pushValueToArrays(params, value) {\n params['zs'].push(value);\n }\n }, {\n key: '_makeNewFrom',\n value: function _makeNewFrom(params) {\n return new ScalarField(params);\n }\n\n /**\n * Calculate min & max values\n * @private\n * @returns {Array} - [min, max]\n */\n\n }, {\n key: '_calculateRange',\n value: function _calculateRange() {\n var data = this.zs;\n if (this._inFilter) {\n data = data.filter(this._inFilter);\n }\n return [d3.min(data), d3.max(data)];\n }\n\n /**\n * Bilinear interpolation for Number\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number} g00\n * @param {Number} g10\n * @param {Number} g01\n * @param {Number} g11\n * @returns {Number}\n */\n\n }, {\n key: '_doInterpolation',\n value: function _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n return g00 * rx * ry + g10 * x * ry + g01 * rx * y + g11 * x * y;\n }\n }]);\n\n return ScalarField;\n}(__WEBPACK_IMPORTED_MODULE_0__Field__[\"a\" /* default */]);\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (ScalarField);\n\n/***/ }),\n/* 3 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * 2D Vector\n */\nvar Vector = function () {\n function Vector(u, v) {\n _classCallCheck(this, Vector);\n\n this.u = u;\n this.v = v;\n }\n\n /**\n * Magnitude\n * @returns {Number}\n */\n\n\n _createClass(Vector, [{\n key: \"magnitude\",\n value: function magnitude() {\n return Math.sqrt(this.u * this.u + this.v * this.v);\n }\n\n /**\n * Angle in degrees (0 to 360º) --> Towards\n * N is 0º and E is 90º\n * @returns {Number}\n */\n\n }, {\n key: \"directionTo\",\n value: function directionTo() {\n var verticalAngle = Math.atan2(this.u, this.v);\n var inDegrees = verticalAngle * (180.0 / Math.PI);\n if (inDegrees < 0) {\n inDegrees = inDegrees + 360.0;\n }\n return inDegrees;\n }\n\n /**\n * Angle in degrees (0 to 360º) From x-->\n * N is 0º and E is 90º\n * @returns {Number}\n */\n\n }, {\n key: \"directionFrom\",\n value: function directionFrom() {\n var a = this.directionTo();\n var opposite = (a + 180.0) % 360.0;\n return opposite;\n }\n\n /*\n Degrees --> text\n new Dictionary\n {\n //{0, 23, 45, 68, 90, 113, 135, 158, 180, 203, 225, 248, 270, 293, 315, 338, 360};\n {0, 'N'},\n {23, 'NNE'},\n {45, 'NE'},\n {68, 'ENE'},\n {90, 'E'},\n {113, 'ESE'},\n {135, 'SE'},\n {158, 'SSE'},\n {180, 'S'},\n {203, 'SSW'},\n {225, 'SW'},\n {248, 'WSW'},\n {270, 'W'},\n {293, 'WNW'},\n {315, 'NW'},\n {338, 'NNW'},\n {360, 'N'}\n };\n */\n\n }]);\n\n return Vector;\n}();\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (Vector);\n\n/***/ }),\n/* 4 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Field__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__ScalarField__ = __webpack_require__(2);\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\n\n\n\n\n/**\n * A set of vectors assigned to a regular 2D-grid (lon-lat)\n * (e.g. a raster representing winds for a region)\n */\n\nvar VectorField = function (_Field) {\n _inherits(VectorField, _Field);\n\n _createClass(VectorField, null, [{\n key: 'fromASCIIGrids',\n\n /**\n * Creates a VectorField from the content of two ASCIIGrid files\n * @param {String} ascU - with u-component\n * @param {String} ascV - with v-component\n * @returns {VectorField}\n */\n value: function fromASCIIGrids(ascU, ascV) {\n var scaleFactor = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;\n\n var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromASCIIGrid(ascU, scaleFactor);\n var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromASCIIGrid(ascV, scaleFactor);\n var p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of two different Geotiff files\n * @param {ArrayBuffer} gtU - geotiff data with u-component (band 0)\n * @param {ArrayBuffer} gtV - geotiff data with v-component (band 0)\n * @returns {VectorField}\n */\n\n }, {\n key: 'fromGeoTIFFs',\n value: function fromGeoTIFFs(gtU, gtV) {\n var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromGeoTIFF(gtU);\n var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromGeoTIFF(gtV);\n var p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of Multiband Geotiff\n * @param {ArrayBuffer} geotiffData - multiband\n * @param {Array} bandIndexesForUV\n * @returns {VectorField}\n */\n\n }, {\n key: 'fromMultibandGeoTIFF',\n value: function fromMultibandGeoTIFF(geotiffData) {\n var bandIndexesForUV = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 1];\n\n var u = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromGeoTIFF(geotiffData, bandIndexesForUV[0]);\n var v = __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */].fromGeoTIFF(geotiffData, bandIndexesForUV[1]);\n var p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Build parameters for VectorField, from 2 ScalarFields.\n * No validation at all (nor interpolation) is applied, so u and v\n * must be 'compatible' from the source\n * @param {ScalarField} u\n * @param {ScalarField} v\n * @returns {Object} - parameters to build VectorField\n */\n\n }, {\n key: '_paramsFromScalarFields',\n value: function _paramsFromScalarFields(u, v) {\n // TODO check u & v compatibility (cellSize...)\n var p = {\n nCols: u.nCols,\n nRows: u.nRows,\n xllCorner: u.xllCorner,\n yllCorner: u.yllCorner,\n cellXSize: u.cellXSize,\n cellYSize: u.cellYSize,\n us: u.zs,\n vs: v.zs\n };\n return p;\n }\n }]);\n\n function VectorField(params) {\n _classCallCheck(this, VectorField);\n\n var _this = _possibleConstructorReturn(this, (VectorField.__proto__ || Object.getPrototypeOf(VectorField)).call(this, params));\n\n _this.us = params['us'];\n _this.vs = params['vs'];\n _this.grid = _this._buildGrid();\n _this.range = _this._calculateRange();\n return _this;\n }\n\n /**\n * Get a derived field, from a computation on \n * the VectorField\n * @param {String} type ['magnitude' | 'directionTo' | 'directionFrom']\n * @returns {ScalarField}\n */\n\n\n _createClass(VectorField, [{\n key: 'getScalarField',\n value: function getScalarField(type) {\n var f = this._getFunctionFor(type);\n var p = {\n nCols: this.params.nCols,\n nRows: this.params.nRows,\n xllCorner: this.params.xllCorner,\n yllCorner: this.params.yllCorner,\n cellXSize: this.params.cellXSize,\n cellYSize: this.params.cellYSize,\n zs: this._applyOnField(f)\n };\n return new __WEBPACK_IMPORTED_MODULE_2__ScalarField__[\"a\" /* default */](p);\n }\n }, {\n key: '_getFunctionFor',\n value: function _getFunctionFor(type) {\n return function (u, v) {\n var uv = new __WEBPACK_IMPORTED_MODULE_0__Vector__[\"a\" /* default */](u, v);\n return uv[type](); // magnitude, directionTo, directionFrom\n };\n }\n }, {\n key: '_applyOnField',\n value: function _applyOnField(func) {\n var zs = [];\n var n = this.numCells();\n for (var i = 0; i < n; i++) {\n var u = this.us[i];\n var v = this.vs[i];\n if (this._isValid(u) && this._isValid(v)) {\n zs.push(func(u, v));\n } else {\n zs.push(null);\n }\n }\n return zs;\n }\n\n /**\n * Builds a grid with a Vector at each point, from two arrays\n * 'us' and 'vs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @returns {Array.>} - grid[row][column]--> Vector\n */\n\n }, {\n key: '_buildGrid',\n value: function _buildGrid() {\n var grid = this._arraysTo2d(this.us, this.vs, this.nRows, this.nCols);\n return grid;\n }\n }, {\n key: '_arraysTo2d',\n value: function _arraysTo2d(us, vs, nRows, nCols) {\n var grid = [];\n var p = 0;\n\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n var u = us[p],\n v = vs[p];\n var valid = this._isValid(u) && this._isValid(v);\n row[i] = valid ? new __WEBPACK_IMPORTED_MODULE_0__Vector__[\"a\" /* default */](u, v) : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n }, {\n key: '_newDataArrays',\n value: function _newDataArrays(params) {\n params['us'] = [];\n params['vs'] = [];\n }\n }, {\n key: '_pushValueToArrays',\n value: function _pushValueToArrays(params, value) {\n //console.log(value);\n params['us'].push(value.u);\n params['vs'].push(value.v);\n }\n }, {\n key: '_makeNewFrom',\n value: function _makeNewFrom(params) {\n return new VectorField(params);\n }\n\n /**\n * Calculate min & max values (magnitude)\n * @private\n * @returns {Array}\n */\n\n }, {\n key: '_calculateRange',\n value: function _calculateRange() {\n // TODO make a clearer method for getting these vectors...\n var vectors = this.getCells().map(function (pt) {\n return pt.value;\n }).filter(function (v) {\n return v !== null;\n });\n\n if (this._inFilter) {\n vectors = vectors.filter(this._inFilter);\n }\n\n // TODO check memory crash with high num of vectors!\n var magnitudes = vectors.map(function (v) {\n return v.magnitude();\n });\n var min = d3.min(magnitudes);\n var max = d3.max(magnitudes);\n\n return [min, max];\n }\n\n /**\n * Bilinear interpolation for Vector\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number[]} g00\n * @param {Number[]} g10\n * @param {Number[]} g01\n * @param {Number[]} g11\n * @returns {Vector}\n */\n\n }, {\n key: '_doInterpolation',\n value: function _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n var a = rx * ry,\n b = x * ry,\n c = rx * y,\n d = x * y;\n var u = g00.u * a + g10.u * b + g01.u * c + g11.u * d;\n var v = g00.v * a + g10.v * b + g01.v * c + g11.v * d;\n return new __WEBPACK_IMPORTED_MODULE_0__Vector__[\"a\" /* default */](u, v);\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n\n }, {\n key: '_isValid',\n value: function _isValid(x) {\n return x !== null && x !== undefined;\n }\n }]);\n\n return VectorField;\n}(__WEBPACK_IMPORTED_MODULE_1__Field__[\"a\" /* default */]);\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (VectorField);\n\n/***/ }),\n/* 5 */\n/***/ (function(module, exports) {\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\n/**\n * Control for a simple legend with a colorbar\n * References:\n * - http://jsfiddle.net/ramnathv/g8stqcf6/\n * - http://jsfiddle.net/vis4/cYLZH/\n */\nL.Control.ColorBar = L.Control.extend({\n options: {\n position: 'bottomleft',\n width: 300, // for colorbar itself (control is wider)\n height: 15,\n margin: 15,\n background: '#fff',\n textColor: 'black',\n steps: 100,\n decimals: 2,\n units: 'uds', // ej: m/s\n title: 'Legend', // ej: Ocean Currents\n labels: [], // empty for no labels\n labelFontSize: 10,\n labelTextPosition: 'middle' // start | middle | end\n },\n\n initialize: function initialize(color, range, options) {\n this.color = color; // 'chromajs' scale function\n this.range = range; // [min, max]\n L.Util.setOptions(this, options);\n },\n\n onAdd: function onAdd(map) {\n this._map = map;\n var div = L.DomUtil.create('div', 'leaflet-control-colorBar leaflet-bar leaflet-control');\n div.style.padding = '10px';\n\n L.DomEvent.addListener(div, 'click', L.DomEvent.stopPropagation).addListener(div, 'click', L.DomEvent.preventDefault);\n div.style.backgroundColor = this.options.background;\n div.style.cursor = 'text';\n div.innerHTML = this.title() + this.palette();\n return div;\n },\n\n title: function title() {\n var d = document.createElement('div');\n d3.select(d).append('span').style('color', this.options.textColor).style('display', 'block').style('margin-bottom', '5px').attr('class', 'leaflet-control-colorBar-title').text(this.options.title);\n return d.innerHTML;\n },\n\n palette: function palette() {\n var d = document.createElement('div');\n var svg = this._createSvgIn(d);\n\n this._appendColorBarTo(svg);\n\n if (this.options.labels) {\n this._appendLabelsTo(svg);\n }\n\n return d.innerHTML;\n },\n\n _createSvgIn: function _createSvgIn(d) {\n var spaceForLabels = this.options.labels ? this.options.margin : 0;\n var svg = d3.select(d).append('svg').attr('width', this.options.width + this.options.margin * 2).attr('height', this.options.height + spaceForLabels);\n return svg;\n },\n\n _appendColorBarTo: function _appendColorBarTo(svg) {\n var _this = this;\n\n var colorPerValue = this._getColorPerValue();\n var w = this.options.width / colorPerValue.length;\n\n var groupBars = svg.append('g').attr('id', 'colorBar-buckets');\n var buckets = groupBars.selectAll('rect').data(colorPerValue).enter().append('rect');\n buckets.attr('x', function (d, i) {\n return i * w + _this.options.margin;\n }).attr('y', function () {\n return 0;\n }).attr('height', function () {\n return _this.options.height;\n } /*w * 4*/).attr('width', function () {\n return w;\n }).attr('stroke-width', 2).attr('stroke-linecap', 'butt').attr('stroke', function (d) {\n return d.color.hex();\n }).attr('fill', function (d) {\n return d.color.hex();\n });\n buckets.append('title').text(function (d) {\n return d.value.toFixed(_this.options.decimals) + ' ' + _this.options.units;\n });\n },\n\n _appendLabelsTo: function _appendLabelsTo(svg) {\n var _this2 = this;\n\n var positionPerLabelValue = this._getPositionPerLabelValue();\n //const w = this.options.width / colorPerValue.length;\n var groupLabels = svg.append('g').attr('id', 'colorBar-labels');\n var labels = groupLabels.selectAll('text').data(positionPerLabelValue).enter().append('text');\n labels.attr('x', function (d) {\n return d.position + _this2.options.margin;\n }).attr('y', this.options.height + this.options.margin).attr('font-size', this.options.labelFontSize + 'px').attr('text-anchor', this.options.labelTextPosition).attr('fill', this.options.textColor).attr('class', 'leaflet-control-colorBar-label').text(function (d) {\n return '' + d.value.toFixed(_this2.options.decimals);\n });\n },\n\n _getColorPerValue: function _getColorPerValue() {\n var _this3 = this;\n\n var _range = _slicedToArray(this.range, 2),\n min = _range[0],\n max = _range[1];\n\n var delta = (max - min) / this.options.steps;\n var data = d3.range(min, max + delta, delta);\n var colorPerValue = data.map(function (d) {\n return {\n value: d,\n color: _this3.color(d)\n };\n });\n return colorPerValue;\n },\n\n _getPositionPerLabelValue: function _getPositionPerLabelValue() {\n var xPositionFor = d3.scaleLinear().range([0, this.options.width]).domain(this.range);\n var data = this.options.labels;\n var positionPerLabel = data.map(function (d) {\n return {\n value: d,\n position: xPositionFor(d)\n };\n });\n return positionPerLabel;\n }\n});\n\nL.control.colorBar = function (color, range, options) {\n return new L.Control.ColorBar(color, range, options);\n};\n\n/***/ }),\n/* 6 */\n/***/ (function(module, exports) {\n\n/**\n * Abstract class for a Field layer on canvas, aka 'a Raster layer'\n * (ScalarField or a VectorField)\n */\nL.CanvasLayer.Field = L.CanvasLayer.extend({\n options: {\n mouseMoveCursor: {\n value: 'pointer',\n noValue: 'default'\n },\n opacity: 1,\n onClick: null,\n onMouseMove: null,\n inFilter: null\n },\n\n initialize: function initialize(field, options) {\n L.Util.setOptions(this, options);\n this._visible = true;\n if (field) {\n this.setData(field);\n }\n },\n\n getEvents: function getEvents() {\n var events = L.CanvasLayer.prototype.getEvents.call(this);\n events.zoomstart = this._hideCanvas.bind(this);\n events.zoomend = this._showCanvas.bind(this);\n return events;\n },\n\n onLayerDidMount: function onLayerDidMount() {\n this._enableIdentify();\n this._ensureCanvasAlignment();\n },\n\n show: function show() {\n this._visible = true;\n this._showCanvas();\n this._enableIdentify();\n },\n hide: function hide() {\n this._visible = false;\n this._hideCanvas();\n this._disableIdentify();\n },\n isVisible: function isVisible() {\n return this._visible;\n },\n _showCanvas: function _showCanvas() {\n if (this._canvas && this._visible) {\n this._canvas.style.visibility = 'visible';\n }\n },\n _hideCanvas: function _hideCanvas() {\n if (this._canvas) {\n this._canvas.style.visibility = 'hidden';\n }\n },\n _enableIdentify: function _enableIdentify() {\n this._map.on('click', this._onClick, this);\n this._map.on('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.on('click', this.options.onClick, this);\n this.options.onMouseMove && this.on('mousemove', this.options.onMouseMove, this);\n },\n _disableIdentify: function _disableIdentify() {\n this._map.off('click', this._onClick, this);\n this._map.off('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.off('click', this.options.onClick, this);\n this.options.onMouseMove && this.off('mousemove', this.options.onMouseMove, this);\n },\n _ensureCanvasAlignment: function _ensureCanvasAlignment() {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n },\n\n\n onLayerWillUnmount: function onLayerWillUnmount() {\n this._disableIdentify();\n },\n\n needRedraw: function needRedraw() {\n if (this._map && this._field) {\n L.CanvasLayer.prototype.needRedraw.call(this);\n }\n },\n\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function onDrawLayer(viewInfo) {\n throw new TypeError('Must be overriden');\n },\n /* eslint-enable no-unused-vars */\n\n setData: function setData(field) {\n this.options.inFilter && field.setFilter(this.options.inFilter);\n this._field = field;\n this.needRedraw();\n this.fire('load');\n },\n\n setFilter: function setFilter(f) {\n this.options.inFilter = f;\n this._field && this._field.setFilter(f);\n this.needRedraw();\n },\n\n setOpacity: function setOpacity(opacity) {\n this.options.opacity = opacity;\n\n if (this._canvas) {\n this._updateOpacity();\n }\n return this;\n },\n\n getBounds: function getBounds() {\n var bb = this._field.extent();\n\n var southWest = L.latLng(bb[1], bb[0]),\n northEast = L.latLng(bb[3], bb[2]);\n var bounds = L.latLngBounds(southWest, northEast);\n return bounds;\n },\n\n _onClick: function _onClick(e) {\n var v = this._queryValue(e);\n this.fire('click', v);\n },\n\n _onMouseMove: function _onMouseMove(e) {\n var v = this._queryValue(e);\n this._changeCursorOn(v);\n this.fire('mousemove', v);\n },\n\n _changeCursorOn: function _changeCursorOn(v) {\n if (!this.options.mouseMoveCursor) return;\n\n var _options$mouseMoveCur = this.options.mouseMoveCursor,\n value = _options$mouseMoveCur.value,\n noValue = _options$mouseMoveCur.noValue;\n\n var style = this._map.getContainer().style;\n style.cursor = v.value !== null ? value : noValue;\n },\n\n _updateOpacity: function _updateOpacity() {\n L.DomUtil.setOpacity(this._canvas, this.options.opacity);\n },\n\n _queryValue: function _queryValue(e) {\n var v = this._field ? this._field.valueAt(e.latlng.lng, e.latlng.lat) : null;\n var result = {\n latlng: e.latlng,\n value: v\n };\n return result;\n },\n\n _getDrawingContext: function _getDrawingContext() {\n var g = this._canvas.getContext('2d');\n g.clearRect(0, 0, this._canvas.width, this._canvas.height);\n return g;\n }\n});\n\n/***/ }),\n/* 7 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Cell__ = __webpack_require__(0);\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\n\n\n/**\n * ScalarField on canvas (a 'Raster')\n */\nL.CanvasLayer.ScalarField = L.CanvasLayer.Field.extend({\n options: {\n type: 'colormap', // [colormap|vector]\n color: null, // function colorFor(value) [e.g. chromajs.scale],\n interpolate: false, // Change to use interpolation\n vectorSize: 20, // only used if 'vector'\n arrowDirection: 'from' // [from|towards]\n },\n\n initialize: function initialize(scalarField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(this, scalarField, options);\n L.Util.setOptions(this, options);\n },\n\n _defaultColorScale: function _defaultColorScale() {\n return chroma.scale(['white', 'black']).domain(this._field.range);\n },\n\n setColor: function setColor(f) {\n this.options.color = f;\n this.needRedraw();\n },\n\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function onDrawLayer(viewInfo) {\n if (!this.isVisible()) return;\n this._updateOpacity();\n\n var r = this._getRendererMethod();\n //console.time('onDrawLayer');\n r();\n //console.timeEnd('onDrawLayer');\n },\n /* eslint-enable no-unused-vars */\n\n _getRendererMethod: function _getRendererMethod() {\n switch (this.options.type) {\n case 'colormap':\n return this._drawImage.bind(this);\n case 'vector':\n return this._drawArrows.bind(this);\n default:\n throw Error('Unkwown renderer type: ' + this.options.type);\n }\n },\n\n _ensureColor: function _ensureColor() {\n if (this.options.color === null) {\n this.setColor(this._defaultColorScale());\n }\n },\n\n _showCanvas: function _showCanvas() {\n L.CanvasLayer.Field.prototype._showCanvas.call(this);\n this.needRedraw(); // TODO check spurious redraw (e.g. hide/show without moving map)\n },\n\n\n /**\n * Draws the field in an ImageData and applying it with putImageData.\n * Used as a reference: http://geoexamples.com/d3-raster-tools-docs/code_samples/raster-pixels-page.html\n */\n _drawImage: function _drawImage() {\n this._ensureColor();\n\n var ctx = this._getDrawingContext();\n var width = this._canvas.width;\n var height = this._canvas.height;\n\n var img = ctx.createImageData(width, height);\n var data = img.data;\n\n this._prepareImageIn(data, width, height);\n ctx.putImageData(img, 0, 0);\n },\n\n /**\n * Prepares the image in data, as array with RGBAs\n * [R1, G1, B1, A1, R2, G2, B2, A2...]\n * @private\n * @param {[[Type]]} data [[Description]]\n * @param {Numver} width\n * @param {Number} height\n */\n _prepareImageIn: function _prepareImageIn(data, width, height) {\n var f = this.options.interpolate ? 'interpolatedValueAt' : 'valueAt';\n\n var pos = 0;\n for (var j = 0; j < height; j++) {\n for (var i = 0; i < width; i++) {\n var pointCoords = this._map.containerPointToLatLng([i, j]);\n var lon = pointCoords.lng;\n var lat = pointCoords.lat;\n\n var v = this._field[f](lon, lat); // 'valueAt' | 'interpolatedValueAt' || TODO check some 'artifacts'\n if (v !== null) {\n var color = this._getColorFor(v);\n\n var _color$rgba = color.rgba(),\n _color$rgba2 = _slicedToArray(_color$rgba, 4),\n R = _color$rgba2[0],\n G = _color$rgba2[1],\n B = _color$rgba2[2],\n A = _color$rgba2[3];\n\n data[pos] = R;\n data[pos + 1] = G;\n data[pos + 2] = B;\n data[pos + 3] = parseInt(A * 255); // not percent in alpha but hex 0-255\n }\n pos = pos + 4;\n }\n }\n },\n\n\n /**\n * Draws the field as a set of arrows. Direction from 0 to 360 is assumed.\n */\n _drawArrows: function _drawArrows() {\n var bounds = this._pixelBounds();\n var pixelSize = (bounds.max.x - bounds.min.x) / this._field.nCols;\n\n var stride = Math.max(1, Math.floor(1.2 * this.options.vectorSize / pixelSize));\n\n var ctx = this._getDrawingContext();\n ctx.strokeStyle = this.options.color;\n\n var currentBounds = this._map.getBounds();\n\n for (var y = 0; y < this._field.height; y = y + stride) {\n for (var x = 0; x < this._field.width; x = x + stride) {\n var _field$_lonLatAtIndex = this._field._lonLatAtIndexes(x, y),\n _field$_lonLatAtIndex2 = _slicedToArray(_field$_lonLatAtIndex, 2),\n lon = _field$_lonLatAtIndex2[0],\n lat = _field$_lonLatAtIndex2[1];\n\n var v = this._field.valueAt(lon, lat);\n var center = L.latLng(lat, lon);\n if (v !== null && currentBounds.contains(center)) {\n var cell = new __WEBPACK_IMPORTED_MODULE_0__Cell__[\"a\" /* default */](center, v, this.cellXSize, this.cellYSize);\n this._drawArrow(cell, ctx);\n }\n }\n }\n },\n\n _pixelBounds: function _pixelBounds() {\n var bounds = this.getBounds();\n var northWest = this._map.latLngToContainerPoint(bounds.getNorthWest());\n var southEast = this._map.latLngToContainerPoint(bounds.getSouthEast());\n var pixelBounds = L.bounds(northWest, southEast);\n return pixelBounds;\n },\n\n _drawArrow: function _drawArrow(cell, ctx) {\n var projected = this._map.latLngToContainerPoint(cell.center);\n\n // colormap vs. simple color\n var color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(cell.value);\n }\n\n var size = this.options.vectorSize;\n ctx.save();\n\n ctx.translate(projected.x, projected.y);\n\n var rotationRads = (90 + cell.value) * Math.PI / 180; // from, by default\n if (this.options.arrowDirection === 'towards') {\n rotationRads = rotationRads + Math.PI;\n }\n ctx.rotate(rotationRads);\n\n ctx.beginPath();\n ctx.moveTo(-size / 2, 0);\n ctx.lineTo(+size / 2, 0);\n ctx.moveTo(size * 0.25, -size * 0.25);\n ctx.lineTo(+size / 2, 0);\n ctx.lineTo(size * 0.25, size * 0.25);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Gets a chroma color for a pixel value, according to 'options.color'\n */\n _getColorFor: function _getColorFor(v) {\n var c = this.options.color; // e.g. for a constant 'red'\n if (typeof c === 'function') {\n c = this.options.color(v);\n }\n var color = chroma(c); // to be more flexible, a chroma color object is always created || TODO improve efficiency\n return color;\n }\n});\n\nL.canvasLayer.scalarField = function (scalarField, options) {\n return new L.CanvasLayer.ScalarField(scalarField, options);\n};\n\n/***/ }),\n/* 8 */\n/***/ (function(module, exports) {\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\n/**\n * Simple layer with lon-lat points\n *\n * TODO rename to SimplePoint?\n */\nL.CanvasLayer.SimpleLonLat = L.CanvasLayer.extend({\n options: {\n color: 'gray'\n },\n\n initialize: function initialize(points, options) {\n this.points = points;\n L.Util.setOptions(this, options);\n },\n\n onLayerDidMount: function onLayerDidMount() {\n // -- prepare custom drawing\n },\n\n onLayerWillUnmount: function onLayerWillUnmount() {\n // -- custom cleanup\n },\n\n /* eslint-disable no-unused-vars */\n setData: function setData(data) {\n // -- custom data set\n this.needRedraw(); // -- call to drawLayer\n },\n /* eslint-enable no-unused-vars */\n\n onDrawLayer: function onDrawLayer(viewInfo) {\n // canvas preparation\n var g = viewInfo.canvas.getContext('2d');\n g.clearRect(0, 0, viewInfo.canvas.width, viewInfo.canvas.height);\n g.fillStyle = this.options.color;\n\n var _iteratorNormalCompletion = true;\n var _didIteratorError = false;\n var _iteratorError = undefined;\n\n try {\n for (var _iterator = this.points[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {\n var point = _step.value;\n\n var p = viewInfo.layer._map.latLngToContainerPoint(point);\n g.beginPath();\n //g.arc(p.x, p.y, 1, 0, Math.PI * 2); // circle | TODO style 'function' as parameter?\n g.fillRect(p.x, p.y, 2, 2); //simple point\n g.fill();\n g.closePath();\n g.stroke();\n }\n } catch (err) {\n _didIteratorError = true;\n _iteratorError = err;\n } finally {\n try {\n if (!_iteratorNormalCompletion && _iterator.return) {\n _iterator.return();\n }\n } finally {\n if (_didIteratorError) {\n throw _iteratorError;\n }\n }\n }\n },\n\n getBounds: function getBounds() {\n // TODO: bounding with points...\n var xs = this.points.map(function (pt) {\n return pt.lng;\n });\n var ys = this.points.map(function (pt) {\n return pt.lat;\n });\n\n var xmin = Math.min.apply(Math, _toConsumableArray(xs));\n var ymin = Math.min.apply(Math, _toConsumableArray(ys));\n var xmax = Math.max.apply(Math, _toConsumableArray(xs));\n var ymax = Math.max.apply(Math, _toConsumableArray(ys));\n\n var southWest = L.latLng(ymin, xmin),\n northEast = L.latLng(ymax, xmax);\n var bounds = L.latLngBounds(southWest, northEast); // TODO FIX ERROR ? half-pixel?\n return bounds;\n }\n});\n\nL.canvasLayer.simpleLonLat = function (lonslats, options) {\n return new L.CanvasLayer.SimpleLonLat(lonslats, options);\n};\n\n/***/ }),\n/* 9 */\n/***/ (function(module, exports) {\n\n/**\n * Animated VectorField on canvas\n */\nL.CanvasLayer.VectorFieldAnim = L.CanvasLayer.Field.extend({\n options: {\n paths: 800,\n color: 'white', // html-color | function colorFor(value) [e.g. chromajs.scale]\n width: 1.0, // number | function widthFor(value)\n fade: 0.96, // 0 to 1\n duration: 20, // milliseconds per 'frame'\n maxAge: 200, // number of maximum frames per path\n velocityScale: 1 / 5000\n },\n\n initialize: function initialize(vectorField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(this, vectorField, options);\n L.Util.setOptions(this, options);\n\n this.timer = null;\n },\n\n onLayerDidMount: function onLayerDidMount() {\n L.CanvasLayer.Field.prototype.onLayerDidMount.call(this);\n this._map.on('move resize', this._stopAnimation, this);\n },\n\n onLayerWillUnmount: function onLayerWillUnmount() {\n L.CanvasLayer.Field.prototype.onLayerWillUnmount.call(this);\n this._map.off('move resize', this._stopAnimation, this);\n this._stopAnimation();\n },\n\n _hideCanvas: function _showCanvas() {\n L.CanvasLayer.Field.prototype._hideCanvas.call(this);\n this._stopAnimation();\n },\n\n onDrawLayer: function onDrawLayer(viewInfo) {\n if (!this._field || !this.isVisible()) return;\n\n this._updateOpacity();\n\n var ctx = this._getDrawingContext();\n var paths = this._prepareParticlePaths();\n\n this.timer = d3.timer(function () {\n _moveParticles();\n _drawParticles();\n }, this.options.duration);\n\n var self = this;\n\n /**\n * Builds the paths, adding 'particles' on each animation step, considering\n * their properties (age / position source > target)\n */\n function _moveParticles() {\n // let screenFactor = 1 / self._map.getZoom(); // consider using a 'screenFactor' to ponderate velocityScale\n paths.forEach(function (par) {\n if (par.age > self.options.maxAge) {\n // restart, on a random x,y\n par.age = 0;\n self._field.randomPosition(par);\n }\n\n var vector = self._field.valueAt(par.x, par.y);\n if (vector === null) {\n par.age = self.options.maxAge;\n } else {\n // the next point will be...\n var xt = par.x + vector.u * self.options.velocityScale; //* screenFactor;\n var yt = par.y + vector.v * self.options.velocityScale; //* screenFactor;\n\n if (self._field.hasValueAt(xt, yt)) {\n par.xt = xt;\n par.yt = yt;\n par.m = vector.magnitude();\n } else {\n // not visible anymore...\n par.age = self.options.maxAge;\n }\n }\n par.age += 1;\n });\n }\n\n /**\n * Draws the paths on each step\n */\n function _drawParticles() {\n // Previous paths...\n var prev = ctx.globalCompositeOperation;\n ctx.globalCompositeOperation = 'destination-in';\n ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n //ctx.globalCompositeOperation = 'source-over';\n ctx.globalCompositeOperation = prev;\n\n // fading paths...\n ctx.fillStyle = 'rgba(0, 0, 0, ' + self.options.fade + ')';\n ctx.lineWidth = self.options.width;\n ctx.strokeStyle = self.options.color;\n\n // New paths\n paths.forEach(function (par) {\n self._drawParticle(viewInfo, ctx, par);\n });\n }\n },\n\n _drawParticle: function _drawParticle(viewInfo, ctx, par) {\n var source = new L.latLng(par.y, par.x);\n var target = new L.latLng(par.yt, par.xt);\n\n if (viewInfo.bounds.contains(source) && par.age <= this.options.maxAge) {\n var pA = viewInfo.layer._map.latLngToContainerPoint(source);\n var pB = viewInfo.layer._map.latLngToContainerPoint(target);\n\n ctx.beginPath();\n ctx.moveTo(pA.x, pA.y);\n ctx.lineTo(pB.x, pB.y);\n\n // next-step movement\n par.x = par.xt;\n par.y = par.yt;\n\n // colormap vs. simple color\n var color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(par.m);\n }\n\n var width = this.options.width;\n if (typeof width === 'function') {\n ctx.lineWidth = width(par.m);\n }\n\n ctx.stroke();\n }\n },\n\n\n _prepareParticlePaths: function _prepareParticlePaths() {\n var paths = [];\n\n for (var i = 0; i < this.options.paths; i++) {\n var p = this._field.randomPosition();\n p.age = this._randomAge();\n paths.push(p);\n }\n return paths;\n },\n\n _randomAge: function _randomAge() {\n return Math.floor(Math.random() * this.options.maxAge);\n },\n\n _stopAnimation: function _stopAnimation() {\n if (this.timer) {\n this.timer.stop();\n }\n }\n});\n\nL.canvasLayer.vectorFieldAnim = function (vectorField, options) {\n return new L.CanvasLayer.VectorFieldAnim(vectorField, options);\n};\n\n/***/ }),\n/* 10 */\n/***/ (function(module, exports) {\n\n/*\n 1.0.1 (downloaded from https://github.com/Sumbera/gLayers.Leaflet/releases/tag/v1.0.1)\n\n Generic Canvas Layer for leaflet 0.7 and 1.0-rc,\n copyright Stanislav Sumbera, 2016 , sumbera.com , license MIT\n originally created and motivated by L.CanvasOverlay available here: https://gist.github.com/Sumbera/11114288\n*/\n\nL.CanvasLayer = L.Layer.extend({\n // -- initialized is called on prototype\n initialize: function initialize(options) {\n this._map = null;\n this._canvas = null;\n this._frame = null;\n this._delegate = null;\n L.setOptions(this, options);\n },\n\n delegate: function delegate(del) {\n this._delegate = del;\n return this;\n },\n\n needRedraw: function needRedraw() {\n if (!this._frame) {\n this._frame = L.Util.requestAnimFrame(this.drawLayer, this);\n }\n return this;\n },\n\n //-------------------------------------------------------------\n _onLayerDidResize: function _onLayerDidResize(resizeEvent) {\n this._canvas.width = resizeEvent.newSize.x;\n this._canvas.height = resizeEvent.newSize.y;\n },\n //-------------------------------------------------------------\n _onLayerDidMove: function _onLayerDidMove() {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n this.drawLayer();\n },\n //-------------------------------------------------------------\n getEvents: function getEvents() {\n var events = {\n resize: this._onLayerDidResize,\n moveend: this._onLayerDidMove\n };\n if (this._map.options.zoomAnimation && L.Browser.any3d) {\n events.zoomanim = this._animateZoom;\n }\n\n return events;\n },\n //-------------------------------------------------------------\n onAdd: function onAdd(map) {\n this._map = map;\n this._canvas = L.DomUtil.create('canvas', 'leaflet-layer');\n this.tiles = {};\n\n var size = this._map.getSize();\n this._canvas.width = size.x;\n this._canvas.height = size.y;\n\n var animated = this._map.options.zoomAnimation && L.Browser.any3d;\n L.DomUtil.addClass(this._canvas, 'leaflet-zoom-' + (animated ? 'animated' : 'hide'));\n\n map._panes.overlayPane.appendChild(this._canvas);\n\n map.on(this.getEvents(), this);\n\n var del = this._delegate || this;\n del.onLayerDidMount && del.onLayerDidMount(); // -- callback\n\n this.needRedraw();\n },\n\n //-------------------------------------------------------------\n onRemove: function onRemove(map) {\n var del = this._delegate || this;\n del.onLayerWillUnmount && del.onLayerWillUnmount(); // -- callback\n\n\n map.getPanes().overlayPane.removeChild(this._canvas);\n\n map.off(this.getEvents(), this);\n\n this._canvas = null;\n },\n\n //------------------------------------------------------------\n addTo: function addTo(map) {\n map.addLayer(this);\n return this;\n },\n // --------------------------------------------------------------------------------\n LatLonToMercator: function LatLonToMercator(latlon) {\n return {\n x: latlon.lng * 6378137 * Math.PI / 180,\n y: Math.log(Math.tan((90 + latlon.lat) * Math.PI / 360)) * 6378137\n };\n },\n\n //------------------------------------------------------------------------------\n drawLayer: function drawLayer() {\n // -- todo make the viewInfo properties flat objects.\n var size = this._map.getSize();\n var bounds = this._map.getBounds();\n var zoom = this._map.getZoom();\n\n var center = this.LatLonToMercator(this._map.getCenter());\n var corner = this.LatLonToMercator(this._map.containerPointToLatLng(this._map.getSize()));\n\n var del = this._delegate || this;\n del.onDrawLayer && del.onDrawLayer({\n layer: this,\n canvas: this._canvas,\n bounds: bounds,\n size: size,\n zoom: zoom,\n center: center,\n corner: corner\n });\n this._frame = null;\n },\n\n //------------------------------------------------------------------------------\n _animateZoom: function _animateZoom(e) {\n var scale = this._map.getZoomScale(e.zoom);\n var offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), e.zoom, e.center);\n\n L.DomUtil.setTransform(this._canvas, offset, scale);\n }\n});\n\nL.canvasLayer = function () {\n return new L.CanvasLayer();\n};\n\n/***/ }),\n/* 11 */\n/***/ (function(module, exports, __webpack_require__) {\n\nvar invariant = __webpack_require__(12);\nvar getCoord = invariant.getCoord;\nvar getCoords = invariant.getCoords;\n\n// http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule\n// modified from: https://github.com/substack/point-in-polygon/blob/master/index.js\n// which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n\n/**\n * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can\n * be convex or concave. The function accounts for holes.\n *\n * @name inside\n * @param {Feature} point input point\n * @param {Feature} polygon input polygon or multipolygon\n * @param {boolean} [ignoreBoundary=false] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false.\n * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon\n * @example\n * var pt = turf.point([-77, 44]);\n * var poly = turf.polygon([[\n * [-81, 41],\n * [-81, 47],\n * [-72, 47],\n * [-72, 41],\n * [-81, 41]\n * ]]);\n *\n * turf.inside(pt, poly);\n * //= true\n */\nmodule.exports = function (point, polygon, ignoreBoundary) {\n // validation\n if (!point) throw new Error('point is required');\n if (!polygon) throw new Error('polygon is required');\n\n var pt = getCoord(point);\n var polys = getCoords(polygon);\n var type = (polygon.geometry) ? polygon.geometry.type : polygon.type;\n var bbox = polygon.bbox;\n\n // Quick elimination if point is not inside bbox\n if (bbox && inBBox(pt, bbox) === false) return false;\n\n // normalize to multipolygon\n if (type === 'Polygon') polys = [polys];\n\n for (var i = 0, insidePoly = false; i < polys.length && !insidePoly; i++) {\n // check if it is in the outer ring first\n if (inRing(pt, polys[i][0], ignoreBoundary)) {\n var inHole = false;\n var k = 1;\n // check for the point in any of the holes\n while (k < polys[i].length && !inHole) {\n if (inRing(pt, polys[i][k], !ignoreBoundary)) {\n inHole = true;\n }\n k++;\n }\n if (!inHole) insidePoly = true;\n }\n }\n return insidePoly;\n};\n\n/**\n * inRing\n *\n * @private\n * @param {[number, number]} pt [x,y]\n * @param {Array<[number, number]>} ring [[x,y], [x,y],..]\n * @param {boolean} ignoreBoundary ignoreBoundary\n * @returns {boolean} inRing\n */\nfunction inRing(pt, ring, ignoreBoundary) {\n var isInside = false;\n if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1);\n\n for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n var xi = ring[i][0], yi = ring[i][1];\n var xj = ring[j][0], yj = ring[j][1];\n var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) &&\n ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0);\n if (onBoundary) return !ignoreBoundary;\n var intersect = ((yi > pt[1]) !== (yj > pt[1])) &&\n (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi);\n if (intersect) isInside = !isInside;\n }\n return isInside;\n}\n\n/**\n * inBBox\n *\n * @private\n * @param {[number, number]} pt point [x,y]\n * @param {[number, number, number, number]} bbox BBox [west, south, east, north]\n * @returns {boolean} true/false if point is inside BBox\n */\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] &&\n bbox[1] <= pt[1] &&\n bbox[2] >= pt[0] &&\n bbox[3] >= pt[1];\n}\n\n\n/***/ }),\n/* 12 */\n/***/ (function(module, exports) {\n\n/**\n * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.\n *\n * @name getCoord\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var pt = turf.point([10, 10]);\n *\n * var coord = turf.getCoord(pt);\n * //= [10, 10]\n */\nfunction getCoord(obj) {\n if (!obj) throw new Error('obj is required');\n\n var coordinates = getCoords(obj);\n\n // getCoord() must contain at least two numbers (Point)\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return coordinates;\n } else {\n throw new Error('Coordinate is not a valid Point');\n }\n}\n\n/**\n * Unwrap coordinates from a Feature, Geometry Object or an Array of numbers\n *\n * @name getCoords\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]);\n *\n * var coord = turf.getCoords(poly);\n * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]\n */\nfunction getCoords(obj) {\n if (!obj) throw new Error('obj is required');\n var coordinates;\n\n // Array of numbers\n if (obj.length) {\n coordinates = obj;\n\n // Geometry Object\n } else if (obj.coordinates) {\n coordinates = obj.coordinates;\n\n // Feature\n } else if (obj.geometry && obj.geometry.coordinates) {\n coordinates = obj.geometry.coordinates;\n }\n // Checks if coordinates contains a number\n if (coordinates) {\n containsNumber(coordinates);\n return coordinates;\n }\n throw new Error('No valid coordinates');\n}\n\n/**\n * Checks if coordinates contains a number\n *\n * @name containsNumber\n * @param {Array} coordinates GeoJSON Coordinates\n * @returns {boolean} true if Array contains a number\n */\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return true;\n }\n\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error('coordinates must only contain numbers');\n}\n\n/**\n * Enforce expectations about types of GeoJSON objects for Turf.\n *\n * @name geojsonType\n * @param {GeoJSON} value any GeoJSON object\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction geojsonType(value, type, name) {\n if (!type || !name) throw new Error('type and name required');\n\n if (!value || value.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + value.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link Feature} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name featureOf\n * @param {Feature} feature a feature with an expected geometry type\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} error if value is not the expected type.\n */\nfunction featureOf(feature, type, name) {\n if (!feature) throw new Error('No feature passed');\n if (!name) throw new Error('.featureOf() requires a name');\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link FeatureCollection} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name collectionOf\n * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) throw new Error('No featureCollection passed');\n if (!name) throw new Error('.collectionOf() requires a name');\n if (!featureCollection || featureCollection.type !== 'FeatureCollection') {\n throw new Error('Invalid input to ' + name + ', FeatureCollection required');\n }\n for (var i = 0; i < featureCollection.features.length; i++) {\n var feature = featureCollection.features[i];\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n }\n}\n\n/**\n * Get Geometry from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {Geometry|null} GeoJSON Geometry Object\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeom(point)\n * //={\"type\": \"Point\", \"coordinates\": [110, 40]}\n */\nfunction getGeom(geojson) {\n if (!geojson) throw new Error('geojson is required');\n if (geojson.geometry !== undefined) return geojson.geometry;\n if (geojson.coordinates || geojson.geometries) return geojson;\n throw new Error('geojson must be a valid Feature or Geometry Object');\n}\n\n/**\n * Get Geometry Type from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {string} GeoJSON Geometry Type\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeomType(point)\n * //=\"Point\"\n */\nfunction getGeomType(geojson) {\n if (!geojson) throw new Error('geojson is required');\n var geom = getGeom(geojson);\n if (geom) return geom.type;\n}\n\nmodule.exports = {\n geojsonType: geojsonType,\n collectionOf: collectionOf,\n featureOf: featureOf,\n getCoord: getCoord,\n getCoords: getCoords,\n containsNumber: containsNumber,\n getGeom: getGeom,\n getGeomType: getGeomType\n};\n\n\n/***/ }),\n/* 13 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0__Vector_js__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__Cell_js__ = __webpack_require__(0);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__Field_js__ = __webpack_require__(1);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__ScalarField_js__ = __webpack_require__(2);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_4__VectorField_js__ = __webpack_require__(4);\n// base\n\nwindow.L.Vector = __WEBPACK_IMPORTED_MODULE_0__Vector_js__[\"a\" /* default */];\n\n\nwindow.L.Cell = __WEBPACK_IMPORTED_MODULE_1__Cell_js__[\"a\" /* default */];\n\n\nwindow.L.Field = __WEBPACK_IMPORTED_MODULE_2__Field_js__[\"a\" /* default */];\n\n\nwindow.L.ScalarField = __WEBPACK_IMPORTED_MODULE_3__ScalarField_js__[\"a\" /* default */];\n\n\nwindow.L.VectorField = __WEBPACK_IMPORTED_MODULE_4__VectorField_js__[\"a\" /* default */];\n\n// layer\n__webpack_require__(10);\n__webpack_require__(8);\n__webpack_require__(6);\n__webpack_require__(7);\n__webpack_require__(9);\n\n// control\n__webpack_require__(5);\n\n/* eslint-disable no-console */\nconsole.log('leaflet.canvaslayer.field v1.4.0');\n/* eslint-enable no-console */\n\n/***/ })\n/******/ ]);\n\n\n// WEBPACK FOOTER //\n// leaflet.canvaslayer.field.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 13);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 82891af380a66293e679","/**\n * Simple regular cell in a raster\n */\nexport default class Cell {\n /**\n * A simple cell with a numerical value\n * @param {L.LatLng} center\n * @param {Number|Vector} value\n * @param {Number} xSize\n * @param {Number} ySize\n */\n constructor(center, value, xSize, ySize = xSize) {\n this.center = center;\n this.value = value;\n this.xSize = xSize;\n this.ySize = ySize;\n }\n\n equals(anotherCell) {\n return (\n this.center.equals(anotherCell.center) &&\n this._equalValues(this.value, anotherCell.value) &&\n this.xSize === anotherCell.xSize &&\n this.ySize === anotherCell.ySize\n );\n }\n\n _equalValues(value, anotherValue) {\n let type = value.constructor.name;\n let answerFor = {\n Number: value === anotherValue,\n Vector: value.u === anotherValue.u && value.v === anotherValue.v\n };\n return answerFor[type];\n }\n\n /**\n * Bounds for the cell\n * @returns {LatLngBounds}\n */\n getBounds() {\n let halfX = this.xSize / 2.0;\n let halfY = this.ySize / 2.0;\n let cLat = this.center.lat;\n let cLng = this.center.lng;\n let ul = L.latLng([cLat + halfY, cLng - halfX]);\n let lr = L.latLng([cLat - halfY, cLng + halfX]);\n\n return L.latLngBounds(\n L.latLng(lr.lat, ul.lng),\n L.latLng(ul.lat, lr.lng)\n );\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./Cell.js","import Cell from './Cell';\nimport inside from '@turf/inside';\n\n/**\n * Abstract class for a set of values (Vector | Scalar)\n * assigned to a regular 2D-grid (lon-lat), aka 'a Raster source'\n */\nexport default class Field {\n constructor(params) {\n this.params = params;\n\n this.nCols = params['nCols'];\n this.nRows = params['nRows'];\n\n // alias\n this.width = params['nCols'];\n this.height = params['nRows'];\n\n // ll = lower-left\n this.xllCorner = params['xllCorner'];\n this.yllCorner = params['yllCorner'];\n\n // ur = upper-right\n this.xurCorner =\n params['xllCorner'] + params['nCols'] * params['cellXSize'];\n this.yurCorner =\n params['yllCorner'] + params['nRows'] * params['cellYSize'];\n\n this.cellXSize = params['cellXSize'];\n this.cellYSize = params['cellYSize'];\n\n this.grid = null; // to be defined by subclasses\n this.isContinuous = this.xurCorner - this.xllCorner >= 360;\n this.longitudeNeedsToBeWrapped = this.xurCorner > 180; // [0, 360] --> [-180, 180]\n\n this._inFilter = null;\n this._spatialMask = null;\n }\n\n /**\n * Builds a grid with a value at each point (either Vector or Number)\n * Original params must include the required input values, following\n * x-ascending & y-descending order (same as in ASCIIGrid)\n * @abstract\n * @private\n * @returns {Array.>} - grid[row][column]--> Vector|Number\n */\n _buildGrid() {\n throw new TypeError('Must be overriden');\n }\n\n _updateRange() {\n this.range = this._calculateRange();\n }\n\n /**\n * Number of cells in the grid (rows * cols)\n * @returns {Number}\n */\n numCells() {\n return this.nRows * this.nCols;\n }\n\n /**\n * A list with every cell\n * @returns {Array} - cells (x-ascending & y-descending order)\n */\n getCells(stride = 1) {\n let cells = [];\n for (let j = 0; j < this.nRows; j = j + stride) {\n for (let i = 0; i < this.nCols; i = i + stride) {\n let [lon, lat] = this._lonLatAtIndexes(i, j);\n let center = L.latLng(lat, lon);\n let value = this._valueAtIndexes(i, j);\n let c = new Cell(center, value, this.cellXSize, this.cellYSize);\n cells.push(c); // <<\n }\n }\n return cells;\n }\n\n /**\n * Apply a filter function to field values\n * @param {Function} f - boolean function\n */\n setFilter(f) {\n this._inFilter = f;\n this._updateRange();\n }\n\n /**\n * Apply a spatial mask to field values\n * @param {L.GeoJSON} m \n */\n setSpatialMask(m) {\n this._spatialMask = m;\n }\n\n /**\n * Grid extent\n * @returns {Number[]} [xmin, ymin, xmax, ymax]\n */\n extent() {\n let [xmin, xmax] = this._getWrappedLongitudes();\n return [xmin, this.yllCorner, xmax, this.yurCorner];\n }\n\n /**\n * [xmin, xmax] in [-180, 180] range\n */\n _getWrappedLongitudes() {\n let xmin = this.xllCorner;\n let xmax = this.xurCorner;\n\n if (this.longitudeNeedsToBeWrapped) {\n if (this.isContinuous) {\n xmin = -180;\n xmax = 180;\n } else {\n // not sure about this (just one particular case, but others...?)\n xmax = this.xurCorner - 360;\n xmin = this.xllCorner - 360;\n /* eslint-disable no-console */\n // console.warn(`are these xmin: ${xmin} & xmax: ${xmax} OK?`);\n // TODO: Better throw an exception on no-controlled situations.\n /* eslint-enable no-console */\n }\n }\n return [xmin, xmax];\n }\n\n /**\n * Returns whether or not the grid contains the point, considering\n * the spatialMask if it has been previously set\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n contains(lon, lat) {\n if (this._spatialMask) {\n return this._pointInMask(lon, lat);\n }\n return this._pointInExtent(lon, lat);\n }\n\n /**\n * Checks if coordinates are inside the Extent (considering wrapped longitudes if needed)\n * @param {Number} lon \n * @param {Number} lat \n */\n _pointInExtent(lon, lat) {\n let [xmin, xmax] = this._getWrappedLongitudes();\n let longitudeIn = lon >= xmin && lon <= xmax;\n let latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n return longitudeIn && latitudeIn;\n }\n\n /**\n * Check if coordinates are inside the spatialMask (Point in Polygon analysis)\n * @param {Number} lon \n * @param {Number} lat \n */\n _pointInMask(lon, lat) {\n const pt = {\n type: 'Feature',\n geometry: {\n type: 'Point',\n coordinates: [lon, lat] // geojson, lon-lat order !\n },\n properties: {}\n };\n const poly = this._spatialMask;\n return inside(pt, poly);\n }\n\n /**\n * Returns if the grid doesn't contain the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n notContains(lon, lat) {\n return !this.contains(lon, lat);\n }\n\n /**\n * Interpolated value at lon-lat coordinates (bilinear method)\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number} [u, v, magnitude]\n * \n * Source: https://github.com/cambecc/earth > product.js\n */\n interpolatedValueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n let [i, j] = this._getDecimalIndexes(lon, lat);\n return this.interpolatedValueAtIndexes(i, j);\n }\n\n /**\n * Interpolated value at i-j indexes (bilinear method)\n * @param {Number} i\n * @param {Number} j\n * @returns {Vector|Number} [u, v, magnitude]\n *\n * Source: https://github.com/cambecc/earth > product.js\n */\n interpolatedValueAtIndexes(i, j) {\n // 1 2 After converting λ and φ to fractional grid indexes i and j, we find the\n // fi i ci four points 'G' that enclose point (i, j). These points are at the four\n // | =1.4 | corners specified by the floor and ceiling of i and j. For example, given\n // ---G--|---G--- fj 8 i = 1.4 and j = 8.3, the four surrounding grid points are (1, 8), (2, 8),\n // j ___|_ . | (1, 9) and (2, 9).\n // =8.3 | |\n // ---G------G--- cj 9 Note that for wrapped grids, the first column is duplicated as the last\n // | | column, so the index ci can be used without taking a modulo.\n\n let indexes = this._getFourSurroundingIndexes(i, j);\n let [fi, ci, fj, cj] = indexes;\n let values = this._getFourSurroundingValues(fi, ci, fj, cj);\n if (values) {\n let [g00, g10, g01, g11] = values;\n return this._doInterpolation(i - fi, j - fj, g00, g10, g01, g11);\n }\n return null;\n }\n\n /**\n * Get decimal indexes\n * @private\n * @param {Number} lon\n * @param {Number} lat\n * @returns {Array} [[Description]]\n */\n _getDecimalIndexes(lon, lat) {\n if (this.longitudeNeedsToBeWrapped && lon < this.xllCorner) {\n lon = lon + 360;\n }\n let i = (lon - this.xllCorner) / this.cellXSize;\n let j = (this.yurCorner - lat) / this.cellYSize;\n return [i, j];\n }\n\n /**\n * Get surrounding indexes (integer), clampling on borders\n * @private\n * @param {Number} i - decimal index\n * @param {Number} j - decimal index\n * @returns {Array} [fi, ci, fj, cj]\n */\n _getFourSurroundingIndexes(i, j) {\n let fi = Math.floor(i);\n let ci = fi + 1;\n // duplicate colum to simplify interpolation logic (wrapped value)\n if (this.isContinuous && ci >= this.nCols) {\n ci = 0;\n }\n ci = this._clampColumnIndex(ci);\n\n let fj = this._clampRowIndex(Math.floor(j));\n let cj = this._clampRowIndex(fj + 1);\n\n return [fi, ci, fj, cj];\n }\n\n /**\n * Get four surrounding values or null if not available,\n * from 4 integer indexes\n * @private\n * @param {Number} fi\n * @param {Number} ci\n * @param {Number} fj\n * @param {Number} cj\n * @returns {Array} \n */\n _getFourSurroundingValues(fi, ci, fj, cj) {\n var row;\n if ((row = this.grid[fj])) {\n // upper row ^^\n var g00 = row[fi]; // << left\n var g10 = row[ci]; // right >>\n if (\n this._isValid(g00) &&\n this._isValid(g10) &&\n (row = this.grid[cj])\n ) {\n // lower row vv\n var g01 = row[fi]; // << left\n var g11 = row[ci]; // right >>\n if (this._isValid(g01) && this._isValid(g11)) {\n return [g00, g10, g01, g11]; // 4 values found!\n }\n }\n }\n return null;\n }\n\n /**\n * Nearest value at lon-lat coordinates\n * @param {Number} longitude\n * @param {Number} latitude\n * @returns {Vector|Number}\n */\n valueAt(lon, lat) {\n if (this.notContains(lon, lat)) return null;\n\n let [i, j] = this._getDecimalIndexes(lon, lat);\n let ii = Math.floor(i);\n let jj = Math.floor(j);\n\n const ci = this._clampColumnIndex(ii);\n const cj = this._clampRowIndex(jj);\n\n let value = this._valueAtIndexes(ci, cj);\n if (this._inFilter) {\n if (!this._inFilter(value)) return null;\n }\n\n return value;\n }\n\n /**\n * Returns whether or not the field has a value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n hasValueAt(lon, lat) {\n let value = this.valueAt(lon, lat);\n let hasValue = value !== null;\n\n let included = true;\n if (this._inFilter) {\n included = this._inFilter(value);\n }\n return hasValue && included;\n }\n\n /**\n * Returns if the grid has no value at the point\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n notHasValueAt(lon, lat) {\n return !this.hasValueAt(lon, lat);\n }\n\n /**\n * Gives a random position to 'o' inside the grid\n * @param {Object} [o] - an object (eg. a particle)\n * @returns {{x: Number, y: Number}} - object with x, y (lon, lat)\n */\n randomPosition(o = {}) {\n let i = (Math.random() * this.nCols) | 0;\n let j = (Math.random() * this.nRows) | 0;\n\n o.x = this._longitudeAtX(i);\n o.y = this._latitudeAtY(j);\n\n return o;\n }\n\n /**\n * Value for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Vector|Number}\n */\n _valueAtIndexes(i, j) {\n return this.grid[j][i]; // <-- j,i !!\n }\n\n /**\n * Lon-Lat for grid indexes\n * @param {Number} i - column index (integer)\n * @param {Number} j - row index (integer)\n * @returns {Number[]} [lon, lat]\n */\n _lonLatAtIndexes(i, j) {\n let lon = this._longitudeAtX(i);\n let lat = this._latitudeAtY(j);\n\n return [lon, lat];\n }\n\n /**\n * Longitude for grid-index\n * @param {Number} i - column index (integer)\n * @returns {Number} longitude at the center of the cell\n */\n _longitudeAtX(i) {\n let halfXPixel = this.cellXSize / 2.0;\n let lon = this.xllCorner + halfXPixel + i * this.cellXSize;\n if (this.longitudeNeedsToBeWrapped) {\n lon = lon > 180 ? lon - 360 : lon;\n }\n return lon;\n }\n\n /**\n * Latitude for grid-index\n * @param {Number} j - row index (integer)\n * @returns {Number} latitude at the center of the cell\n */\n _latitudeAtY(j) {\n let halfYPixel = this.cellYSize / 2.0;\n return this.yurCorner - halfYPixel - j * this.cellYSize;\n }\n\n /**\n * Apply the interpolation\n * @abstract\n * @private\n */\n /* eslint-disable no-unused-vars */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n throw new TypeError('Must be overriden');\n }\n /* eslint-disable no-unused-vars */\n\n /**\n * Check the column index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} ii - index\n * @returns {Number} i - inside the allowed indexes\n */\n _clampColumnIndex(ii) {\n let i = ii;\n if (ii < 0) {\n i = 0;\n }\n let maxCol = this.nCols - 1;\n if (ii > maxCol) {\n i = maxCol;\n }\n return i;\n }\n\n /**\n * Check the row index is inside the field,\n * adjusting to min or max when needed\n * @private\n * @param {Number} jj index\n * @returns {Number} j - inside the allowed indexes\n */\n _clampRowIndex(jj) {\n let j = jj;\n if (jj < 0) {\n j = 0;\n }\n let maxRow = this.nRows - 1;\n if (jj > maxRow) {\n j = maxRow;\n }\n return j;\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n _isValid(x) {\n return x !== null && x !== undefined;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./Field.js","import Field from './Field';\n\n/**\n * Scalar Field\n */\nexport default class ScalarField extends Field {\n /**\n * Creates a ScalarField from the content of an ASCIIGrid file\n * @param {String} asc\n * @returns {ScalarField}\n */\n static fromASCIIGrid(asc, scaleFactor = 1) {\n //console.time('ScalarField from ASC');\n\n let lines = asc.split('\\n');\n\n // Header\n ScalarField._checkIsValidASCIIGridHeader(lines);\n\n let n = /-?(?:0|[1-9]\\d*)(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/; // any number\n\n const cellSize = parseFloat(lines[4].match(n)); // right now, no different x-y size is allowed\n let p = {\n nCols: parseInt(lines[0].match(n)),\n nRows: parseInt(lines[1].match(n)),\n xllCorner: parseFloat(lines[2].match(n)),\n yllCorner: parseFloat(lines[3].match(n)),\n cellXSize: cellSize,\n cellYSize: cellSize\n };\n let noDataValue = lines[5]\n .toUpperCase()\n .replace('NODATA_VALUE', '')\n .trim();\n\n // Data (left-right and top-down)\n let zs = []; // TODO Consider using TypedArray (& manage NO_DATA)\n for (let i = 6; i < lines.length; i++) {\n let line = lines[i].trim();\n if (line === '') break;\n\n let items = line.split(' ');\n items.forEach(it => {\n const v =\n it !== noDataValue ? parseFloat(it * scaleFactor) : null;\n zs.push(v);\n });\n }\n p.zs = zs;\n\n //console.timeEnd('ScalarField from ASC');\n return new ScalarField(p);\n }\n\n static _checkIsValidASCIIGridHeader(lines) {\n const upperCasesLines = lines.map(lin => lin.toUpperCase());\n\n const parameters = [\n 'NCOLS',\n 'NROWS',\n 'XLLCORNER',\n 'YLLCORNER',\n 'CELLSIZE',\n 'NODATA_VALUE'\n ];\n\n let i = 0;\n for (let expected of parameters) {\n let line = upperCasesLines[i];\n let found = line.indexOf(expected) != -1;\n if (!found) {\n throw `Not valid ASCIIGrid: expected '${expected}' at line '${line}' [lin. nº ${i}]`;\n }\n i++;\n }\n }\n\n /**\n * Creates a ScalarField from the content of a GeoTIFF file, as read by geotiff.js\n * @param {ArrayBuffer} data\n * @param {Number} bandIndex\n * @returns {ScalarField}\n */\n static fromGeoTIFF(data, bandIndex = 0) {\n //console.time('ScalarField from GeoTIFF');\n\n let tiff = GeoTIFF.parse(data); // geotiff.js\n let image = tiff.getImage();\n let rasters = image.readRasters();\n let tiepoint = image.getTiePoints()[0];\n let fileDirectory = image.getFileDirectory();\n let [xScale, yScale] = fileDirectory.ModelPixelScale;\n\n let zs = rasters[bandIndex]; // left-right and top-down order\n\n if (fileDirectory.GDAL_NODATA) {\n let noData = parseFloat(fileDirectory.GDAL_NODATA);\n // console.log(noData);\n let simpleZS = Array.from(zs); // to simple array, so null is allowed | TODO efficiency??\n zs = simpleZS.map(function(z) {\n return z === noData ? null : z;\n });\n }\n\n let p = {\n nCols: image.getWidth(),\n nRows: image.getHeight(),\n xllCorner: tiepoint.x,\n yllCorner: tiepoint.y - image.getHeight() * yScale,\n cellXSize: xScale,\n cellYSize: yScale,\n zs: zs\n };\n\n //console.timeEnd('ScalarField from GeoTIFF');\n return new ScalarField(p);\n }\n\n constructor(params) {\n super(params);\n this.zs = params['zs'];\n\n this.grid = this._buildGrid();\n this._updateRange();\n //console.log(`ScalarField created (${this.nCols} x ${this.nRows})`);\n }\n\n /**\n * Builds a grid with a Number at each point, from an array\n * 'zs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @private\n * @returns {Array.>} - grid[row][column]--> Number\n */\n _buildGrid() {\n let grid = this._arrayTo2d(this.zs, this.nRows, this.nCols);\n return grid;\n }\n\n _arrayTo2d(array, nRows, nCols) {\n let grid = [];\n let p = 0;\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n let z = array[p];\n row[i] = this._isValid(z) ? z : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n\n _newDataArrays(params) {\n params['zs'] = [];\n }\n\n _pushValueToArrays(params, value) {\n params['zs'].push(value);\n }\n\n _makeNewFrom(params) {\n return new ScalarField(params);\n }\n\n /**\n * Calculate min & max values\n * @private\n * @returns {Array} - [min, max]\n */\n _calculateRange() {\n var data = this.zs;\n if (this._inFilter) {\n data = data.filter(this._inFilter);\n }\n return [d3.min(data), d3.max(data)];\n }\n\n /**\n * Bilinear interpolation for Number\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number} g00\n * @param {Number} g10\n * @param {Number} g01\n * @param {Number} g11\n * @returns {Number}\n */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n return g00 * rx * ry + g10 * x * ry + g01 * rx * y + g11 * x * y;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./ScalarField.js","/**\n * 2D Vector\n */\nexport default class Vector {\n\n constructor(u, v) {\n this.u = u;\n this.v = v;\n }\n\n /**\n * Magnitude\n * @returns {Number}\n */\n magnitude() {\n return Math.sqrt(this.u * this.u + this.v * this.v);\n }\n\n /**\n * Angle in degrees (0 to 360º) --> Towards\n * N is 0º and E is 90º\n * @returns {Number}\n */\n directionTo() {\n let verticalAngle = Math.atan2(this.u, this.v);\n let inDegrees = verticalAngle * (180.0 / Math.PI);\n if (inDegrees < 0) {\n inDegrees = inDegrees + 360.0;\n }\n return inDegrees;\n }\n\n /**\n * Angle in degrees (0 to 360º) From x-->\n * N is 0º and E is 90º\n * @returns {Number}\n */\n directionFrom() {\n let a = this.directionTo();\n let opposite = (a + 180.0) % 360.0;\n return opposite;\n }\n\n /*\n Degrees --> text\n new Dictionary\n {\n //{0, 23, 45, 68, 90, 113, 135, 158, 180, 203, 225, 248, 270, 293, 315, 338, 360};\n {0, 'N'},\n {23, 'NNE'},\n {45, 'NE'},\n {68, 'ENE'},\n {90, 'E'},\n {113, 'ESE'},\n {135, 'SE'},\n {158, 'SSE'},\n {180, 'S'},\n {203, 'SSW'},\n {225, 'SW'},\n {248, 'WSW'},\n {270, 'W'},\n {293, 'WNW'},\n {315, 'NW'},\n {338, 'NNW'},\n {360, 'N'}\n };\n */\n}\n\n\n\n// WEBPACK FOOTER //\n// ./Vector.js","import Vector from './Vector';\nimport Field from './Field';\nimport ScalarField from './ScalarField';\n\n/**\n * A set of vectors assigned to a regular 2D-grid (lon-lat)\n * (e.g. a raster representing winds for a region)\n */\nexport default class VectorField extends Field {\n /**\n * Creates a VectorField from the content of two ASCIIGrid files\n * @param {String} ascU - with u-component\n * @param {String} ascV - with v-component\n * @returns {VectorField}\n */\n static fromASCIIGrids(ascU, ascV, scaleFactor = 1) {\n let u = ScalarField.fromASCIIGrid(ascU, scaleFactor);\n let v = ScalarField.fromASCIIGrid(ascV, scaleFactor);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of two different Geotiff files\n * @param {ArrayBuffer} gtU - geotiff data with u-component (band 0)\n * @param {ArrayBuffer} gtV - geotiff data with v-component (band 0)\n * @returns {VectorField}\n */\n static fromGeoTIFFs(gtU, gtV) {\n let u = ScalarField.fromGeoTIFF(gtU);\n let v = ScalarField.fromGeoTIFF(gtV);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Creates a VectorField from the content of Multiband Geotiff\n * @param {ArrayBuffer} geotiffData - multiband\n * @param {Array} bandIndexesForUV\n * @returns {VectorField}\n */\n static fromMultibandGeoTIFF(geotiffData, bandIndexesForUV = [0, 1]) {\n let u = ScalarField.fromGeoTIFF(geotiffData, bandIndexesForUV[0]);\n let v = ScalarField.fromGeoTIFF(geotiffData, bandIndexesForUV[1]);\n let p = VectorField._paramsFromScalarFields(u, v);\n\n return new VectorField(p);\n }\n\n /**\n * Build parameters for VectorField, from 2 ScalarFields.\n * No validation at all (nor interpolation) is applied, so u and v\n * must be 'compatible' from the source\n * @param {ScalarField} u\n * @param {ScalarField} v\n * @returns {Object} - parameters to build VectorField\n */\n static _paramsFromScalarFields(u, v) {\n // TODO check u & v compatibility (cellSize...)\n let p = {\n nCols: u.nCols,\n nRows: u.nRows,\n xllCorner: u.xllCorner,\n yllCorner: u.yllCorner,\n cellXSize: u.cellXSize,\n cellYSize: u.cellYSize,\n us: u.zs,\n vs: v.zs\n };\n return p;\n }\n\n constructor(params) {\n super(params);\n\n this.us = params['us'];\n this.vs = params['vs'];\n this.grid = this._buildGrid();\n this.range = this._calculateRange();\n }\n\n /**\n * Get a derived field, from a computation on \n * the VectorField\n * @param {String} type ['magnitude' | 'directionTo' | 'directionFrom']\n * @returns {ScalarField}\n */\n getScalarField(type) {\n let f = this._getFunctionFor(type);\n let p = {\n nCols: this.params.nCols,\n nRows: this.params.nRows,\n xllCorner: this.params.xllCorner,\n yllCorner: this.params.yllCorner,\n cellXSize: this.params.cellXSize,\n cellYSize: this.params.cellYSize,\n zs: this._applyOnField(f)\n };\n return new ScalarField(p);\n }\n\n _getFunctionFor(type) {\n return function(u, v) {\n let uv = new Vector(u, v);\n return uv[type](); // magnitude, directionTo, directionFrom\n };\n }\n\n _applyOnField(func) {\n let zs = [];\n let n = this.numCells();\n for (var i = 0; i < n; i++) {\n let u = this.us[i];\n let v = this.vs[i];\n if (this._isValid(u) && this._isValid(v)) {\n zs.push(func(u, v));\n } else {\n zs.push(null);\n }\n }\n return zs;\n }\n\n /**\n * Builds a grid with a Vector at each point, from two arrays\n * 'us' and 'vs' following x-ascending & y-descending order\n * (same as in ASCIIGrid)\n * @returns {Array.>} - grid[row][column]--> Vector\n */\n _buildGrid() {\n let grid = this._arraysTo2d(this.us, this.vs, this.nRows, this.nCols);\n return grid;\n }\n\n _arraysTo2d(us, vs, nRows, nCols) {\n let grid = [];\n let p = 0;\n\n for (var j = 0; j < nRows; j++) {\n var row = [];\n for (var i = 0; i < nCols; i++, p++) {\n let u = us[p],\n v = vs[p];\n let valid = this._isValid(u) && this._isValid(v);\n row[i] = valid ? new Vector(u, v) : null; // <<<\n }\n grid[j] = row;\n }\n return grid;\n }\n\n _newDataArrays(params) {\n params['us'] = [];\n params['vs'] = [];\n }\n _pushValueToArrays(params, value) {\n //console.log(value);\n params['us'].push(value.u);\n params['vs'].push(value.v);\n }\n _makeNewFrom(params) {\n return new VectorField(params);\n }\n\n /**\n * Calculate min & max values (magnitude)\n * @private\n * @returns {Array}\n */\n _calculateRange() {\n // TODO make a clearer method for getting these vectors...\n let vectors = this.getCells().map(pt => pt.value).filter(function(v) {\n return v !== null;\n });\n\n if (this._inFilter) {\n vectors = vectors.filter(this._inFilter);\n }\n\n // TODO check memory crash with high num of vectors!\n let magnitudes = vectors.map(v => v.magnitude());\n let min = d3.min(magnitudes);\n let max = d3.max(magnitudes);\n\n return [min, max];\n }\n\n /**\n * Bilinear interpolation for Vector\n * https://en.wikipedia.org/wiki/Bilinear_interpolation\n * @param {Number} x\n * @param {Number} y\n * @param {Number[]} g00\n * @param {Number[]} g10\n * @param {Number[]} g01\n * @param {Number[]} g11\n * @returns {Vector}\n */\n _doInterpolation(x, y, g00, g10, g01, g11) {\n var rx = 1 - x;\n var ry = 1 - y;\n var a = rx * ry,\n b = x * ry,\n c = rx * y,\n d = x * y;\n var u = g00.u * a + g10.u * b + g01.u * c + g11.u * d;\n var v = g00.v * a + g10.v * b + g01.v * c + g11.v * d;\n return new Vector(u, v);\n }\n\n /**\n * Is valid (not 'null' nor 'undefined')\n * @private\n * @param {Object} x object\n * @returns {Boolean}\n */\n _isValid(x) {\n return x !== null && x !== undefined;\n }\n}\n\n\n\n// WEBPACK FOOTER //\n// ./VectorField.js","/**\n * Control for a simple legend with a colorbar\n * References:\n * - http://jsfiddle.net/ramnathv/g8stqcf6/\n * - http://jsfiddle.net/vis4/cYLZH/\n */\nL.Control.ColorBar = L.Control.extend({\n options: {\n position: 'bottomleft',\n width: 300, // for colorbar itself (control is wider)\n height: 15,\n margin: 15,\n background: '#fff',\n textColor: 'black',\n steps: 100,\n decimals: 2,\n units: 'uds', // ej: m/s\n title: 'Legend', // ej: Ocean Currents\n labels: [], // empty for no labels\n labelFontSize: 10,\n labelTextPosition: 'middle' // start | middle | end\n },\n\n initialize: function(color, range, options) {\n this.color = color; // 'chromajs' scale function\n this.range = range; // [min, max]\n L.Util.setOptions(this, options);\n },\n\n onAdd: function(map) {\n this._map = map;\n let div = L.DomUtil.create(\n 'div',\n 'leaflet-control-colorBar leaflet-bar leaflet-control'\n );\n div.style.padding = '10px';\n\n L.DomEvent\n .addListener(div, 'click', L.DomEvent.stopPropagation)\n .addListener(div, 'click', L.DomEvent.preventDefault);\n div.style.backgroundColor = this.options.background;\n div.style.cursor = 'text';\n div.innerHTML = this.title() + this.palette();\n return div;\n },\n\n title: function() {\n let d = document.createElement('div');\n d3\n .select(d)\n .append('span')\n .style('color', this.options.textColor)\n .style('display', 'block')\n .style('margin-bottom', '5px')\n .attr('class', 'leaflet-control-colorBar-title')\n .text(this.options.title);\n return d.innerHTML;\n },\n\n palette: function() {\n let d = document.createElement('div');\n let svg = this._createSvgIn(d);\n\n this._appendColorBarTo(svg);\n\n if (this.options.labels) {\n this._appendLabelsTo(svg);\n }\n\n return d.innerHTML;\n },\n\n _createSvgIn: function(d) {\n let spaceForLabels = this.options.labels ? this.options.margin : 0;\n let svg = d3\n .select(d)\n .append('svg')\n .attr('width', this.options.width + this.options.margin * 2)\n .attr('height', this.options.height + spaceForLabels);\n return svg;\n },\n\n _appendColorBarTo: function(svg) {\n const colorPerValue = this._getColorPerValue();\n const w = this.options.width / colorPerValue.length;\n\n let groupBars = svg.append('g').attr('id', 'colorBar-buckets');\n let buckets = groupBars\n .selectAll('rect')\n .data(colorPerValue)\n .enter()\n .append('rect');\n buckets\n .attr('x', (d, i) => i * w + this.options.margin)\n .attr('y', () => 0)\n .attr('height', () => this.options.height /*w * 4*/)\n .attr('width', () => w)\n .attr('stroke-width', 2)\n .attr('stroke-linecap', 'butt')\n .attr('stroke', d => d.color.hex())\n .attr('fill', d => d.color.hex());\n buckets\n .append('title')\n .text(\n d =>\n `${d.value.toFixed(this.options.decimals)} ${this.options\n .units}`\n );\n },\n\n _appendLabelsTo: function(svg) {\n const positionPerLabelValue = this._getPositionPerLabelValue();\n //const w = this.options.width / colorPerValue.length;\n let groupLabels = svg.append('g').attr('id', 'colorBar-labels');\n let labels = groupLabels\n .selectAll('text')\n .data(positionPerLabelValue)\n .enter()\n .append('text');\n labels\n .attr('x', d => d.position + this.options.margin)\n .attr('y', this.options.height + this.options.margin)\n .attr('font-size', `${this.options.labelFontSize}px`)\n .attr('text-anchor', this.options.labelTextPosition)\n .attr('fill', this.options.textColor)\n .attr('class', 'leaflet-control-colorBar-label')\n .text(d => `${d.value.toFixed(this.options.decimals)}`);\n },\n\n _getColorPerValue: function() {\n const [min, max] = this.range;\n let delta = (max - min) / this.options.steps;\n let data = d3.range(min, max + delta, delta);\n let colorPerValue = data.map(d => {\n return {\n value: d,\n color: this.color(d)\n };\n });\n return colorPerValue;\n },\n\n _getPositionPerLabelValue: function() {\n var xPositionFor = d3\n .scaleLinear()\n .range([0, this.options.width])\n .domain(this.range);\n let data = this.options.labels;\n let positionPerLabel = data.map(d => {\n return {\n value: d,\n position: xPositionFor(d)\n };\n });\n return positionPerLabel;\n }\n});\n\nL.control.colorBar = function(color, range, options) {\n return new L.Control.ColorBar(color, range, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./control/L.Control.ColorBar.js","/**\n * Abstract class for a Field layer on canvas, aka 'a Raster layer'\n * (ScalarField or a VectorField)\n */\nL.CanvasLayer.Field = L.CanvasLayer.extend({\n options: {\n mouseMoveCursor: {\n value: 'pointer',\n noValue: 'default'\n },\n opacity: 1,\n onClick: null,\n onMouseMove: null,\n inFilter: null\n },\n\n initialize: function(field, options) {\n L.Util.setOptions(this, options);\n this._visible = true;\n if (field) {\n this.setData(field);\n }\n },\n\n getEvents: function() {\n var events = L.CanvasLayer.prototype.getEvents.call(this);\n events.zoomstart = this._hideCanvas.bind(this);\n events.zoomend = this._showCanvas.bind(this);\n return events;\n },\n\n onLayerDidMount: function() {\n this._enableIdentify();\n this._ensureCanvasAlignment();\n },\n\n show() {\n this._visible = true;\n this._showCanvas();\n this._enableIdentify();\n },\n\n hide() {\n this._visible = false;\n this._hideCanvas();\n this._disableIdentify();\n },\n\n isVisible() {\n return this._visible;\n },\n\n _showCanvas() {\n if (this._canvas && this._visible) {\n this._canvas.style.visibility = 'visible';\n }\n },\n\n _hideCanvas() {\n if (this._canvas) {\n this._canvas.style.visibility = 'hidden';\n }\n },\n\n _enableIdentify() {\n this._map.on('click', this._onClick, this);\n this._map.on('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.on('click', this.options.onClick, this);\n this.options.onMouseMove &&\n this.on('mousemove', this.options.onMouseMove, this);\n },\n\n _disableIdentify() {\n this._map.off('click', this._onClick, this);\n this._map.off('mousemove', this._onMouseMove, this);\n\n this.options.onClick && this.off('click', this.options.onClick, this);\n this.options.onMouseMove &&\n this.off('mousemove', this.options.onMouseMove, this);\n },\n\n _ensureCanvasAlignment() {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n },\n\n onLayerWillUnmount: function() {\n this._disableIdentify();\n },\n\n needRedraw() {\n if (this._map && this._field) {\n L.CanvasLayer.prototype.needRedraw.call(this);\n }\n },\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function(viewInfo) {\n throw new TypeError('Must be overriden');\n },\n /* eslint-enable no-unused-vars */\n\n setData: function(field) {\n this.options.inFilter && field.setFilter(this.options.inFilter);\n this._field = field;\n this.needRedraw();\n this.fire('load');\n },\n\n setFilter: function(f) {\n this.options.inFilter = f;\n this._field && this._field.setFilter(f);\n this.needRedraw();\n },\n\n setOpacity: function(opacity) {\n this.options.opacity = opacity;\n\n if (this._canvas) {\n this._updateOpacity();\n }\n return this;\n },\n\n getBounds: function() {\n let bb = this._field.extent();\n\n let southWest = L.latLng(bb[1], bb[0]),\n northEast = L.latLng(bb[3], bb[2]);\n let bounds = L.latLngBounds(southWest, northEast);\n return bounds;\n },\n\n _onClick: function(e) {\n let v = this._queryValue(e);\n this.fire('click', v);\n },\n\n _onMouseMove: function(e) {\n let v = this._queryValue(e);\n this._changeCursorOn(v);\n this.fire('mousemove', v);\n },\n\n _changeCursorOn: function(v) {\n if (!this.options.mouseMoveCursor) return;\n\n let { value, noValue } = this.options.mouseMoveCursor;\n let style = this._map.getContainer().style;\n style.cursor = v.value !== null ? value : noValue;\n },\n\n _updateOpacity: function() {\n L.DomUtil.setOpacity(this._canvas, this.options.opacity);\n },\n\n _queryValue: function(e) {\n let v = this._field\n ? this._field.valueAt(e.latlng.lng, e.latlng.lat)\n : null;\n let result = {\n latlng: e.latlng,\n value: v\n };\n return result;\n },\n\n _getDrawingContext: function() {\n let g = this._canvas.getContext('2d');\n g.clearRect(0, 0, this._canvas.width, this._canvas.height);\n return g;\n }\n});\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.Field.js","import Cell from '../Cell';\n\n/**\n * ScalarField on canvas (a 'Raster')\n */\nL.CanvasLayer.ScalarField = L.CanvasLayer.Field.extend({\n options: {\n type: 'colormap', // [colormap|vector]\n color: null, // function colorFor(value) [e.g. chromajs.scale],\n interpolate: false, // Change to use interpolation\n vectorSize: 20, // only used if 'vector'\n arrowDirection: 'from' // [from|towards]\n },\n\n initialize: function(scalarField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(\n this,\n scalarField,\n options\n );\n L.Util.setOptions(this, options);\n },\n\n _defaultColorScale: function() {\n return chroma.scale(['white', 'black']).domain(this._field.range);\n },\n\n setColor(f) {\n this.options.color = f;\n this.needRedraw();\n },\n\n /* eslint-disable no-unused-vars */\n onDrawLayer: function(viewInfo) {\n if (!this.isVisible()) return;\n this._updateOpacity();\n\n let r = this._getRendererMethod();\n //console.time('onDrawLayer');\n r();\n //console.timeEnd('onDrawLayer');\n },\n /* eslint-enable no-unused-vars */\n\n _getRendererMethod: function() {\n switch (this.options.type) {\n case 'colormap':\n return this._drawImage.bind(this);\n case 'vector':\n return this._drawArrows.bind(this);\n default:\n throw Error(`Unkwown renderer type: ${this.options.type}`);\n }\n },\n\n _ensureColor: function() {\n if (this.options.color === null) {\n this.setColor(this._defaultColorScale());\n }\n },\n\n _showCanvas() {\n L.CanvasLayer.Field.prototype._showCanvas.call(this);\n this.needRedraw(); // TODO check spurious redraw (e.g. hide/show without moving map)\n },\n\n /**\n * Draws the field in an ImageData and applying it with putImageData.\n * Used as a reference: http://geoexamples.com/d3-raster-tools-docs/code_samples/raster-pixels-page.html\n */\n _drawImage: function() {\n this._ensureColor();\n\n let ctx = this._getDrawingContext();\n let width = this._canvas.width;\n let height = this._canvas.height;\n\n let img = ctx.createImageData(width, height);\n let data = img.data;\n\n this._prepareImageIn(data, width, height);\n ctx.putImageData(img, 0, 0);\n },\n\n /**\n * Prepares the image in data, as array with RGBAs\n * [R1, G1, B1, A1, R2, G2, B2, A2...]\n * @private\n * @param {[[Type]]} data [[Description]]\n * @param {Numver} width\n * @param {Number} height\n */\n _prepareImageIn(data, width, height) {\n let f = this.options.interpolate ? 'interpolatedValueAt' : 'valueAt';\n\n let pos = 0;\n for (let j = 0; j < height; j++) {\n for (let i = 0; i < width; i++) {\n let pointCoords = this._map.containerPointToLatLng([i, j]);\n let lon = pointCoords.lng;\n let lat = pointCoords.lat;\n\n let v = this._field[f](lon, lat); // 'valueAt' | 'interpolatedValueAt' || TODO check some 'artifacts'\n if (v !== null) {\n let color = this._getColorFor(v);\n let [R, G, B, A] = color.rgba();\n data[pos] = R;\n data[pos + 1] = G;\n data[pos + 2] = B;\n data[pos + 3] = parseInt(A * 255); // not percent in alpha but hex 0-255\n }\n pos = pos + 4;\n }\n }\n },\n\n /**\n * Draws the field as a set of arrows. Direction from 0 to 360 is assumed.\n */\n _drawArrows: function() {\n const bounds = this._pixelBounds();\n const pixelSize = (bounds.max.x - bounds.min.x) / this._field.nCols;\n\n var stride = Math.max(\n 1,\n Math.floor(1.2 * this.options.vectorSize / pixelSize)\n );\n\n const ctx = this._getDrawingContext();\n ctx.strokeStyle = this.options.color;\n\n var currentBounds = this._map.getBounds();\n\n for (var y = 0; y < this._field.height; y = y + stride) {\n for (var x = 0; x < this._field.width; x = x + stride) {\n let [lon, lat] = this._field._lonLatAtIndexes(x, y);\n let v = this._field.valueAt(lon, lat);\n let center = L.latLng(lat, lon);\n if (v !== null && currentBounds.contains(center)) {\n let cell = new Cell(\n center,\n v,\n this.cellXSize,\n this.cellYSize\n );\n this._drawArrow(cell, ctx);\n }\n }\n }\n },\n\n _pixelBounds: function() {\n const bounds = this.getBounds();\n const northWest = this._map.latLngToContainerPoint(\n bounds.getNorthWest()\n );\n const southEast = this._map.latLngToContainerPoint(\n bounds.getSouthEast()\n );\n var pixelBounds = L.bounds(northWest, southEast);\n return pixelBounds;\n },\n\n _drawArrow: function(cell, ctx) {\n var projected = this._map.latLngToContainerPoint(cell.center);\n\n // colormap vs. simple color\n let color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(cell.value);\n }\n\n const size = this.options.vectorSize;\n ctx.save();\n\n ctx.translate(projected.x, projected.y);\n\n let rotationRads = (90 + cell.value) * Math.PI / 180; // from, by default\n if (this.options.arrowDirection === 'towards') {\n rotationRads = rotationRads + Math.PI;\n }\n ctx.rotate(rotationRads);\n\n ctx.beginPath();\n ctx.moveTo(-size / 2, 0);\n ctx.lineTo(+size / 2, 0);\n ctx.moveTo(size * 0.25, -size * 0.25);\n ctx.lineTo(+size / 2, 0);\n ctx.lineTo(size * 0.25, size * 0.25);\n ctx.stroke();\n ctx.restore();\n },\n\n /**\n * Gets a chroma color for a pixel value, according to 'options.color'\n */\n _getColorFor(v) {\n let c = this.options.color; // e.g. for a constant 'red'\n if (typeof c === 'function') {\n c = this.options.color(v);\n }\n let color = chroma(c); // to be more flexible, a chroma color object is always created || TODO improve efficiency\n return color;\n }\n});\n\nL.canvasLayer.scalarField = function(scalarField, options) {\n return new L.CanvasLayer.ScalarField(scalarField, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.ScalarField.js","/**\n * Simple layer with lon-lat points\n *\n * TODO rename to SimplePoint?\n */\nL.CanvasLayer.SimpleLonLat = L.CanvasLayer.extend({\n options: {\n color: 'gray'\n },\n\n initialize: function(points, options) {\n this.points = points;\n L.Util.setOptions(this, options);\n },\n\n onLayerDidMount: function() {\n // -- prepare custom drawing\n },\n\n onLayerWillUnmount: function() {\n // -- custom cleanup\n },\n\n /* eslint-disable no-unused-vars */\n setData: function(data) {\n // -- custom data set\n this.needRedraw(); // -- call to drawLayer\n },\n /* eslint-enable no-unused-vars */\n\n onDrawLayer: function(viewInfo) {\n // canvas preparation\n let g = viewInfo.canvas.getContext('2d');\n g.clearRect(0, 0, viewInfo.canvas.width, viewInfo.canvas.height);\n g.fillStyle = this.options.color;\n\n for (let point of this.points) {\n let p = viewInfo.layer._map.latLngToContainerPoint(point);\n g.beginPath();\n //g.arc(p.x, p.y, 1, 0, Math.PI * 2); // circle | TODO style 'function' as parameter?\n g.fillRect(p.x, p.y, 2, 2); //simple point\n g.fill();\n g.closePath();\n g.stroke();\n }\n },\n\n getBounds: function() {\n // TODO: bounding with points...\n let xs = this.points.map(pt => pt.lng);\n let ys = this.points.map(pt => pt.lat);\n\n let xmin = Math.min(...xs);\n let ymin = Math.min(...ys);\n let xmax = Math.max(...xs);\n let ymax = Math.max(...ys);\n\n let southWest = L.latLng(ymin, xmin),\n northEast = L.latLng(ymax, xmax);\n let bounds = L.latLngBounds(southWest, northEast); // TODO FIX ERROR ? half-pixel?\n return bounds;\n }\n});\n\nL.canvasLayer.simpleLonLat = function(lonslats, options) {\n return new L.CanvasLayer.SimpleLonLat(lonslats, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.SimpleLonLat.js","/**\n * Animated VectorField on canvas\n */\nL.CanvasLayer.VectorFieldAnim = L.CanvasLayer.Field.extend({\n options: {\n paths: 800,\n color: 'white', // html-color | function colorFor(value) [e.g. chromajs.scale]\n width: 1.0, // number | function widthFor(value)\n fade: 0.96, // 0 to 1\n duration: 20, // milliseconds per 'frame'\n maxAge: 200, // number of maximum frames per path\n velocityScale: 1 / 5000\n },\n\n initialize: function(vectorField, options) {\n L.CanvasLayer.Field.prototype.initialize.call(\n this,\n vectorField,\n options\n );\n L.Util.setOptions(this, options);\n\n this.timer = null;\n },\n\n onLayerDidMount: function() {\n L.CanvasLayer.Field.prototype.onLayerDidMount.call(this);\n this._map.on('move resize', this._stopAnimation, this);\n },\n\n onLayerWillUnmount: function() {\n L.CanvasLayer.Field.prototype.onLayerWillUnmount.call(this);\n this._map.off('move resize', this._stopAnimation, this);\n this._stopAnimation();\n },\n\n _hideCanvas: function _showCanvas() {\n L.CanvasLayer.Field.prototype._hideCanvas.call(this);\n this._stopAnimation();\n },\n\n onDrawLayer: function(viewInfo) {\n if (!this._field || !this.isVisible()) return;\n\n this._updateOpacity();\n\n let ctx = this._getDrawingContext();\n let paths = this._prepareParticlePaths();\n\n this.timer = d3.timer(function() {\n _moveParticles();\n _drawParticles();\n }, this.options.duration);\n\n let self = this;\n\n /**\n * Builds the paths, adding 'particles' on each animation step, considering\n * their properties (age / position source > target)\n */\n function _moveParticles() {\n // let screenFactor = 1 / self._map.getZoom(); // consider using a 'screenFactor' to ponderate velocityScale\n paths.forEach(function(par) {\n if (par.age > self.options.maxAge) {\n // restart, on a random x,y\n par.age = 0;\n self._field.randomPosition(par);\n }\n\n let vector = self._field.valueAt(par.x, par.y);\n if (vector === null) {\n par.age = self.options.maxAge;\n } else {\n // the next point will be...\n let xt = par.x + vector.u * self.options.velocityScale; //* screenFactor;\n let yt = par.y + vector.v * self.options.velocityScale; //* screenFactor;\n\n if (self._field.hasValueAt(xt, yt)) {\n par.xt = xt;\n par.yt = yt;\n par.m = vector.magnitude();\n } else {\n // not visible anymore...\n par.age = self.options.maxAge;\n }\n }\n par.age += 1;\n });\n }\n\n /**\n * Draws the paths on each step\n */\n function _drawParticles() {\n // Previous paths...\n let prev = ctx.globalCompositeOperation;\n ctx.globalCompositeOperation = 'destination-in';\n ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);\n //ctx.globalCompositeOperation = 'source-over';\n ctx.globalCompositeOperation = prev;\n\n // fading paths...\n ctx.fillStyle = `rgba(0, 0, 0, ${self.options.fade})`;\n ctx.lineWidth = self.options.width;\n ctx.strokeStyle = self.options.color;\n\n // New paths\n paths.forEach(function(par) {\n self._drawParticle(viewInfo, ctx, par);\n });\n }\n },\n\n _drawParticle(viewInfo, ctx, par) {\n let source = new L.latLng(par.y, par.x);\n let target = new L.latLng(par.yt, par.xt);\n\n if (\n viewInfo.bounds.contains(source) &&\n par.age <= this.options.maxAge\n ) {\n let pA = viewInfo.layer._map.latLngToContainerPoint(source);\n let pB = viewInfo.layer._map.latLngToContainerPoint(target);\n\n ctx.beginPath();\n ctx.moveTo(pA.x, pA.y);\n ctx.lineTo(pB.x, pB.y);\n\n // next-step movement\n par.x = par.xt;\n par.y = par.yt;\n\n // colormap vs. simple color\n let color = this.options.color;\n if (typeof color === 'function') {\n ctx.strokeStyle = color(par.m);\n }\n\n let width = this.options.width;\n if (typeof width === 'function') {\n ctx.lineWidth = width(par.m);\n }\n\n ctx.stroke();\n }\n },\n\n _prepareParticlePaths: function() {\n let paths = [];\n\n for (var i = 0; i < this.options.paths; i++) {\n let p = this._field.randomPosition();\n p.age = this._randomAge();\n paths.push(p);\n }\n return paths;\n },\n\n _randomAge: function() {\n return Math.floor(Math.random() * this.options.maxAge);\n },\n\n _stopAnimation: function() {\n if (this.timer) {\n this.timer.stop();\n }\n }\n});\n\nL.canvasLayer.vectorFieldAnim = function(vectorField, options) {\n return new L.CanvasLayer.VectorFieldAnim(vectorField, options);\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.VectorFieldAnim.js","/*\n 1.0.1 (downloaded from https://github.com/Sumbera/gLayers.Leaflet/releases/tag/v1.0.1)\n\n Generic Canvas Layer for leaflet 0.7 and 1.0-rc,\n copyright Stanislav Sumbera, 2016 , sumbera.com , license MIT\n originally created and motivated by L.CanvasOverlay available here: https://gist.github.com/Sumbera/11114288\n*/\n\nL.CanvasLayer = L.Layer.extend({\n // -- initialized is called on prototype\n initialize: function (options) {\n this._map = null;\n this._canvas = null;\n this._frame = null;\n this._delegate = null;\n L.setOptions(this, options);\n },\n\n delegate: function (del) {\n this._delegate = del;\n return this;\n },\n\n needRedraw: function () {\n if (!this._frame) {\n this._frame = L.Util.requestAnimFrame(this.drawLayer, this);\n }\n return this;\n },\n\n //-------------------------------------------------------------\n _onLayerDidResize: function (resizeEvent) {\n this._canvas.width = resizeEvent.newSize.x;\n this._canvas.height = resizeEvent.newSize.y;\n },\n //-------------------------------------------------------------\n _onLayerDidMove: function () {\n var topLeft = this._map.containerPointToLayerPoint([0, 0]);\n L.DomUtil.setPosition(this._canvas, topLeft);\n this.drawLayer();\n },\n //-------------------------------------------------------------\n getEvents: function () {\n var events = {\n resize: this._onLayerDidResize,\n moveend: this._onLayerDidMove\n };\n if (this._map.options.zoomAnimation && L.Browser.any3d) {\n events.zoomanim = this._animateZoom;\n }\n\n return events;\n },\n //-------------------------------------------------------------\n onAdd: function (map) {\n this._map = map;\n this._canvas = L.DomUtil.create('canvas', 'leaflet-layer');\n this.tiles = {};\n\n var size = this._map.getSize();\n this._canvas.width = size.x;\n this._canvas.height = size.y;\n\n var animated = this._map.options.zoomAnimation && L.Browser.any3d;\n L.DomUtil.addClass(this._canvas, 'leaflet-zoom-' + (animated ? 'animated' : 'hide'));\n\n\n map._panes.overlayPane.appendChild(this._canvas);\n\n map.on(this.getEvents(), this);\n\n var del = this._delegate || this;\n del.onLayerDidMount && del.onLayerDidMount(); // -- callback\n\n this.needRedraw();\n },\n\n //-------------------------------------------------------------\n onRemove: function (map) {\n var del = this._delegate || this;\n del.onLayerWillUnmount && del.onLayerWillUnmount(); // -- callback\n\n\n map.getPanes().overlayPane.removeChild(this._canvas);\n\n map.off(this.getEvents(), this);\n\n this._canvas = null;\n\n },\n\n //------------------------------------------------------------\n addTo: function (map) {\n map.addLayer(this);\n return this;\n },\n // --------------------------------------------------------------------------------\n LatLonToMercator: function (latlon) {\n return {\n x: latlon.lng * 6378137 * Math.PI / 180,\n y: Math.log(Math.tan((90 + latlon.lat) * Math.PI / 360)) * 6378137\n };\n },\n\n //------------------------------------------------------------------------------\n drawLayer: function () {\n // -- todo make the viewInfo properties flat objects.\n var size = this._map.getSize();\n var bounds = this._map.getBounds();\n var zoom = this._map.getZoom();\n\n var center = this.LatLonToMercator(this._map.getCenter());\n var corner = this.LatLonToMercator(this._map.containerPointToLatLng(this._map.getSize()));\n\n var del = this._delegate || this;\n del.onDrawLayer && del.onDrawLayer({\n layer: this,\n canvas: this._canvas,\n bounds: bounds,\n size: size,\n zoom: zoom,\n center: center,\n corner: corner\n });\n this._frame = null;\n },\n\n //------------------------------------------------------------------------------\n _animateZoom: function (e) {\n var scale = this._map.getZoomScale(e.zoom);\n var offset = this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(), e.zoom, e.center);\n\n L.DomUtil.setTransform(this._canvas, offset, scale);\n }\n});\n\nL.canvasLayer = function () {\n return new L.CanvasLayer();\n};\n\n\n\n// WEBPACK FOOTER //\n// ./layer/L.CanvasLayer.js","var invariant = require('@turf/invariant');\nvar getCoord = invariant.getCoord;\nvar getCoords = invariant.getCoords;\n\n// http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule\n// modified from: https://github.com/substack/point-in-polygon/blob/master/index.js\n// which was modified from http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html\n\n/**\n * Takes a {@link Point} and a {@link Polygon} or {@link MultiPolygon} and determines if the point resides inside the polygon. The polygon can\n * be convex or concave. The function accounts for holes.\n *\n * @name inside\n * @param {Feature} point input point\n * @param {Feature} polygon input polygon or multipolygon\n * @param {boolean} [ignoreBoundary=false] True if polygon boundary should be ignored when determining if the point is inside the polygon otherwise false.\n * @returns {boolean} `true` if the Point is inside the Polygon; `false` if the Point is not inside the Polygon\n * @example\n * var pt = turf.point([-77, 44]);\n * var poly = turf.polygon([[\n * [-81, 41],\n * [-81, 47],\n * [-72, 47],\n * [-72, 41],\n * [-81, 41]\n * ]]);\n *\n * turf.inside(pt, poly);\n * //= true\n */\nmodule.exports = function (point, polygon, ignoreBoundary) {\n // validation\n if (!point) throw new Error('point is required');\n if (!polygon) throw new Error('polygon is required');\n\n var pt = getCoord(point);\n var polys = getCoords(polygon);\n var type = (polygon.geometry) ? polygon.geometry.type : polygon.type;\n var bbox = polygon.bbox;\n\n // Quick elimination if point is not inside bbox\n if (bbox && inBBox(pt, bbox) === false) return false;\n\n // normalize to multipolygon\n if (type === 'Polygon') polys = [polys];\n\n for (var i = 0, insidePoly = false; i < polys.length && !insidePoly; i++) {\n // check if it is in the outer ring first\n if (inRing(pt, polys[i][0], ignoreBoundary)) {\n var inHole = false;\n var k = 1;\n // check for the point in any of the holes\n while (k < polys[i].length && !inHole) {\n if (inRing(pt, polys[i][k], !ignoreBoundary)) {\n inHole = true;\n }\n k++;\n }\n if (!inHole) insidePoly = true;\n }\n }\n return insidePoly;\n};\n\n/**\n * inRing\n *\n * @private\n * @param {[number, number]} pt [x,y]\n * @param {Array<[number, number]>} ring [[x,y], [x,y],..]\n * @param {boolean} ignoreBoundary ignoreBoundary\n * @returns {boolean} inRing\n */\nfunction inRing(pt, ring, ignoreBoundary) {\n var isInside = false;\n if (ring[0][0] === ring[ring.length - 1][0] && ring[0][1] === ring[ring.length - 1][1]) ring = ring.slice(0, ring.length - 1);\n\n for (var i = 0, j = ring.length - 1; i < ring.length; j = i++) {\n var xi = ring[i][0], yi = ring[i][1];\n var xj = ring[j][0], yj = ring[j][1];\n var onBoundary = (pt[1] * (xi - xj) + yi * (xj - pt[0]) + yj * (pt[0] - xi) === 0) &&\n ((xi - pt[0]) * (xj - pt[0]) <= 0) && ((yi - pt[1]) * (yj - pt[1]) <= 0);\n if (onBoundary) return !ignoreBoundary;\n var intersect = ((yi > pt[1]) !== (yj > pt[1])) &&\n (pt[0] < (xj - xi) * (pt[1] - yi) / (yj - yi) + xi);\n if (intersect) isInside = !isInside;\n }\n return isInside;\n}\n\n/**\n * inBBox\n *\n * @private\n * @param {[number, number]} pt point [x,y]\n * @param {[number, number, number, number]} bbox BBox [west, south, east, north]\n * @returns {boolean} true/false if point is inside BBox\n */\nfunction inBBox(pt, bbox) {\n return bbox[0] <= pt[0] &&\n bbox[1] <= pt[1] &&\n bbox[2] >= pt[0] &&\n bbox[3] >= pt[1];\n}\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/@turf/inside/index.js\n// module id = 11\n// module chunks = 0","/**\n * Unwrap a coordinate from a Point Feature, Geometry or a single coordinate.\n *\n * @name getCoord\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var pt = turf.point([10, 10]);\n *\n * var coord = turf.getCoord(pt);\n * //= [10, 10]\n */\nfunction getCoord(obj) {\n if (!obj) throw new Error('obj is required');\n\n var coordinates = getCoords(obj);\n\n // getCoord() must contain at least two numbers (Point)\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return coordinates;\n } else {\n throw new Error('Coordinate is not a valid Point');\n }\n}\n\n/**\n * Unwrap coordinates from a Feature, Geometry Object or an Array of numbers\n *\n * @name getCoords\n * @param {Array|Geometry|Feature} obj Object\n * @returns {Array} coordinates\n * @example\n * var poly = turf.polygon([[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]);\n *\n * var coord = turf.getCoords(poly);\n * //= [[[119.32, -8.7], [119.55, -8.69], [119.51, -8.54], [119.32, -8.7]]]\n */\nfunction getCoords(obj) {\n if (!obj) throw new Error('obj is required');\n var coordinates;\n\n // Array of numbers\n if (obj.length) {\n coordinates = obj;\n\n // Geometry Object\n } else if (obj.coordinates) {\n coordinates = obj.coordinates;\n\n // Feature\n } else if (obj.geometry && obj.geometry.coordinates) {\n coordinates = obj.geometry.coordinates;\n }\n // Checks if coordinates contains a number\n if (coordinates) {\n containsNumber(coordinates);\n return coordinates;\n }\n throw new Error('No valid coordinates');\n}\n\n/**\n * Checks if coordinates contains a number\n *\n * @name containsNumber\n * @param {Array} coordinates GeoJSON Coordinates\n * @returns {boolean} true if Array contains a number\n */\nfunction containsNumber(coordinates) {\n if (coordinates.length > 1 &&\n typeof coordinates[0] === 'number' &&\n typeof coordinates[1] === 'number') {\n return true;\n }\n\n if (Array.isArray(coordinates[0]) && coordinates[0].length) {\n return containsNumber(coordinates[0]);\n }\n throw new Error('coordinates must only contain numbers');\n}\n\n/**\n * Enforce expectations about types of GeoJSON objects for Turf.\n *\n * @name geojsonType\n * @param {GeoJSON} value any GeoJSON object\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction geojsonType(value, type, name) {\n if (!type || !name) throw new Error('type and name required');\n\n if (!value || value.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + value.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link Feature} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name featureOf\n * @param {Feature} feature a feature with an expected geometry type\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} error if value is not the expected type.\n */\nfunction featureOf(feature, type, name) {\n if (!feature) throw new Error('No feature passed');\n if (!name) throw new Error('.featureOf() requires a name');\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n}\n\n/**\n * Enforce expectations about types of {@link FeatureCollection} inputs for Turf.\n * Internally this uses {@link geojsonType} to judge geometry types.\n *\n * @name collectionOf\n * @param {FeatureCollection} featureCollection a FeatureCollection for which features will be judged\n * @param {string} type expected GeoJSON type\n * @param {string} name name of calling function\n * @throws {Error} if value is not the expected type.\n */\nfunction collectionOf(featureCollection, type, name) {\n if (!featureCollection) throw new Error('No featureCollection passed');\n if (!name) throw new Error('.collectionOf() requires a name');\n if (!featureCollection || featureCollection.type !== 'FeatureCollection') {\n throw new Error('Invalid input to ' + name + ', FeatureCollection required');\n }\n for (var i = 0; i < featureCollection.features.length; i++) {\n var feature = featureCollection.features[i];\n if (!feature || feature.type !== 'Feature' || !feature.geometry) {\n throw new Error('Invalid input to ' + name + ', Feature with geometry required');\n }\n if (!feature.geometry || feature.geometry.type !== type) {\n throw new Error('Invalid input to ' + name + ': must be a ' + type + ', given ' + feature.geometry.type);\n }\n }\n}\n\n/**\n * Get Geometry from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {Geometry|null} GeoJSON Geometry Object\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeom(point)\n * //={\"type\": \"Point\", \"coordinates\": [110, 40]}\n */\nfunction getGeom(geojson) {\n if (!geojson) throw new Error('geojson is required');\n if (geojson.geometry !== undefined) return geojson.geometry;\n if (geojson.coordinates || geojson.geometries) return geojson;\n throw new Error('geojson must be a valid Feature or Geometry Object');\n}\n\n/**\n * Get Geometry Type from Feature or Geometry Object\n *\n * @param {Feature|Geometry} geojson GeoJSON Feature or Geometry Object\n * @returns {string} GeoJSON Geometry Type\n * @throws {Error} if geojson is not a Feature or Geometry Object\n * @example\n * var point = {\n * \"type\": \"Feature\",\n * \"properties\": {},\n * \"geometry\": {\n * \"type\": \"Point\",\n * \"coordinates\": [110, 40]\n * }\n * }\n * var geom = turf.getGeomType(point)\n * //=\"Point\"\n */\nfunction getGeomType(geojson) {\n if (!geojson) throw new Error('geojson is required');\n var geom = getGeom(geojson);\n if (geom) return geom.type;\n}\n\nmodule.exports = {\n geojsonType: geojsonType,\n collectionOf: collectionOf,\n featureOf: featureOf,\n getCoord: getCoord,\n getCoords: getCoords,\n containsNumber: containsNumber,\n getGeom: getGeom,\n getGeomType: getGeomType\n};\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ../~/@turf/invariant/index.js\n// module id = 12\n// module chunks = 0","// base\nimport Vector from './Vector.js';\nwindow.L.Vector = Vector;\n\nimport Cell from './Cell.js';\nwindow.L.Cell = Cell;\n\nimport Field from './Field.js';\nwindow.L.Field = Field;\n\nimport ScalarField from './ScalarField.js';\nwindow.L.ScalarField = ScalarField;\n\nimport VectorField from './VectorField.js';\nwindow.L.VectorField = VectorField;\n\n// layer\nrequire('./layer/L.CanvasLayer.js');\nrequire('./layer/L.CanvasLayer.SimpleLonLat.js');\nrequire('./layer/L.CanvasLayer.Field.js');\nrequire('./layer/L.CanvasLayer.ScalarField.js');\nrequire('./layer/L.CanvasLayer.VectorFieldAnim.js');\n\n// control\nrequire('./control/L.Control.ColorBar.js');\n\n/* eslint-disable no-console */\nconsole.log('leaflet.canvaslayer.field v1.4.0');\n/* eslint-enable no-console */\n\n\n\n// WEBPACK FOOTER //\n// ./_main.js"],"sourceRoot":""} \ No newline at end of file diff --git a/docs/example_ScalarField_Mask.html b/docs/example_ScalarField_Mask.html new file mode 100644 index 0000000..8855e7b --- /dev/null +++ b/docs/example_ScalarField_Mask.html @@ -0,0 +1,96 @@ + + + + + ScalarField / Mask + + + + + + + + +

ScalarField Mask

+
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/_main.js b/src/_main.js index 937bcbe..9d4430e 100644 --- a/src/_main.js +++ b/src/_main.js @@ -25,5 +25,5 @@ require('./layer/L.CanvasLayer.VectorFieldAnim.js'); require('./control/L.Control.ColorBar.js'); /* eslint-disable no-console */ -console.log('leaflet.canvaslayer.field v1.4.0 in progress...'); +console.log('leaflet.canvaslayer.field v1.4.0'); /* eslint-enable no-console */