node-red-contrib-web-worldmap 2.21.3 → 2.21.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,8 @@
1
1
  ### Change Log for Node-RED Worldmap
2
2
 
3
+ - v2.21.7 - Let SIDC/icon short code be only 4 chars long
4
+ - v2.21.5 - Fix handling of "old" ship nav to ship navigation
5
+ - v2.21.4 - Fix speed leader length. Add transparentPixels option.
3
6
  - v2.21.3 - Add zoom to bounds action. Adjust map layers max zoom levels.
4
7
  - v2.21.2 - Expand ship nav to ship navigation.
5
8
  - v2.21.1 - Fix ui check callback to not use .
package/README.md CHANGED
@@ -11,6 +11,9 @@ map web page for plotting "things" on.
11
11
 
12
12
  ### Updates
13
13
 
14
+ - v2.21.7 - Let SIDC/icon short code be only 4 chars long
15
+ - v2.21.5 - Fix handling of "old" ship nav to ship navigation
16
+ - v2.21.4 - Fix speed leader length. Add transparentPixels option..
14
17
  - v2.21.3 - Add zoom to bounds action. Adjust map layers max zoom levels.
15
18
  - v2.21.2 - Expand ship nav to ship navigation.
16
19
  - v2.21.1 - Fix ui check callback to not use .
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "node-red-contrib-web-worldmap",
3
- "version": "2.21.3",
3
+ "version": "2.21.7",
4
4
  "description": "A Node-RED node to provide a web page of a world map for plotting things on.",
5
5
  "dependencies": {
6
6
  "@turf/bezier-spline": "~6.5.0",
@@ -24,7 +24,7 @@ a {
24
24
  }
25
25
 
26
26
  .leaflet-interactive:hover {
27
- filter: opacity(0.5);
27
+ filter: opacity(0.7);
28
28
  }
29
29
 
30
30
  .topbar {
@@ -72,6 +72,7 @@
72
72
  <script src="leaflet/leaflet.latlng-graticule.js"></script>
73
73
  <script src="leaflet/VectorTileLayer.umd.min.js"></script>
74
74
  <script src="leaflet/Semicircle.js"></script>
75
+ <script src="leaflet/L.TileLayer.PixelFilter.js"></script>
75
76
  <script src="leaflet/dialog-polyfill.js"></script>
76
77
 
77
78
  <script src="images/emoji.js"></script>
@@ -0,0 +1,152 @@
1
+ /*
2
+ * L.TileLayer.PixelFilter
3
+ * https://github.com/greeninfo/L.TileLayer.PixelFilter
4
+ * http://greeninfo-network.github.io/L.TileLayer.PixelFilter/
5
+ */
6
+ L.tileLayerPixelFilter = function (url, options) {
7
+ return new L.TileLayer.PixelFilter(url, options);
8
+ }
9
+
10
+ L.TileLayer.PixelFilter = L.TileLayer.extend({
11
+ // the constructor saves settings and throws a fit if settings are bad, as typical
12
+ // then adds the all-important 'tileload' event handler which basically "detects" an unmodified tile and performs the pxiel-swap
13
+ initialize: function (url, options) {
14
+ options = L.extend({}, L.TileLayer.prototype.options, {
15
+ matchRGBA: null,
16
+ missRGBA: null,
17
+ pixelCodes: [],
18
+ crossOrigin: 'Anonymous', // per issue 15, this is how you do it in Leaflet 1.x
19
+ }, options);
20
+ L.TileLayer.prototype.initialize.call(this, url, options);
21
+ L.setOptions(this, options);
22
+
23
+ // go ahead and save our settings
24
+ this.setMatchRGBA(this.options.matchRGBA);
25
+ this.setMissRGBA(this.options.missRGBA);
26
+ this.setPixelCodes(this.options.pixelCodes);
27
+
28
+ // and add our tile-load event hook which triggers us to do the pixel-swap
29
+ this.on('tileload', function (event) {
30
+ this.applyFiltersToTile(event.tile);
31
+ });
32
+ },
33
+
34
+ // settings setters
35
+ setMatchRGBA: function (rgba) {
36
+ // save the setting
37
+ if (rgba !== null && (typeof rgba !== 'object' || typeof rgba.length !== 'number' || rgba.length !== 4) ) throw "L.TileLayer.PixelSwap expected matchRGBA to be RGBA [r,g,b,a] array or else null";
38
+ this.options.matchRGBA = rgba;
39
+
40
+ // force a redraw, which means new tiles, which mean new tileload events; the circle of life
41
+ this.redraw(true);
42
+ },
43
+ setMissRGBA: function (rgba) {
44
+ // save the setting
45
+ if (rgba !== null && (typeof rgba !== 'object' || typeof rgba.length !== 'number' || rgba.length !== 4) ) throw "L.TileLayer.PixelSwap expected missRGBA to be RGBA [r,g,b,a] array or else null";
46
+ this.options.missRGBA = rgba;
47
+
48
+ // force a redraw, which means new tiles, which mean new tileload events; the circle of life
49
+ this.redraw(true);
50
+ },
51
+ setPixelCodes: function (pixelcodes) {
52
+ // save the setting
53
+ if (typeof pixelcodes !== 'object' || typeof pixelcodes.length !== 'number') throw "L.TileLayer.PixelSwap expected pixelCodes to be a list of triplets: [ [r,g,b], [r,g,b], ... ]";
54
+ this.options.pixelCodes = pixelcodes;
55
+
56
+ // force a redraw, which means new tiles, which mean new tileload events; the circle of life
57
+ this.redraw(true);
58
+ },
59
+
60
+ // extend the _createTile function to add the .crossOrigin attribute, since loading tiles from a separate service is a pretty common need
61
+ // and the Canvas is paranoid about cross-domain image data. see issue #5
62
+ // this is really only for Leaflet 0.7; as of 1.0 L.TileLayer has a crossOrigin setting which we define as a layer option
63
+ _createTile: function () {
64
+ var tile = L.TileLayer.prototype._createTile.call(this);
65
+ tile.crossOrigin = "Anonymous";
66
+ return tile;
67
+ },
68
+
69
+ // the heavy lifting to do the pixel-swapping
70
+ // called upon 'tileload' and passed the IMG element
71
+ // tip: when the tile is saved back to the IMG element that counts as a tileload event too! thus an infinite loop, as wel as comparing the pixelCodes against already-replaced pixels!
72
+ // so, we tag the already-swapped tiles so we know when to quit
73
+ // if the layer is redrawn, it's a new IMG element and that means it would not yet be tagged
74
+ applyFiltersToTile: function (imgelement) {
75
+ // already processed, see note above
76
+ if (imgelement.getAttribute('data-PixelFilterDone')) return;
77
+
78
+ // copy the image data onto a canvas for manipulation
79
+ var width = imgelement.width;
80
+ var height = imgelement.height;
81
+ var canvas = document.createElement("canvas");
82
+ canvas.width = width;
83
+ canvas.height = height;
84
+ var context = canvas.getContext("2d");
85
+ context.drawImage(imgelement, 0, 0);
86
+
87
+ // create our target imagedata
88
+ var output = context.createImageData(width, height);
89
+
90
+ // extract out our RGBA trios into separate numbers, so we don't have to use rgba[i] a zillion times
91
+ var matchRGBA = this.options.matchRGBA, missRGBA = this.options.missRGBA;
92
+ if (matchRGBA !== null) {
93
+ var match_r = matchRGBA[0], match_g = matchRGBA[1], match_b = matchRGBA[2], match_a = matchRGBA[3];
94
+ }
95
+ if (missRGBA !== null) {
96
+ var miss_r = missRGBA[0], miss_g = missRGBA[1], miss_b = missRGBA[2], miss_a = missRGBA[3];
97
+ }
98
+
99
+ // go over our pixel-code list and generate the list of integers that we'll use for RGB matching
100
+ // 1000000*R + 1000*G + B = 123123123 which is an integer, and finding an integer inside an array is a lot faster than finding an array inside an array
101
+ var pixelcodes = [];
102
+ for (var i=0, l=this.options.pixelCodes.length; i<l; i++) {
103
+ var value = 1000000 * this.options.pixelCodes[i][0] + 1000 * this.options.pixelCodes[i][1] + this.options.pixelCodes[i][2];
104
+ pixelcodes.push(value);
105
+ }
106
+
107
+ // iterate over the pixels (each one is 4 bytes, RGBA)
108
+ // and see if they are on our list (recall the "addition" thing so we're comparing integers in an array for performance)
109
+ // per issue #5 catch a failure here, which is likely a cross-domain problem
110
+ try {
111
+ var pixels = context.getImageData(0, 0, width, height).data;
112
+ } catch(e) {
113
+ throw "L.TileLayer.PixelFilter getImageData() failed. Likely a cross-domain issue?";
114
+ }
115
+ for(var i = 0, n = pixels.length; i < n; i += 4) {
116
+ var r = pixels[i ];
117
+ var g = pixels[i+1];
118
+ var b = pixels[i+2];
119
+ var a = pixels[i+3];
120
+
121
+ // bail condition: if the alpha is 0 then it's already transparent, likely nodata, and we should skip it
122
+ if (a == 0) {
123
+ output.data[i ] = 255;
124
+ output.data[i+1] = 255;
125
+ output.data[i+2] = 255;
126
+ output.data[i+3] = 0;
127
+ continue;
128
+ }
129
+
130
+ // default to matching, so that if we are not in fact filtering by code it's an automatic hit
131
+ // number matching trick: 1000000*R + 1000*G + 1*B = 123,123,123 a simple number that either is or isn't on the list
132
+ var match = true;
133
+ if (pixelcodes.length) {
134
+ var sum = 1000000 * r + 1000 * g + b;
135
+ if (-1 === pixelcodes.indexOf(sum)) match = false;
136
+ }
137
+
138
+ // did it match? either way we push a R, a G, and a B onto the image blob
139
+ // if the target RGBA is a null, then we push exactly the same RGBA as we found in the source pixel
140
+ output.data[i ] = match ? (matchRGBA===null ? r : match_r) : (missRGBA===null ? r : miss_r);
141
+ output.data[i+1] = match ? (matchRGBA===null ? g : match_g) : (missRGBA===null ? g : miss_g);
142
+ output.data[i+2] = match ? (matchRGBA===null ? b : match_b) : (missRGBA===null ? b : miss_b);
143
+ output.data[i+3] = match ? (matchRGBA===null ? a : match_a) : (missRGBA===null ? a : miss_a);
144
+ }
145
+
146
+ // write the image back to the canvas, and assign its base64 back into the on-screen tile to visualize the change
147
+ // tag the tile as having already been updated, so we don't process a 'load' event again and re-process a tile that surely won't match any target RGB codes, in an infinite loop!
148
+ context.putImageData(output, 0, 0);
149
+ imgelement.setAttribute('data-PixelFilterDone', true);
150
+ imgelement.src = canvas.toDataURL();
151
+ }
152
+ });
@@ -1 +1 @@
1
- "use strict";L.DomUtil.setTransform||(L.DomUtil.setTransform=function(t,n,e){var i=n||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(e?" scale("+e+")":"")}),L.CanvasLayer=(L.Layer?L.Layer:L.Class).extend({initialize:function(t){this._map=null,this._canvas=null,this._frame=null,this._delegate=null,L.setOptions(this,t)},delegate:function(t){return this._delegate=t,this},needRedraw:function(){return this._frame||(this._frame=L.Util.requestAnimFrame(this.drawLayer,this)),this},_onLayerDidResize:function(t){this._canvas.width=t.newSize.x,this._canvas.height=t.newSize.y},_onLayerDidMove:function(){var t=this._map.containerPointToLayerPoint([0,0]);L.DomUtil.setPosition(this._canvas,t),this.drawLayer()},getEvents:function(){var t={resize:this._onLayerDidResize,moveend:this._onLayerDidMove};return this._map.options.zoomAnimation&&L.Browser.any3d&&(t.zoomanim=this._animateZoom),t},onAdd:function(t){this._map=t,this._canvas=L.DomUtil.create("canvas","leaflet-layer"),this.tiles={};var n=this._map.getSize();this._canvas.width=n.x,this._canvas.height=n.y;var e=this._map.options.zoomAnimation&&L.Browser.any3d;L.DomUtil.addClass(this._canvas,"leaflet-zoom-"+(e?"animated":"hide")),this.options.pane.appendChild(this._canvas),t.on(this.getEvents(),this);var i=this._delegate||this;i.onLayerDidMount&&i.onLayerDidMount(),this.needRedraw();var o=this;setTimeout(function(){o._onLayerDidMove()},0)},onRemove:function(t){var n=this._delegate||this;n.onLayerWillUnmount&&n.onLayerWillUnmount(),this.options.pane.removeChild(this._canvas),t.off(this.getEvents(),this),this._canvas=null},addTo:function(t){return t.addLayer(this),this},drawLayer:function(){var t=this._map.getSize(),n=this._map.getBounds(),e=this._map.getZoom(),i=this._map.options.crs.project(this._map.getCenter()),o=this._map.options.crs.project(this._map.containerPointToLatLng(this._map.getSize())),a=this._delegate||this;a.onDrawLayer&&a.onDrawLayer({layer:this,canvas:this._canvas,bounds:n,size:t,zoom:e,center:i,corner:o}),this._frame=null},_setTransform:function(t,n,e){var i=n||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(e?" scale("+e+")":"")},_animateZoom:function(t){var n=this._map.getZoomScale(t.zoom),e=L.Layer?this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(),t.zoom,t.center):this._map._getCenterOffset(t.center)._multiplyBy(-n).subtract(this._map._getMapPanePos());L.DomUtil.setTransform(this._canvas,e,n)}}),L.canvasLayer=function(t){return new L.CanvasLayer(t)},L.Control.Velocity=L.Control.extend({options:{position:"bottomleft",emptyString:"Unavailable",angleConvention:"bearingCCW",showCardinal:!1,speedUnit:"m/s",directionString:"Direction",speedString:"Speed",onAdd:null,onRemove:null},onAdd:function(t){return this._container=L.DomUtil.create("div","leaflet-control-velocity"),L.DomEvent.disableClickPropagation(this._container),t.on("mousemove",this._onMouseMove,this),this._container.innerHTML=this.options.emptyString,this.options.leafletVelocity.options.onAdd&&this.options.leafletVelocity.options.onAdd(),this._container},onRemove:function(t){t.off("mousemove",this._onMouseMove,this),this.options.leafletVelocity.options.onRemove&&this.options.leafletVelocity.options.onRemove()},vectorToSpeed:function(t,n,e){var i=Math.sqrt(Math.pow(t,2)+Math.pow(n,2));return"k/h"===e?this.meterSec2kilometerHour(i):"kt"===e?this.meterSec2Knots(i):i},vectorToDegrees:function(t,n,e){e.endsWith("CCW")&&(n=0<n?n=-n:Math.abs(n));var i=Math.sqrt(Math.pow(t,2)+Math.pow(n,2)),o=180*Math.atan2(t/i,n/i)/Math.PI+180;return"bearingCW"!==e&&"meteoCCW"!==e||360<=(o+=180)&&(o-=360),o},degreesToCardinalDirection:function(t){var n="";return 0<=t&&t<11.25||348.75<=t?n="N":11.25<=t&&t<33.75?n="NNW":33.75<=t&&t<56.25?n="NW":56.25<=t&&t<78.75?n="WNW":78.25<=t&&t<101.25?n="W":101.25<=t&&t<123.75?n="WSW":123.75<=t&&t<146.25?n="SW":146.25<=t&&t<168.75?n="SSW":168.75<=t&&t<191.25?n="S":191.25<=t&&t<213.75?n="SSE":213.75<=t&&t<236.25?n="SE":236.25<=t&&t<258.75?n="ESE":258.75<=t&&t<281.25?n="E":281.25<=t&&t<303.75?n="ENE":303.75<=t&&t<326.25?n="NE":326.25<=t&&t<348.75&&(n="NNE"),n},meterSec2Knots:function(t){return t/.514},meterSec2kilometerHour:function(t){return 3.6*t},_onMouseMove:function(t){var n=this.options.leafletVelocity._map.containerPointToLatLng(L.point(t.containerPoint.x,t.containerPoint.y)),e=this.options.leafletVelocity._windy.interpolatePoint(n.lng,n.lat),i="";if(e&&!isNaN(e[0])&&!isNaN(e[1])&&e[2]){var o=this.vectorToDegrees(e[0],e[1],this.options.angleConvention),a=this.options.showCardinal?" (".concat(this.degreesToCardinalDirection(o),")"):"";i="<strong> ".concat(this.options.velocityType," ").concat(this.options.directionString,": </strong> ").concat(o.toFixed(2),"°").concat(a,", <strong> ").concat(this.options.speedString,": </strong> ").concat(this.vectorToSpeed(e[0],e[1],this.options.speedUnit).toFixed(2)," ").concat(this.options.speedUnit)}else i=this.options.emptyString;this._container.innerHTML=i}}),L.Map.mergeOptions({positionControl:!1}),L.Map.addInitHook(function(){this.options.positionControl&&(this.positionControl=new L.Control.MousePosition,this.addControl(this.positionControl))}),L.control.velocity=function(t){return new L.Control.Velocity(t)},L.VelocityLayer=(L.Layer?L.Layer:L.Class).extend({options:{displayValues:!0,displayOptions:{velocityType:"Velocity",position:"bottomleft",emptyString:"No velocity data"},maxVelocity:10,colorScale:null,data:null},_map:null,_canvasLayer:null,_windy:null,_context:null,_timer:0,_mouseControl:null,initialize:function(t){L.setOptions(this,t)},onAdd:function(t){this._paneName=this.options.paneName||"overlayPane";var n=t._panes.overlayPane;t.getPane&&(n=(n=t.getPane(this._paneName))||t.createPane(this._paneName)),this._canvasLayer=L.canvasLayer({pane:n}).delegate(this),this._canvasLayer.addTo(t),this._map=t},onRemove:function(t){this._destroyWind()},setData:function(t){this.options.data=t,this._windy&&(this._windy.setData(t),this._clearAndRestart()),this.fire("load")},setOpacity:function(t){console.log("this._canvasLayer",this._canvasLayer),this._canvasLayer.setOpacity(t)},setOptions:function(t){this.options=Object.assign(this.options,t),t.hasOwnProperty("displayOptions")&&(this.options.displayOptions=Object.assign(this.options.displayOptions,t.displayOptions),this._initMouseHandler(!0)),t.hasOwnProperty("data")&&(this.options.data=t.data),this._windy&&(this._windy.setOptions(t),t.hasOwnProperty("data")&&this._windy.setData(t.data),this._clearAndRestart()),this.fire("load")},onDrawLayer:function(t,n){var e=this;this._windy?this.options.data&&(this._timer&&clearTimeout(e._timer),this._timer=setTimeout(function(){e._startWindy()},750)):this._initWindy(this)},_startWindy:function(){var t=this._map.getBounds(),n=this._map.getSize();this._windy.start([[0,0],[n.x,n.y]],n.x,n.y,[[t._southWest.lng,t._southWest.lat],[t._northEast.lng,t._northEast.lat]])},_initWindy:function(t){var n=Object.assign({canvas:t._canvasLayer._canvas,map:this._map},t.options);this._windy=new Windy(n),this._context=this._canvasLayer._canvas.getContext("2d"),this._canvasLayer._canvas.classList.add("velocity-overlay"),this.onDrawLayer(),this._map.on("dragstart",t._windy.stop),this._map.on("dragend",t._clearAndRestart),this._map.on("zoomstart",t._windy.stop),this._map.on("zoomend",t._clearAndRestart),this._map.on("resize",t._clearWind),this._initMouseHandler(!1)},_initMouseHandler:function(t){if(t&&(this._map.removeControl(this._mouseControl),this._mouseControl=!1),!this._mouseControl&&this.options.displayValues){var n=this.options.displayOptions||{};(n.leafletVelocity=this)._mouseControl=L.control.velocity(n).addTo(this._map)}},_clearAndRestart:function(){this._context&&this._context.clearRect(0,0,3e3,3e3),this._windy&&this._startWindy()},_clearWind:function(){this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3)},_destroyWind:function(){this._timer&&clearTimeout(this._timer),this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3),this._mouseControl&&this._map.removeControl(this._mouseControl),this._mouseControl=null,this._windy=null,this._map.removeLayer(this._canvasLayer)}}),L.velocityLayer=function(t){return new L.VelocityLayer(t)};var Windy=function(b){function o(t,n,e,i,o,a){var r=1-t,s=1-n,l=r*s,h=t*s,c=r*n,d=t*n,p=e[0]*l+i[0]*h+o[0]*c+a[0]*d,u=e[1]*l+i[1]*h+o[1]*c+a[1]*d;return[p,u,Math.sqrt(p*p+u*u)]}function d(t){var n=null,e=null;return t.forEach(function(t){switch(t.header.parameterCategory+","+t.header.parameterNumber){case"1,2":case"2,2":n=t;break;case"1,3":case"2,3":e=t;break;default:t}}),function(t,n){var e=t.data,i=n.data;return{header:t.header,data:function(t){return[e[t],i[t]]},interpolate:o}}(n,e)}function a(i,o,t){function a(t,n){var e=i[Math.round(t)];return e&&e[Math.round(n)]||h}a.release=function(){i=[]},a.randomize=function(t){for(var n,e,i=0;null===a(n=Math.round(Math.floor(Math.random()*o.width)+o.x),e=Math.round(Math.floor(Math.random()*o.height)+o.y))[2]&&i++<30;);return t.x=n,t.y=e,t},t(o,a)}function r(t){return t/180*Math.PI}function s(i,s){var n,e,l=(n=x,e=C,R.indexFor=function(t){return Math.max(0,Math.min(R.length-1,Math.round((t-n)/(e-n)*(R.length-1))))},R),h=l.map(function(){return[]}),t=Math.round(i.width*i.height*D);/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)&&(t*=T);for(var o="rgba(0, 0, 0, ".concat(O,")"),a=[],r=0;r<t;r++)a.push(s.randomize({age:Math.floor(Math.random()*P)+0}));var c=b.canvas.getContext("2d");c.lineWidth=S,c.fillStyle=o,c.globalAlpha=.6;var d=Date.now();!function t(){M=requestAnimationFrame(t);var n=Date.now(),e=n-d;W<e&&(d=n-e%W,h.forEach(function(t){t.length=0}),a.forEach(function(t){t.age>P&&(s.randomize(t).age=0);var n=t.x,e=t.y,i=s(n,e),o=i[2];if(null===o)t.age=P;else{var a=n+i[0],r=e+i[1];null!==s(a,r)[2]?(t.xt=a,t.yt=r,h[l.indexFor(o)].push(t)):(t.x=a,t.y=r)}t.age+=1}),c.globalCompositeOperation="destination-in",c.fillRect(i.x,i.y,i.width,i.height),c.globalCompositeOperation="lighter",c.globalAlpha=0===O?0:.9*O,h.forEach(function(t,n){0<t.length&&(c.beginPath(),c.strokeStyle=l[n],t.forEach(function(t){c.moveTo(t.x,t.y),c.lineTo(t.xt,t.yt),t.x=t.xt,t.y=t.yt}),c.stroke())}))}()}var u,m,p,y,_,f,v,g,w,M,x=b.minVelocity||0,C=b.maxVelocity||10,l=(b.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),P=b.particleAge||90,S=b.lineWidth||1,D=b.particleMultiplier||1/300,T=Math.pow(window.devicePixelRatio,1/3)||1.6,n=b.frameRate||15,W=1e3/n,O=.97,R=b.colorScale||["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"],h=[NaN,NaN,null],c=b.data,N=function(t,n){if(!m)return null;var e,i=z(t-y,360)/f,o=(_-n)/v,a=Math.floor(i),r=a+1,s=Math.floor(o),l=s+1;if(e=m[s]){var h=e[a],c=e[r];if(A(h)&&A(c)&&(e=m[l])){var d=e[a],p=e[r];if(A(d)&&A(p))return u.interpolate(i-a,o-s,h,c,d,p)}}return null},A=function(t){return null!=t},z=function(t,n){return t-n*Math.floor(t/n)},E=function(t,n,e,i,o){var a=2*Math.PI,r=n<0?5:-5,s=e<0?5:-5,l=V(e,n+r),h=V(e+s,n),c=Math.cos(e/360*a);return[(l[0]-i)/r/c,(l[1]-o)/r/c,(h[0]-i)/s,(h[1]-o)/s]},V=function(t,n,e){var i=b.map.latLngToContainerPoint(L.latLng(t,n));return[i.x,i.y]},U=function(){F.field&&F.field.release(),M&&cancelAnimationFrame(M)},F={params:b,start:function(n,e,i,t){var o={south:r(t[0][1]),north:r(t[1][1]),east:r(t[1][0]),west:r(t[0][0]),width:e,height:i};U(),function(t,n){var e=!0;t.length<2&&(e=!1),e||console.log("Windy Error: data must have at least two components (u,v)");var i=(u=d(t)).header;if(i.hasOwnProperty("gridDefinitionTemplate")&&0!=i.gridDefinitionTemplate&&(e=!1),e||console.log("Windy Error: Only data with Latitude_Longitude coordinates is supported"),e=!0,y=i.lo1,_=i.la1,f=i.dx,v=i.dy,g=i.nx,w=i.ny,i.hasOwnProperty("scanMode")){var o=i.scanMode.toString(2),a=(o=("0"+o).slice(-8)).split("").map(Number).map(Boolean);a[0]&&(f=-f),a[1]&&(v=-v),a[2]&&(e=!1),a[3]&&(e=!1),a[4]&&(e=!1),a[5]&&(e=!1),a[6]&&(e=!1),a[7]&&(e=!1),e||console.log("Windy Error: Data with scanMode: "+i.scanMode+" is not supported.")}(p=new Date(i.refTime)).setHours(p.getHours()+i.forecastTime),m=[];for(var r=0,s=360<=Math.floor(g*f),l=0;l<w;l++){for(var h=[],c=0;c<g;c++,r++)h[c]=u.data(r);s&&h.push(h[0]),m[l]=h}n({date:p,interpolate:N})}(c,function(t){!function(w,M,t,e){var x={},n=(t.south-t.north)*(t.west-t.east),C=l*Math.pow(n,.4),P=[],i=M.x;function o(t){for(var n,e,i,o,a,r,s,l,h,c,d,p,u,m=[],y=M.y;y<=M.yMax;y+=2){var _=(d=t,p=y,void 0,[(u=b.map.containerPointToLatLng(L.point(d,p))).lng,u.lat]),f=_[0],v=_[1];if(isFinite(f)){var g=w.interpolate(f,v);g&&(n=x,e=f,i=v,o=t,a=y,r=C,void 0,l=(s=g)[0]*r,h=s[1]*r,c=E(n,e,i,o,a),s[0]=c[0]*l+c[2]*h,s[1]=c[1]*l+c[3]*h,g=s,m[y+1]=m[y]=g)}}P[t+1]=P[t]=m}!function t(){for(var n=Date.now();i<M.width;)if(o(i),i+=2,1e3<Date.now()-n)return void setTimeout(t,25);a(P,M,e)}()}(t,function(t,n,e){var i=t[0],o=t[1],a=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],n),n-1);return{x:a,y:r,xMax:n,yMax:Math.min(Math.ceil(o[1],e),e-1),width:n,height:e}}(n,e,i),o,function(t,n){F.field=n,s(t,n)})})},stop:U,createField:a,interpolatePoint:N,setData:function(t){c=t},setOptions:function(t){t.hasOwnProperty("minVelocity")&&(x=t.minVelocity),t.hasOwnProperty("maxVelocity")&&(C=t.maxVelocity),t.hasOwnProperty("velocityScale")&&(l=(t.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),t.hasOwnProperty("particleAge")&&(P=t.particleAge),t.hasOwnProperty("lineWidth")&&(S=t.lineWidth),t.hasOwnProperty("particleMultiplier")&&(D=t.particleMultiplier),t.hasOwnProperty("opacity")&&(O=+t.opacity),t.hasOwnProperty("frameRate")&&(n=t.frameRate),W=1e3/n}};return F};window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)});
1
+ "use strict";L.DomUtil.setTransform||(L.DomUtil.setTransform=function(t,e,n){var i=e||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(n?" scale("+n+")":"")}),L.CanvasLayer=(L.Layer?L.Layer:L.Class).extend({initialize:function(t){this._map=null,this._canvas=null,this._frame=null,this._delegate=null,L.setOptions(this,t)},delegate:function(t){return this._delegate=t,this},needRedraw:function(){return this._frame||(this._frame=L.Util.requestAnimFrame(this.drawLayer,this)),this},_onLayerDidResize:function(t){this._canvas.width=t.newSize.x,this._canvas.height=t.newSize.y},_onLayerDidMove:function(){var t=this._map.containerPointToLayerPoint([0,0]);L.DomUtil.setPosition(this._canvas,t),this.drawLayer()},getEvents:function(){var t={resize:this._onLayerDidResize,moveend:this._onLayerDidMove};return this._map.options.zoomAnimation&&L.Browser.any3d&&(t.zoomanim=this._animateZoom),t},onAdd:function(t){console.log("canvas onAdd",this),this._map=t,this._canvas=L.DomUtil.create("canvas","leaflet-layer"),this.tiles={};var e=this._map.getSize();this._canvas.width=e.x,this._canvas.height=e.y;var n=this._map.options.zoomAnimation&&L.Browser.any3d;L.DomUtil.addClass(this._canvas,"leaflet-zoom-"+(n?"animated":"hide")),this.options.pane.appendChild(this._canvas),t.on(this.getEvents(),this);var i=this._delegate||this;i.onLayerDidMount&&i.onLayerDidMount(),this.needRedraw();var o=this;setTimeout(function(){o._onLayerDidMove()},0)},onRemove:function(t){var e=this._delegate||this;e.onLayerWillUnmount&&e.onLayerWillUnmount(),this.options.pane.removeChild(this._canvas),t.off(this.getEvents(),this),this._canvas=null},addTo:function(t){return t.addLayer(this),this},drawLayer:function(){var t=this._map.getSize(),e=this._map.getBounds(),n=this._map.getZoom(),i=this._map.options.crs.project(this._map.getCenter()),o=this._map.options.crs.project(this._map.containerPointToLatLng(this._map.getSize())),a=this._delegate||this;a.onDrawLayer&&a.onDrawLayer({layer:this,canvas:this._canvas,bounds:e,size:t,zoom:n,center:i,corner:o}),this._frame=null},_setTransform:function(t,e,n){var i=e||new L.Point(0,0);t.style[L.DomUtil.TRANSFORM]=(L.Browser.ie3d?"translate("+i.x+"px,"+i.y+"px)":"translate3d("+i.x+"px,"+i.y+"px,0)")+(n?" scale("+n+")":"")},_animateZoom:function(t){var e=this._map.getZoomScale(t.zoom),n=L.Layer?this._map._latLngToNewLayerPoint(this._map.getBounds().getNorthWest(),t.zoom,t.center):this._map._getCenterOffset(t.center)._multiplyBy(-e).subtract(this._map._getMapPanePos());L.DomUtil.setTransform(this._canvas,n,e)}}),L.canvasLayer=function(t){return new L.CanvasLayer(t)},L.Control.Velocity=L.Control.extend({options:{position:"bottomleft",emptyString:"Unavailable",angleConvention:"bearingCCW",showCardinal:!1,speedUnit:"m/s",directionString:"Direction",speedString:"Speed",onAdd:null,onRemove:null},onAdd:function(t){return this._container=L.DomUtil.create("div","leaflet-control-velocity"),L.DomEvent.disableClickPropagation(this._container),t.on("mousemove",this._onMouseMove,this),this._container.innerHTML=this.options.emptyString,this.options.leafletVelocity.options.onAdd&&this.options.leafletVelocity.options.onAdd(),this._container},onRemove:function(t){t.off("mousemove",this._onMouseMove,this),this.options.leafletVelocity.options.onRemove&&this.options.leafletVelocity.options.onRemove()},vectorToSpeed:function(t,e,n){var i=Math.sqrt(Math.pow(t,2)+Math.pow(e,2));return"k/h"===n?this.meterSec2kilometerHour(i):"kt"===n?this.meterSec2Knots(i):"mph"===n?this.meterSec2milesHour(i):i},vectorToDegrees:function(t,e,n){n.endsWith("CCW")&&(e=0<e?e=-e:Math.abs(e));var i=Math.sqrt(Math.pow(t,2)+Math.pow(e,2)),o=180*Math.atan2(t/i,e/i)/Math.PI+180;return"bearingCW"!==n&&"meteoCCW"!==n||360<=(o+=180)&&(o-=360),o},degreesToCardinalDirection:function(t){var e="";return 0<=t&&t<11.25||348.75<=t?e="N":11.25<=t&&t<33.75?e="NNW":33.75<=t&&t<56.25?e="NW":56.25<=t&&t<78.75?e="WNW":78.25<=t&&t<101.25?e="W":101.25<=t&&t<123.75?e="WSW":123.75<=t&&t<146.25?e="SW":146.25<=t&&t<168.75?e="SSW":168.75<=t&&t<191.25?e="S":191.25<=t&&t<213.75?e="SSE":213.75<=t&&t<236.25?e="SE":236.25<=t&&t<258.75?e="ESE":258.75<=t&&t<281.25?e="E":281.25<=t&&t<303.75?e="ENE":303.75<=t&&t<326.25?e="NE":326.25<=t&&t<348.75&&(e="NNE"),e},meterSec2Knots:function(t){return t/.514},meterSec2kilometerHour:function(t){return 3.6*t},meterSec2milesHour:function(t){return 2.23694*t},_onMouseMove:function(t){var e=this.options.leafletVelocity._map.containerPointToLatLng(L.point(t.containerPoint.x,t.containerPoint.y)),n=this.options.leafletVelocity._windy.interpolatePoint(e.lng,e.lat),i="";if(n&&!isNaN(n[0])&&!isNaN(n[1])&&n[2]){var o=this.vectorToDegrees(n[0],n[1],this.options.angleConvention),a=this.options.showCardinal?" (".concat(this.degreesToCardinalDirection(o),") "):"";i="<strong> ".concat(this.options.velocityType," ").concat(this.options.directionString,": </strong> ").concat(o.toFixed(2),"°").concat(a,", <strong> ").concat(this.options.velocityType," ").concat(this.options.speedString,": </strong> ").concat(this.vectorToSpeed(n[0],n[1],this.options.speedUnit).toFixed(2)," ").concat(this.options.speedUnit)}else i=this.options.emptyString;this._container.innerHTML=i}}),L.Map.mergeOptions({positionControl:!1}),L.Map.addInitHook(function(){this.options.positionControl&&(this.positionControl=new L.Control.MousePosition,this.addControl(this.positionControl))}),L.control.velocity=function(t){return new L.Control.Velocity(t)},L.VelocityLayer=(L.Layer?L.Layer:L.Class).extend({options:{displayValues:!0,displayOptions:{velocityType:"Velocity",position:"bottomleft",emptyString:"No velocity data"},maxVelocity:10,colorScale:null,data:null},_map:null,_canvasLayer:null,_windy:null,_context:null,_timer:0,_mouseControl:null,initialize:function(t){L.setOptions(this,t)},onAdd:function(t){this._paneName=this.options.paneName||"overlayPane";var e=t._panes.overlayPane;t.getPane&&(e=(e=t.getPane(this._paneName))||t.createPane(this._paneName)),this._canvasLayer=L.canvasLayer({pane:e}).delegate(this),this._canvasLayer.addTo(t),this._map=t},onRemove:function(t){this._destroyWind()},setData:function(t){this.options.data=t,this._windy&&(this._windy.setData(t),this._clearAndRestart()),this.fire("load")},setOpacity:function(t){console.log("this._canvasLayer",this._canvasLayer),this._canvasLayer.setOpacity(t)},setOptions:function(t){this.options=Object.assign(this.options,t),t.hasOwnProperty("displayOptions")&&(this.options.displayOptions=Object.assign(this.options.displayOptions,t.displayOptions),this._initMouseHandler(!0)),t.hasOwnProperty("data")&&(this.options.data=t.data),this._windy&&(this._windy.setOptions(t),t.hasOwnProperty("data")&&this._windy.setData(t.data),this._clearAndRestart()),this.fire("load")},onDrawLayer:function(t,e){var n=this;this._windy?this.options.data&&(this._timer&&clearTimeout(n._timer),this._timer=setTimeout(function(){n._startWindy()},750)):this._initWindy(this)},_startWindy:function(){var t=this._map.getBounds(),e=this._map.getSize();this._windy.start([[0,0],[e.x,e.y]],e.x,e.y,[[t._southWest.lng,t._southWest.lat],[t._northEast.lng,t._northEast.lat]])},_initWindy:function(t){var e=Object.assign({canvas:t._canvasLayer._canvas,map:this._map},t.options);this._windy=new Windy(e),this._context=this._canvasLayer._canvas.getContext("2d"),this._canvasLayer._canvas.classList.add("velocity-overlay"),this.onDrawLayer(),this._map.on("dragstart",t._windy.stop),this._map.on("dragend",t._clearAndRestart),this._map.on("zoomstart",t._windy.stop),this._map.on("zoomend",t._clearAndRestart),this._map.on("resize",t._clearWind),this._initMouseHandler(!1)},_initMouseHandler:function(t){if(t&&(this._map.removeControl(this._mouseControl),this._mouseControl=!1),!this._mouseControl&&this.options.displayValues){var e=this.options.displayOptions||{};(e.leafletVelocity=this)._mouseControl=L.control.velocity(e).addTo(this._map)}},_clearAndRestart:function(){this._context&&this._context.clearRect(0,0,3e3,3e3),this._windy&&this._startWindy()},_clearWind:function(){this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3)},_destroyWind:function(){this._timer&&clearTimeout(this._timer),this._windy&&this._windy.stop(),this._context&&this._context.clearRect(0,0,3e3,3e3),this._mouseControl&&this._map.removeControl(this._mouseControl),this._mouseControl=null,this._windy=null,this._map.removeLayer(this._canvasLayer)}}),L.velocityLayer=function(t){return new L.VelocityLayer(t)};var Windy=function(S){function o(t,e,n,i,o,a){var r=1-t,s=1-e,l=r*s,h=t*s,c=r*e,d=t*e,p=n[0]*l+i[0]*h+o[0]*c+a[0]*d,u=n[1]*l+i[1]*h+o[1]*c+a[1]*d;return[p,u,Math.sqrt(p*p+u*u)]}function d(t){var e=null,n=null;return t.forEach(function(t){switch(t.header.parameterCategory+","+t.header.parameterNumber){case"1,2":case"2,2":e=t;break;case"1,3":case"2,3":n=t;break;default:t}}),function(t,e){var n=t.data,i=e.data;return{header:t.header,data:function(t){return[n[t],i[t]]},interpolate:o}}(e,n)}function a(i,o,t){function a(t,e){var n=i[Math.round(t)];return n&&n[Math.round(e)]||h}a.release=function(){i=[]},a.randomize=function(t){for(var e,n,i=0;null===a(e=Math.round(Math.floor(Math.random()*o.width)+o.x),n=Math.round(Math.floor(Math.random()*o.height)+o.y))[2]&&i++<30;);return t.x=e,t.y=n,t},t(o,a)}function r(t){return t/180*Math.PI}function s(i,s){var e,n,l=(e=x,n=C,R.indexFor=function(t){return Math.max(0,Math.min(R.length-1,Math.round((t-e)/(n-e)*(R.length-1))))},R),h=l.map(function(){return[]}),t=Math.round(i.width*i.height*D);/android|blackberry|iemobile|ipad|iphone|ipod|opera mini|webos/i.test(navigator.userAgent)&&(t*=T);for(var o="rgba(0, 0, 0, ".concat(O,")"),a=[],r=0;r<t;r++)a.push(s.randomize({age:Math.floor(Math.random()*P)+0}));var c=S.canvas.getContext("2d");c.lineWidth=b,c.fillStyle=o,c.globalAlpha=.6;var d=Date.now();!function t(){M=requestAnimationFrame(t);var e=Date.now(),n=e-d;W<n&&(d=e-n%W,h.forEach(function(t){t.length=0}),a.forEach(function(t){t.age>P&&(s.randomize(t).age=0);var e=t.x,n=t.y,i=s(e,n),o=i[2];if(null===o)t.age=P;else{var a=e+i[0],r=n+i[1];null!==s(a,r)[2]?(t.xt=a,t.yt=r,h[l.indexFor(o)].push(t)):(t.x=a,t.y=r)}t.age+=1}),c.globalCompositeOperation="destination-in",c.fillRect(i.x,i.y,i.width,i.height),c.globalCompositeOperation="lighter",c.globalAlpha=0===O?0:.9*O,h.forEach(function(t,e){0<t.length&&(c.beginPath(),c.strokeStyle=l[e],t.forEach(function(t){c.moveTo(t.x,t.y),c.lineTo(t.xt,t.yt),t.x=t.xt,t.y=t.yt}),c.stroke())}))}()}var u,m,p,y,_,f,v,g,w,M,x=S.minVelocity||0,C=S.maxVelocity||10,l=(S.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1),P=S.particleAge||90,b=S.lineWidth||1,D=S.particleMultiplier||1/300,T=Math.pow(window.devicePixelRatio,1/3)||1.6,e=S.frameRate||15,W=1e3/e,O=.97,R=S.colorScale||["rgb(36,104, 180)","rgb(60,157, 194)","rgb(128,205,193 )","rgb(151,218,168 )","rgb(198,231,181)","rgb(238,247,217)","rgb(255,238,159)","rgb(252,217,125)","rgb(255,182,100)","rgb(252,150,75)","rgb(250,112,52)","rgb(245,64,32)","rgb(237,45,28)","rgb(220,24,32)","rgb(180,0,35)"],h=[NaN,NaN,null],c=S.data,N=function(t,e){if(!m)return null;var n,i=z(t-y,360)/f,o=(_-e)/v,a=Math.floor(i),r=a+1,s=Math.floor(o),l=s+1;if(n=m[s]){var h=n[a],c=n[r];if(A(h)&&A(c)&&(n=m[l])){var d=n[a],p=n[r];if(A(d)&&A(p))return u.interpolate(i-a,o-s,h,c,d,p)}}return null},A=function(t){return null!=t},z=function(t,e){return t-e*Math.floor(t/e)},E=function(t,e,n,i,o){var a=2*Math.PI,r=e<0?5:-5,s=n<0?5:-5,l=V(n,e+r),h=V(n+s,e),c=Math.cos(n/360*a);return[(l[0]-i)/r/c,(l[1]-o)/r/c,(h[0]-i)/s,(h[1]-o)/s]},V=function(t,e,n){var i=S.map.latLngToContainerPoint(L.latLng(t,e));return[i.x,i.y]},U=function(){F.field&&F.field.release(),M&&cancelAnimationFrame(M)},F={params:S,start:function(e,n,i,t){var o={south:r(t[0][1]),north:r(t[1][1]),east:r(t[1][0]),west:r(t[0][0]),width:n,height:i};U(),function(t,e){var n=!0;t.length<2&&(n=!1),n||console.log("Windy Error: data must have at least two components (u,v)");var i=(u=d(t)).header;if(i.hasOwnProperty("gridDefinitionTemplate")&&0!=i.gridDefinitionTemplate&&(n=!1),n||console.log("Windy Error: Only data with Latitude_Longitude coordinates is supported"),n=!0,y=i.lo1,_=i.la1,f=i.dx,v=i.dy,g=i.nx,w=i.ny,i.hasOwnProperty("scanMode")){var o=i.scanMode.toString(2),a=(o=("0"+o).slice(-8)).split("").map(Number).map(Boolean);a[0]&&(f=-f),a[1]&&(v=-v),a[2]&&(n=!1),a[3]&&(n=!1),a[4]&&(n=!1),a[5]&&(n=!1),a[6]&&(n=!1),a[7]&&(n=!1),n||console.log("Windy Error: Data with scanMode: "+i.scanMode+" is not supported.")}(p=new Date(i.refTime)).setHours(p.getHours()+i.forecastTime),m=[];for(var r=0,s=360<=Math.floor(g*f),l=0;l<w;l++){for(var h=[],c=0;c<g;c++,r++)h[c]=u.data(r);s&&h.push(h[0]),m[l]=h}e({date:p,interpolate:N})}(c,function(t){!function(w,M,t,n){var x={},e=(t.south-t.north)*(t.west-t.east),C=l*Math.pow(e,.4),P=[],i=M.x;function o(t){for(var e,n,i,o,a,r,s,l,h,c,d,p,u,m=[],y=M.y;y<=M.yMax;y+=2){var _=(d=t,p=y,void 0,[(u=S.map.containerPointToLatLng(L.point(d,p))).lng,u.lat]),f=_[0],v=_[1];if(isFinite(f)){var g=w.interpolate(f,v);g&&(e=x,n=f,i=v,o=t,a=y,r=C,void 0,l=(s=g)[0]*r,h=s[1]*r,c=E(e,n,i,o,a),s[0]=c[0]*l+c[2]*h,s[1]=c[1]*l+c[3]*h,g=s,m[y+1]=m[y]=g)}}P[t+1]=P[t]=m}!function t(){for(var e=Date.now();i<M.width;)if(o(i),i+=2,1e3<Date.now()-e)return void setTimeout(t,25);a(P,M,n)}()}(t,function(t,e,n){var i=t[0],o=t[1],a=Math.round(i[0]),r=Math.max(Math.floor(i[1],0),0);Math.min(Math.ceil(o[0],e),e-1);return{x:a,y:r,xMax:e,yMax:Math.min(Math.ceil(o[1],n),n-1),width:e,height:n}}(e,n,i),o,function(t,e){F.field=e,s(t,e)})})},stop:U,createField:a,interpolatePoint:N,setData:function(t){c=t},setOptions:function(t){t.hasOwnProperty("minVelocity")&&(x=t.minVelocity),t.hasOwnProperty("maxVelocity")&&(C=t.maxVelocity),t.hasOwnProperty("velocityScale")&&(l=(t.velocityScale||.005)*(Math.pow(window.devicePixelRatio,1/3)||1)),t.hasOwnProperty("particleAge")&&(P=t.particleAge),t.hasOwnProperty("lineWidth")&&(b=t.lineWidth),t.hasOwnProperty("particleMultiplier")&&(D=t.particleMultiplier),t.hasOwnProperty("opacity")&&(O=+t.opacity),t.hasOwnProperty("frameRate")&&(e=t.frameRate),W=1e3/e}};return F};window.cancelAnimationFrame||(window.cancelAnimationFrame=function(t){clearTimeout(t)});
@@ -110,7 +110,12 @@ var handleData = function(data) {
110
110
  }
111
111
  }
112
112
  if (data.command) { doCommand(data.command); delete data.command; }
113
- if (data.hasOwnProperty("type") && data.type.indexOf("Feature") === 0) { doGeojson("geojson",data); }
113
+ if (data.hasOwnProperty("type") && data.type.indexOf("Feature") === 0) {
114
+ if (data.hasOwnProperty('properties') && data.properties.hasOwnProperty('title')) {
115
+ doGeojson(data.properties.title,data)
116
+ }
117
+ else { doGeojson("geojson",data); }
118
+ }
114
119
  else if (data.hasOwnProperty("name")) { setMarker(data); }
115
120
  else {
116
121
  if (JSON.stringify(data) !== '{}') {
@@ -663,7 +668,7 @@ var addThing = function() {
663
668
  var colo = (bits[3] || "#910000").trim();
664
669
  var hdg = parseFloat(bits[4] || 0);
665
670
  var drag = true;
666
- var regi = /^[S,G,E,I,O][A-Z]{4}.*/i; // if it looks like a SIDC code
671
+ var regi = /^[S,G,E,I,O][A-Z]{3}.*/i; // if it looks like a SIDC code
667
672
  var d = {action:"point", name:bits[0].trim(), layer:lay, draggable:drag, lat:rclk.lat, lon:rclk.lng, hdg:hdg};
668
673
  if (regi.test(icon)) {
669
674
  d.SIDC = (icon.toUpperCase()+"------------").substr(0,12);
@@ -1778,8 +1783,9 @@ function setMarker(data) {
1778
1783
  opts.size = opts.size || sz;
1779
1784
  opts.size = opts.size * (opts.scale || 1);
1780
1785
  // escape out any isocodes eg flag symbols
1781
- var optfields = ["additionalInformation","higherFormation","specialHeadquarters","staffComments","type","uniqueDesignation","speed"];
1782
- const regex = /\p{Extended_Pictographic}/ug;
1786
+ var optfields = ["additionalInformation","higherFormation","specialHeadquarters","staffComments","type","uniqueDesignation","speed","country"];
1787
+ //const regex = /\p{Extended_Pictographic}/ug;
1788
+ const regex = /(\u00a9|\u00ae|[\u2000-\u3300]|\ud83c[\ud000-\udfff]|\ud83d[\ud000-\udfff]|\ud83e[\ud000-\udfff])/gi;
1783
1789
  optfields.forEach(function (item) {
1784
1790
  if (opts.hasOwnProperty(item) && regex.test(opts[item])) {
1785
1791
  opts[item] = unescape(encodeURIComponent(opts[item]));
@@ -1983,7 +1989,7 @@ function setMarker(data) {
1983
1989
  else if (data.heading !== undefined) { track = data.heading; }
1984
1990
  else if (data.bearing !== undefined) { track = data.bearing; }
1985
1991
  if (track != undefined) { // if there is a heading
1986
- if (data.speed != null && !data.length) { // and a speed - lets convert to a leader length
1992
+ if (data.speed != null && data.length === undefined) { // and a speed - lets convert to a leader length
1987
1993
  data.length = parseFloat(data.speed || "0") * 60;
1988
1994
  var re1 = new RegExp('kn|knot|kt','i');
1989
1995
  var re2 = new RegExp('kph|kmh','i');
@@ -1992,7 +1998,7 @@ function setMarker(data) {
1992
1998
  else if ( re2.test(""+data.speed) ) { data.length = data.length * 0.44704; }
1993
1999
  else if ( re3.test(""+data.speed) ) { data.length = data.length * 0.277778; }
1994
2000
  }
1995
- if (data.length != null) {
2001
+ if (data.length !== undefined) {
1996
2002
  if (polygons[data.name] != null && !polygons[data.name].hasOwnProperty("_layers")) {
1997
2003
  map.removeLayer(polygons[data.name]);
1998
2004
  }
@@ -2452,6 +2458,11 @@ function doCommand(cmd) {
2452
2458
  else if (cmd.map.url.slice(-4).toLowerCase() === ".pbf") {
2453
2459
  overlays[cmd.map.overlay] = VectorTileLayer(cmd.map.url, cmd.map.opt);
2454
2460
  }
2461
+ else if (cmd.map.hasOwnProperty("transparentPixels")) {
2462
+ cmd.map.opt.pixelCodes = cmd.map.transparentPixels;
2463
+ cmd.map.opt.matchRGBA = [ 0,0,0,0 ];
2464
+ overlays[cmd.map.overlay] = L.tileLayerPixelFilter(cmd.map.url, cmd.map.opt);
2465
+ }
2455
2466
  else {
2456
2467
  overlays[cmd.map.overlay] = L.tileLayer(cmd.map.url, cmd.map.opt);
2457
2468
  }
@@ -2503,6 +2514,8 @@ function doCommand(cmd) {
2503
2514
  // Turn on an existing overlay(s)
2504
2515
  if (cmd.hasOwnProperty("showlayer")) {
2505
2516
  if (typeof cmd.showlayer === "string") { cmd.showlayer = [ cmd.showlayer ]; }
2517
+ var sn = cmd.showlayer.indexOf("ship nav");
2518
+ if (sn !== -1) { cmd.showlayer[sn] = "ship navigation"; }
2506
2519
  for (var i=0; i < cmd.showlayer.length; i++) {
2507
2520
  if (overlays.hasOwnProperty(cmd.showlayer[i])) {
2508
2521
  map.addLayer(overlays[cmd.showlayer[i]]);
@@ -2512,6 +2525,8 @@ function doCommand(cmd) {
2512
2525
  // Turn off an existing overlay(s)
2513
2526
  if (cmd.hasOwnProperty("hidelayer")) {
2514
2527
  if (typeof cmd.hidelayer === "string") { cmd.hidelayer = [ cmd.hidelayer ]; }
2528
+ var sn = cmd.hidelayer.indexOf("ship nav");
2529
+ if (sn !== -1) { cmd.hidelayer[sn] = "ship navigation"; }
2515
2530
  for (var i=0; i < cmd.hidelayer.length; i++) {
2516
2531
  if (overlays.hasOwnProperty(cmd.hidelayer[i])) {
2517
2532
  map.removeLayer(overlays[cmd.hidelayer[i]]);
@@ -2566,6 +2581,7 @@ function doCommand(cmd) {
2566
2581
 
2567
2582
  // handle any incoming GEOJSON directly - may style badly
2568
2583
  function doGeojson(n,g,l,o) {
2584
+ //console.log("GEOJSON",n,g,l,o)
2569
2585
  var lay = l || g.name || "unknown";
2570
2586
  // if (!basemaps[lay]) {
2571
2587
  var opt = { style: function(feature) {
@@ -2597,12 +2613,29 @@ function doGeojson(n,g,l,o) {
2597
2613
  return st;
2598
2614
  }}
2599
2615
  opt.pointToLayer = function (feature, latlng) {
2600
- var myMarker = L.VectorMarkers.icon({
2601
- icon: feature.properties["marker-symbol"] || "circle",
2602
- markerColor: (feature.properties["marker-color"] || "#910000"),
2603
- prefix: 'fa',
2604
- iconColor: 'white'
2605
- });
2616
+ var myMarker;
2617
+ if (feature.properties.hasOwnProperty("SIDC")) {
2618
+ myMarker = new ms.Symbol( feature.properties.SIDC.toUpperCase(), {
2619
+ uniqueDesignation:unescape(encodeURIComponent(feature.properties.title)) ,
2620
+ country:feature.properties.country,
2621
+ direction:feature.properties.bearing,
2622
+ additionalInformation:feature.properties.modifier,
2623
+ size:24
2624
+ });
2625
+ myMarker = L.icon({
2626
+ iconUrl: myMarker.toDataURL(),
2627
+ iconAnchor: [myMarker.getAnchor().x, myMarker.getAnchor().y],
2628
+ className: "natoicon",
2629
+ });
2630
+ }
2631
+ else {
2632
+ myMarker = L.VectorMarkers.icon({
2633
+ icon: feature.properties["marker-symbol"] || "circle",
2634
+ markerColor: (feature.properties["marker-color"] || "#910000"),
2635
+ prefix: 'fa',
2636
+ iconColor: 'white'
2637
+ });
2638
+ }
2606
2639
  if (!feature.properties.hasOwnProperty("title")) {
2607
2640
  feature.properties.title = feature.properties["marker-symbol"];
2608
2641
  }
@@ -42,6 +42,7 @@
42
42
  <script src="leaflet/Leaflet.Coordinates.js"></script>
43
43
  <script src="leaflet/leaflet.latlng-graticule.js"></script>
44
44
  <script src="leaflet/Semicircle.js"></script>
45
+ <script src="leaflet/L.TileLayer.PixelFilter.js"></script>
45
46
  <script src="leaflet/dialog-polyfill.js"></script>
46
47
 
47
48
  <script src="images/emoji.js"></script>
package/worldmap.js CHANGED
@@ -151,13 +151,11 @@ module.exports = function(RED) {
151
151
  var height = config.height;
152
152
  if (height == 0) { height = 10; }
153
153
  var size = ui.getSizes();
154
- var frameWidth = (size.sx +size.cx) * width - size.cx;
155
- var frameHeight = (size.sy +size.cy) * height - size.cy;
154
+ var frameWidth = (size.sx + size.cx) * width - size.cx;
155
+ var frameHeight = (size.sy + size.cy) * height - size.cy;
156
156
  var url = encodeURI(config.path);
157
157
  var html = `<style>.nr-dashboard-ui_worldmap{padding:0;}</style><div style="overflow:hidden;">
158
- <iframe src="${url}" width="${frameWidth}px" height="${frameHeight}px" style="border:none;"></iframe>
159
- </div>
160
- `;
158
+ <iframe src="${url}" width="${frameWidth}px" height="${frameHeight}px" style="border:none;"></iframe></div>`;
161
159
  return html;
162
160
  }
163
161
 
@@ -219,7 +217,8 @@ module.exports = function(RED) {
219
217
  }
220
218
  setImmediate(function() { RED.nodes.registerType("ui_worldmap", UIWorldMap) });
221
219
  }
222
- }, 250);
220
+ }, 100);
221
+
223
222
 
224
223
  var WorldMapIn = function(n) {
225
224
  RED.nodes.createNode(this,n);
@@ -288,6 +287,7 @@ module.exports = function(RED) {
288
287
  }
289
288
  RED.nodes.registerType("worldmap in",WorldMapIn);
290
289
 
290
+
291
291
  var WorldMapTracks = function(n) {
292
292
  RED.nodes.createNode(this,n);
293
293
  this.depth = parseInt(Number(n.depth) || 20);
@@ -407,6 +407,7 @@ module.exports = function(RED) {
407
407
  }
408
408
  RED.nodes.registerType("worldmap-tracks",WorldMapTracks);
409
409
 
410
+
410
411
  var WorldMapHull = function(n) {
411
412
  RED.nodes.createNode(this,n);
412
413
  this.prop = n.prop || "layer";