Add routing option to draw line
This commit is contained in:
parent
e95e7699f6
commit
ab7bbbe34d
@ -1,5 +1,6 @@
|
||||
### Change Log for Node-RED Worldmap
|
||||
|
||||
- v2.6.0 - Add route capability to draw line when online
|
||||
- v2.5.9 - Fix handling of multiple hulls, tidy contextmenu handling
|
||||
- v2.5.8 - Let node name be the full page map title
|
||||
- v2.5.7 - Let fillColor set color of hulls
|
||||
|
10
README.md
10
README.md
@ -11,6 +11,7 @@ map web page for plotting "things" on.
|
||||
|
||||
### Updates
|
||||
|
||||
- v2.6.0 - Add route capability to draw line when online
|
||||
- v2.5.9 - Fix handling of multiple hulls, tidy contextmenu handling
|
||||
- v2.5.8 - Let node name be the full page map title
|
||||
- v2.5.7 - Let fillColor set color of hulls
|
||||
@ -111,18 +112,19 @@ There are also several special icons...
|
||||
#### NATO Symbology
|
||||
|
||||
You can use NATO symbols from <a href="https://github.com/spatialillusions/milsymbol" target="mapinfo">milsymbol.js</a>.
|
||||
To do this you need to supply a `msg.SIDC` instead of an icon, for example:
|
||||
To do this you need to supply a `msg.payload.SIDC` instead of an icon, for example:
|
||||
|
||||
msg.payload = { "name": "Emergency Medical Operation",
|
||||
msg.payload = {
|
||||
"name": "Emergency Medical Operation",
|
||||
"lat": 51.05,
|
||||
"lon": -1.35,
|
||||
"SIDC": "ENOPA-------",
|
||||
"options": { "fillOpacity":0.8 }
|
||||
"options": { "fillOpacity":0.8, "additionalInformation":"Extra info" }
|
||||
}
|
||||
|
||||
SIDC codes can be generated using the online tool - https://spatialillusions.com/unitgenerator/
|
||||
|
||||
There are lots of extra options you can specify as `msg.options` - see the <a href="https://github.com/spatialillusions/milsymbol/tree/master/docs" target="mapinfo">milsymbol docs here</a>.
|
||||
There are lots of extra options you can specify as `msg.payload.options` - see the <a href="https://spatialillusions.com/milsymbol/documentation.html" target="mapinfo">milsymbol docs here</a>.
|
||||
|
||||
### Areas, Lines and Rectangles
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-contrib-web-worldmap",
|
||||
"version": "2.5.9",
|
||||
"version": "2.6.0",
|
||||
"description": "A Node-RED node to provide a web page of a world map for plotting things on.",
|
||||
"dependencies": {
|
||||
"cgi": "0.3.1",
|
||||
|
@ -143,7 +143,7 @@ then by default <code>⌘⇧m</code> - <code>ctrl-shift-m</code> will load the m
|
||||
<p>Icons of type <i>plane</i>, <i>ship</i>, <i>car</i>, <i>uav</i> or <i>arrow</i> will use built in SVG icons that align to the
|
||||
<code>bearing</code> value.</p>
|
||||
<p>Font Awesome (<a href="https://fontawesome.com/v4.7.0/icons/" target="_new">fa-icons 4.7</a>) can also be used, as can
|
||||
NATO symbology codes (SIDC), or <a href="https://github.com/dceejay/RedMap/blob/master/emojilist.md" target="_new">:emoji name:</a>,
|
||||
NATO symbology codes (<a href="https://spatialillusions.com/unitgenerator/">SIDC</a>), or <a href="https://github.com/dceejay/RedMap/blob/master/emojilist.md" target="_new">:emoji name:</a>,
|
||||
or the url of a small icon image (32x32)</p>
|
||||
<p>See the <a href="https://www.npmjs.com/package/node-red-contrib-web-worldmap" target="_new">README</a> for further
|
||||
details and examples of icons and commands for drawing <b>lines</b> and <b>areas</b>, and to <b>add layers</b> and
|
||||
|
@ -764,15 +764,6 @@ basemaps["Watercolor"] = L.tileLayer(watercolorUrl, {
|
||||
|
||||
// Now add the overlays
|
||||
|
||||
// Add the countries (world-110m) for offline use
|
||||
var customTopoLayer = L.geoJson(null, {clickable:false, style: {color:"blue", weight:2, fillColor:"#cf6", fillOpacity:0.04}});
|
||||
layers["_countries"] = omnivore.topojson('images/world-50m-flat.json',null,customTopoLayer);
|
||||
overlays["countries"] = layers["_countries"];
|
||||
|
||||
// Add the day/night overlay
|
||||
layers["_daynight"] = new L.LayerGroup();
|
||||
overlays["day/night"] = layers["_daynight"];
|
||||
|
||||
// Add the drawing layer for fun...
|
||||
layers["_drawing"] = new L.FeatureGroup();
|
||||
overlays["drawing"] = layers["_drawing"];
|
||||
@ -837,10 +828,100 @@ map.on('draw:created', function (e) {
|
||||
layers["_drawing"].addLayer(shape.layer);
|
||||
|
||||
var rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\",true);'>Edit points</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
|
||||
if (e.layer.options.fill === false && navigator.onLine) {
|
||||
rightmenuMarker = L.popup({offset:[0,-12]}).setContent("<input type='text' autofocus value='"+name+"' id='dinput' placeholder='name (,icon, layer)'/><br/><button onclick='editPoly(\""+name+"\",true);'>Edit points</button><button onclick='delMarker(\""+name+"\",true);'>Delete</button><button onclick='sendRoute(\""+name+"\");'>Route</button><button onclick='sendDrawing(\""+name+"\");'>OK</button>");
|
||||
}
|
||||
rightmenuMarker.setLatLng(cent);
|
||||
setTimeout(function() {map.openPopup(rightmenuMarker)},25);
|
||||
});
|
||||
|
||||
|
||||
var defaultOptions = function () {
|
||||
var options = {};
|
||||
options.precision = 5;
|
||||
options.factor = Math.pow(10, options.precision);
|
||||
options.dimension = 2;
|
||||
return options;
|
||||
};
|
||||
|
||||
var decode = function (encoded, options) {
|
||||
options = defaultOptions(options);
|
||||
var flatPoints = decodeDeltas(encoded);
|
||||
var points = [];
|
||||
for (var i = 0, len = flatPoints.length; i + (options.dimension - 1) < len;) {
|
||||
var point = [];
|
||||
for (var dim = 0; dim < options.dimension; ++dim) {
|
||||
point.push(flatPoints[i++]);
|
||||
}
|
||||
points.push(point);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
var decodeDeltas = function (encoded, options) {
|
||||
options = defaultOptions(options);
|
||||
var lastNumbers = [];
|
||||
var numbers = decodeFloats(encoded, options);
|
||||
for (var i = 0, len = numbers.length; i < len;) {
|
||||
for (var d = 0; d < options.dimension; ++d, ++i) {
|
||||
numbers[i] = Math.round((lastNumbers[d] = numbers[i] + (lastNumbers[d] || 0)) * options.factor) / options.factor;
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
var decodeFloats = function (encoded, options) {
|
||||
options = defaultOptions(options);
|
||||
var numbers = decodeSignedIntegers(encoded);
|
||||
for (var i = 0, len = numbers.length; i < len; ++i) {
|
||||
numbers[i] /= options.factor;
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
var decodeSignedIntegers = function (encoded) {
|
||||
var numbers = decodeUnsignedIntegers(encoded);
|
||||
for (var i = 0, len = numbers.length; i < len; ++i) {
|
||||
var num = numbers[i];
|
||||
numbers[i] = (num & 1) ? ~(num >> 1) : (num >> 1);
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
var decodeUnsignedIntegers = function (encoded) {
|
||||
var numbers = [];
|
||||
var current = 0;
|
||||
var shift = 0;
|
||||
for (var i = 0, len = encoded.length; i < len; ++i) {
|
||||
var b = encoded.charCodeAt(i) - 63;
|
||||
current |= (b & 0x1f) << shift;
|
||||
if (b < 0x20) {
|
||||
numbers.push(current);
|
||||
current = 0;
|
||||
shift = 0;
|
||||
} else {
|
||||
shift += 5;
|
||||
}
|
||||
}
|
||||
return numbers;
|
||||
}
|
||||
|
||||
var sendRoute = function(n) {
|
||||
var p = (polygons[n]._latlngs.map(function(x) {
|
||||
return x.lng+","+x.lat;
|
||||
})).join(';');
|
||||
|
||||
fetch('https://router.project-osrm.org/route/v1/driving/'+p)
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
if (data.code !== "Ok") { sendDrawing(n); }
|
||||
var r = decode(data.routes[0].geometry).map( x => L.latLng(x[0],x[1]) );
|
||||
polygons[n]._latlngs = r;
|
||||
shape.m.line = r;
|
||||
sendDrawing(n);
|
||||
});
|
||||
}
|
||||
|
||||
var sendDrawing = function(n) {
|
||||
var thing = document.getElementById('dinput').value;
|
||||
map.closePopup();
|
||||
@ -854,6 +935,15 @@ var sendDrawing = function(n) {
|
||||
ws.send(JSON.stringify(shape.m));
|
||||
}
|
||||
|
||||
// Add the countries (world-110m) for offline use
|
||||
var customTopoLayer = L.geoJson(null, {clickable:false, style: {color:"blue", weight:2, fillColor:"#cf6", fillOpacity:0.04}});
|
||||
layers["_countries"] = omnivore.topojson('images/world-50m-flat.json',null,customTopoLayer);
|
||||
overlays["countries"] = layers["_countries"];
|
||||
|
||||
// Add the day/night overlay
|
||||
layers["_daynight"] = new L.LayerGroup();
|
||||
overlays["day/night"] = layers["_daynight"];
|
||||
|
||||
// Add the heatmap layer
|
||||
var heat = L.heatLayer([], {radius:60, gradient:{0.2:'blue', 0.4:'lime', 0.6:'red', 0.8:'yellow', 1:'white'}});
|
||||
layers["_heat"] = new L.LayerGroup().addLayer(heat);
|
||||
|
Loading…
Reference in New Issue
Block a user