From 0e6382d450c22139fd1099efaf62c2c506b3c2d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Velarde?= Date: Thu, 12 Oct 2017 00:32:09 +0200 Subject: [PATCH] Preparing minor release 1.3.4 --- CHANGELOG.md | 5 ++++- dist/leaflet.canvaslayer.field.js | 2 +- dist/leaflet.canvaslayer.field.js.map | 2 +- docs/dist/leaflet.canvaslayer.field.js | 2 +- package.json | 2 +- src/_main.js | 2 +- 6 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efaade3..9248ba1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,4 +39,7 @@ #v1.3.3 - Fixed some problems when dealing with 0-360º rasters [wrong wrapped value + interpolation artifact at first column (see v1.2.1)]. - Build: added karma to run jasmine tests (instead of previous manual mode) and webpack-dev-server. -- Minor: deleted unused L.ColorScale class + little adjustments in examples. \ No newline at end of file +- Minor: deleted unused L.ColorScale class + little adjustments in examples. + +#v1.3.4 +- Fixed 'RangeError: Maximum call stack size exceeded', when loading some big ASCII Grid files. \ No newline at end of file diff --git a/dist/leaflet.canvaslayer.field.js b/dist/leaflet.canvaslayer.field.js index 010ccc1..2dc8188 100644 --- a/dist/leaflet.canvaslayer.field.js +++ b/dist/leaflet.canvaslayer.field.js @@ -1,2 +1,2 @@ -!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=11)}([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=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")}}(),a=function(){function t(t,e){for(var n=0;n=360,this.longitudeNeedsToBeWrapped=this.xurCorner>180,this._inFilter=null}return a(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<=a,l=e>=this.yllCorner&&e<=this.yurCorner;return s&&l}},{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=o(n,2),r=i[0],a=i[1];return this.interpolatedValueAtIndexes(r,a)}},{key:"interpolatedValueAtIndexes",value:function(t,e){var n=this._getFourSurroundingIndexes(t,e),i=o(n,4),r=i[0],a=i[1],s=i[2],l=i[3],u=this._getFourSurroundingValues(r,a,s,l);if(u){var h=o(u,4),c=h[0],f=h[1],d=h[2],v=h[3];return this._doInterpolation(t-r,e-s,c,f,d,v)}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=o(n,2),r=i[0],a=i[1],s=Math.floor(r),l=Math.floor(a),u=this._clampColumnIndex(s),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=s},function(t,e,n){"use strict";function i(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e1&&void 0!==arguments[1]?arguments[1]:1,r=t.split("\n");e._checkIsValidASCIIGridHeader(r);for(var o=/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/,a=parseFloat(r[4].match(o)),s={nCols:parseInt(r[0].match(o)),nRows:parseInt(r[1].match(o)),xllCorner:parseFloat(r[2].match(o)),yllCorner:parseFloat(r[3].match(o)),cellXSize:a,cellYSize:a},l=r[5].toUpperCase().replace("NODATA_VALUE","").trim(),u=[],h=6;h1&&void 0!==arguments[1]?arguments[1]:0,i=GeoTIFF.parse(t),r=i.getImage(),o=r.readRasters(),a=r.getTiePoints()[0],s=r.getFileDirectory(),u=l(s.ModelPixelScale,2),h=u[0],c=u[1],f=o[n];if(s.GDAL_NODATA){var d=parseFloat(s.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})}}]),u(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;e3&&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=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")}}(),a=function(){function t(t,e){for(var n=0;n=360,this.longitudeNeedsToBeWrapped=this.xurCorner>180,this._inFilter=null}return a(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<=a,l=e>=this.yllCorner&&e<=this.yurCorner;return s&&l}},{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=o(n,2),r=i[0],a=i[1];return this.interpolatedValueAtIndexes(r,a)}},{key:"interpolatedValueAtIndexes",value:function(t,e){var n=this._getFourSurroundingIndexes(t,e),i=o(n,4),r=i[0],a=i[1],s=i[2],l=i[3],u=this._getFourSurroundingValues(r,a,s,l);if(u){var h=o(u,4),c=h[0],f=h[1],d=h[2],v=h[3];return this._doInterpolation(t-r,e-s,c,f,d,v)}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=o(n,2),r=i[0],a=i[1],s=Math.floor(r),l=Math.floor(a),u=this._clampColumnIndex(s),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=s},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;e 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);\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 * 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 }\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 * 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\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 var _getWrappedLongitudes4 = this._getWrappedLongitudes(),\n _getWrappedLongitudes5 = _slicedToArray(_getWrappedLongitudes4, 2),\n xmin = _getWrappedLongitudes5[0],\n xmax = _getWrappedLongitudes5[1];\n\n //let longitudeIn = this.isContinuous ? true : (lon >= xmin && lon <= xmax);\n\n\n var longitudeIn = lon >= xmin && lon <= xmax;\n var latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n\n return longitudeIn && latitudeIn;\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 _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\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 var values = items.map(function (it) {\n return it !== noDataValue ? parseFloat(it * scaleFactor) : null;\n });\n zs.push.apply(zs, _toConsumableArray(values));\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, __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.3.3 in progress...');\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 = 11);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap 3f6dd16acb41f814dcc6","/**\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';\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 }\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 * 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\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n contains(lon, lat) {\n let [xmin, xmax] = this._getWrappedLongitudes();\n\n //let longitudeIn = this.isContinuous ? true : (lon >= xmin && lon <= xmax);\n let longitudeIn = lon >= xmin && lon <= xmax;\n let latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n\n return longitudeIn && latitudeIn;\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 let values = items.map(it => {\n return it !== noDataValue ? parseFloat(it * scaleFactor) : null;\n });\n zs.push(...values);\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","// 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.3.3 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 be06f2089b8372745479","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:///./_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__","_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","range","_calculateRange","stride","cells","j","_lonLatAtIndexes2","_lonLatAtIndexes","_lonLatAtIndexes3","lon","_valueAtIndexes","f","_updateRange","_getWrappedLongitudes2","_getWrappedLongitudes","_getWrappedLongitudes3","xmin","xmax","_getWrappedLongitudes4","_getWrappedLongitudes5","longitudeIn","latitudeIn","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","pt","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","__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 = 11);\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);\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 * 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 }\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 * 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\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 var _getWrappedLongitudes4 = this._getWrappedLongitudes(),\n _getWrappedLongitudes5 = _slicedToArray(_getWrappedLongitudes4, 2),\n xmin = _getWrappedLongitudes5[0],\n xmax = _getWrappedLongitudes5[1];\n\n //let longitudeIn = this.isContinuous ? true : (lon >= xmin && lon <= xmax);\n\n\n var longitudeIn = lon >= xmin && lon <= xmax;\n var latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n\n return longitudeIn && latitudeIn;\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, __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.3.4');\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 = 11);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap be06f2089b8372745479","/**\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';\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 }\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 * 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\n * @param {Number} lon - longitude\n * @param {Number} lat - latitude\n * @returns {Boolean}\n */\n contains(lon, lat) {\n let [xmin, xmax] = this._getWrappedLongitudes();\n\n //let longitudeIn = this.isContinuous ? true : (lon >= xmin && lon <= xmax);\n let longitudeIn = lon >= xmin && lon <= xmax;\n let latitudeIn = lat >= this.yllCorner && lat <= this.yurCorner;\n\n return longitudeIn && latitudeIn;\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","// 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.3.4');\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/dist/leaflet.canvaslayer.field.js b/docs/dist/leaflet.canvaslayer.field.js index 010ccc1..2dc8188 100644 --- a/docs/dist/leaflet.canvaslayer.field.js +++ b/docs/dist/leaflet.canvaslayer.field.js @@ -1,2 +1,2 @@ -!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=11)}([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=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")}}(),a=function(){function t(t,e){for(var n=0;n=360,this.longitudeNeedsToBeWrapped=this.xurCorner>180,this._inFilter=null}return a(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<=a,l=e>=this.yllCorner&&e<=this.yurCorner;return s&&l}},{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=o(n,2),r=i[0],a=i[1];return this.interpolatedValueAtIndexes(r,a)}},{key:"interpolatedValueAtIndexes",value:function(t,e){var n=this._getFourSurroundingIndexes(t,e),i=o(n,4),r=i[0],a=i[1],s=i[2],l=i[3],u=this._getFourSurroundingValues(r,a,s,l);if(u){var h=o(u,4),c=h[0],f=h[1],d=h[2],v=h[3];return this._doInterpolation(t-r,e-s,c,f,d,v)}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=o(n,2),r=i[0],a=i[1],s=Math.floor(r),l=Math.floor(a),u=this._clampColumnIndex(s),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=s},function(t,e,n){"use strict";function i(t){if(Array.isArray(t)){for(var e=0,n=Array(t.length);e1&&void 0!==arguments[1]?arguments[1]:1,r=t.split("\n");e._checkIsValidASCIIGridHeader(r);for(var o=/-?(?:0|[1-9]\d*)(?:\.\d*)?(?:[eE][+\-]?\d+)?/,a=parseFloat(r[4].match(o)),s={nCols:parseInt(r[0].match(o)),nRows:parseInt(r[1].match(o)),xllCorner:parseFloat(r[2].match(o)),yllCorner:parseFloat(r[3].match(o)),cellXSize:a,cellYSize:a},l=r[5].toUpperCase().replace("NODATA_VALUE","").trim(),u=[],h=6;h1&&void 0!==arguments[1]?arguments[1]:0,i=GeoTIFF.parse(t),r=i.getImage(),o=r.readRasters(),a=r.getTiePoints()[0],s=r.getFileDirectory(),u=l(s.ModelPixelScale,2),h=u[0],c=u[1],f=o[n];if(s.GDAL_NODATA){var d=parseFloat(s.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})}}]),u(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;e3&&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=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")}}(),a=function(){function t(t,e){for(var n=0;n=360,this.longitudeNeedsToBeWrapped=this.xurCorner>180,this._inFilter=null}return a(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<=a,l=e>=this.yllCorner&&e<=this.yurCorner;return s&&l}},{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=o(n,2),r=i[0],a=i[1];return this.interpolatedValueAtIndexes(r,a)}},{key:"interpolatedValueAtIndexes",value:function(t,e){var n=this._getFourSurroundingIndexes(t,e),i=o(n,4),r=i[0],a=i[1],s=i[2],l=i[3],u=this._getFourSurroundingValues(r,a,s,l);if(u){var h=o(u,4),c=h[0],f=h[1],d=h[2],v=h[3];return this._doInterpolation(t-r,e-s,c,f,d,v)}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=o(n,2),r=i[0],a=i[1],s=Math.floor(r),l=Math.floor(a),u=this._clampColumnIndex(s),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=s},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;e