Add range rings capability
This commit is contained in:
parent
ec4068c839
commit
9d904f5b10
@ -1,5 +1,6 @@
|
||||
### Change Log for Node-RED Worldmap
|
||||
|
||||
- v2.2.0 - Add rangering arcs function
|
||||
- v2.1.6 - Add legend command to allow inserting an html legend
|
||||
- v2.1.5 - Fix squawk icon color handling
|
||||
- v2.1.4 - Fix alt and speed as strings
|
||||
|
52
README.md
52
README.md
@ -1,7 +1,7 @@
|
||||
# node-red-contrib-web-worldmap
|
||||
|
||||
[![npm version](https://badge.fury.io/js/node-red-contrib-web-worldmap.svg)](https://badge.fury.io/js/node-red-contrib-web-worldmap)
|
||||
[![GitHub license](https://github.com/dceejay/redmap/blob/master/LICENSE)](https://img.shields.io/github/license/dceejay/redmap.svg)
|
||||
[![GitHub license](https://img.shields.io/github/license/dceejay/redmap.svg)](https://github.com/dceejay/redmap/blob/master/LICENSE)
|
||||
|
||||
A <a href="https://nodered.org" target="mapinfo">Node-RED</a> node to provide a world
|
||||
map web page for plotting "things" on.
|
||||
@ -10,6 +10,7 @@ map web page for plotting "things" on.
|
||||
|
||||
### Updates
|
||||
|
||||
- v2.2.0 - Add rangerings arcs function
|
||||
- v2.1.6 - Add legend command to allow inserting an html legend
|
||||
- v2.1.5 - Fix squawk icon color handling
|
||||
- v2.1.4 - Fix alt and speed as strings
|
||||
@ -17,27 +18,8 @@ map web page for plotting "things" on.
|
||||
- v2.1.2 - Fix layercontrol remove bug. Issue #116
|
||||
- v2.1.1 - fix bug in repeated add with polygon
|
||||
- v2.1.0 - add ui-worldmap node to make embedding in Dashboard easier. Let -in node specify connection actions only.
|
||||
- v2.0.22 - fix SIDC missing property
|
||||
- v2.0.21 - allow adding overlays without making them visible (visible:false). Issue #108
|
||||
- v2.0.20 - ensure `fit` option is boolean, Issue #109. Fix track layers, Issue #110.
|
||||
- v2.0.18 - Stop map contextmenu bleedthrough to marker. Add compress middleware.
|
||||
- v2.0.17 - Let clear command also clear tracks from tracks node
|
||||
- v2.0.16 - Revert use of ES6 import. Keep IE11 happy for while
|
||||
- v2.0.13 - Fix tracks colour.
|
||||
- v2.0.12 - Ensure default icon is in place if not specified (regression)
|
||||
- v2.0.9 - Only update maxage on screen once it exists
|
||||
- v2.0.8 - Drop beta flag, re-organise index, js and css files. Now using leaflet 1.4
|
||||
- v2.0.7-beta - Switch Ruler control to be independent of Draw library.
|
||||
- v2.0.6-beta - Re-enable editing of draw layer, add rectangles to lines and areas. Make individual objects editable.
|
||||
- v2.0.5-beta - Fix clustering on zoom (update old library)
|
||||
- v2.0.4-beta - Add helicopter icon. Correct Leaflet.Coordinates file name. Fix right contextmenu.
|
||||
- v2.0.3-beta - Let circles have popups. Better drawing of ellipses
|
||||
- v2.0.2-beta - Let lines and areas also have popups
|
||||
- v2.0.1-beta - Add optional graticule
|
||||
- v2.0.0-beta - Move to leaflet 1.4.x plus all plugins updated
|
||||
- ...
|
||||
|
||||
see [CHANGELOG](https://github.com/dceejay/RedMap/blob/master/CHANGELOG.md) for full list.
|
||||
- see [CHANGELOG](https://github.com/dceejay/RedMap/blob/master/CHANGELOG.md) for full list.
|
||||
|
||||
## Install
|
||||
|
||||
@ -45,7 +27,6 @@ Either use the Manage Palette option in the Node-RED Editor menu, or run the fol
|
||||
|
||||
npm i node-red-contrib-web-worldmap
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Plots "things" on a map. By default the map will be served from `{httpRoot}/worldmap`, but this
|
||||
@ -225,6 +206,7 @@ a number of degrees.
|
||||
|
||||
msg.payload = { "name":"Bristol Channel", "lat":51.5, "lon":-2.9, "radius":[30000,70000], "tilt":45 };
|
||||
|
||||
|
||||
### Options
|
||||
|
||||
Areas, Rectangles, Lines, Circles and Ellipses can also specify more optional properties:
|
||||
@ -242,6 +224,31 @@ Areas, Rectangles, Lines, Circles and Ellipses can also specify more optional pr
|
||||
|
||||
Other properties can be found in the leaflet documentation.
|
||||
|
||||
|
||||
### Arcs, Range Rings
|
||||
|
||||
You can add supplemental arc(s) to an icon by adding an **arc** property as below.
|
||||
Supplemental means that you can also specify a line using a **bearing** and **length** property.
|
||||
|
||||
```
|
||||
msg.payload = { name:"Camera01", icon:"fa-camera", lat:51.05, lon:-1.35,
|
||||
bearing: 235,
|
||||
length: 2200,
|
||||
arc: {
|
||||
ranges: [500,1000,2000],
|
||||
pan: 228,
|
||||
fov: 40,
|
||||
color: '#aaaa00'
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**ranges** can be a single number or an array of arc distances from the marker.
|
||||
The **pan** is the bearing of the centre of the arc, and the **fov** (Field of view)
|
||||
specifies the angle of the arc.
|
||||
Defaults are shown above.
|
||||
|
||||
|
||||
## Drawing
|
||||
|
||||
A single *right click* will allow you to add a point to the map - you must specify the `name` and optionally the `icon` and `layer`.
|
||||
@ -251,6 +258,7 @@ Right-clicking on an icon will allow you to delete it.
|
||||
If you select the **drawing** layer you can also add and edit polylines, polygons, rectangles and circles.
|
||||
Once an item is drawn you can right click to edit or delete it. Double click the object to exit edit mode.
|
||||
|
||||
|
||||
## Events from the map
|
||||
|
||||
The **worldmap in** node can be used to receive various events from the map. Examples of messages coming FROM the map include:
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-contrib-web-worldmap",
|
||||
"version": "2.1.6",
|
||||
"version": "2.2.0",
|
||||
"description": "A Node-RED node to provide a web page of a world map for plotting things on.",
|
||||
"dependencies": {
|
||||
"cgi": "0.3.1",
|
||||
|
@ -67,6 +67,7 @@
|
||||
<script src="leaflet/leaflet-omnivore.min.js"></script>
|
||||
<script src="leaflet/Leaflet.Coordinates.js"></script>
|
||||
<script src="leaflet/leaflet.latlng-graticule.js"></script>
|
||||
<script src="leaflet/Semicircle.js"></script>
|
||||
<script src="leaflet/dialog-polyfill.js"></script>
|
||||
|
||||
<script src="images/emoji.js"></script>
|
||||
|
196
worldmap/leaflet/Semicircle.js
Normal file
196
worldmap/leaflet/Semicircle.js
Normal file
@ -0,0 +1,196 @@
|
||||
/**
|
||||
* Semicircle extension for L.Circle.
|
||||
* Jan Pieter Waagmeester <jieter@jieter.nl>
|
||||
*
|
||||
* This version is tested with leaflet 1.0.2
|
||||
*/
|
||||
(function (factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD
|
||||
define(['leaflet'], factory);
|
||||
} else if (typeof module !== 'undefined' && typeof require !== 'undefined') {
|
||||
// Node/CommonJS
|
||||
module.exports = factory(require('leaflet'));
|
||||
} else {
|
||||
// Browser globals
|
||||
if (typeof window.L === 'undefined') {
|
||||
throw 'Leaflet must be loaded first';
|
||||
}
|
||||
factory(window.L);
|
||||
}
|
||||
})(function (L) {
|
||||
var DEG_TO_RAD = Math.PI / 180;
|
||||
|
||||
// make sure 0 degrees is up (North) and convert to radians.
|
||||
function fixAngle (angle) {
|
||||
return (angle - 90) * DEG_TO_RAD;
|
||||
}
|
||||
|
||||
// rotate point [x + r, y+r] around [x, y] by `angle` radians.
|
||||
function rotated (p, angle, r) {
|
||||
return p.add(
|
||||
L.point(Math.cos(angle), Math.sin(angle)).multiplyBy(r)
|
||||
);
|
||||
}
|
||||
|
||||
L.Point.prototype.rotated = function (angle, r) {
|
||||
return rotated(this, angle, r);
|
||||
};
|
||||
|
||||
var semicircle = {
|
||||
options: {
|
||||
startAngle: 0,
|
||||
stopAngle: 359.9999
|
||||
},
|
||||
|
||||
startAngle: function () {
|
||||
if (this.options.startAngle < this.options.stopAngle) {
|
||||
return fixAngle(this.options.startAngle);
|
||||
} else {
|
||||
return fixAngle(this.options.stopAngle);
|
||||
}
|
||||
},
|
||||
|
||||
stopAngle: function () {
|
||||
if (this.options.startAngle < this.options.stopAngle) {
|
||||
return fixAngle(this.options.stopAngle);
|
||||
} else {
|
||||
return fixAngle(this.options.startAngle);
|
||||
}
|
||||
},
|
||||
|
||||
setStartAngle: function (angle) {
|
||||
this.options.startAngle = angle;
|
||||
return this.redraw();
|
||||
},
|
||||
|
||||
setStopAngle: function (angle) {
|
||||
this.options.stopAngle = angle;
|
||||
return this.redraw();
|
||||
},
|
||||
|
||||
setDirection: function (direction, degrees) {
|
||||
if (degrees === undefined) {
|
||||
degrees = 10;
|
||||
}
|
||||
this.options.startAngle = direction - (degrees / 2);
|
||||
this.options.stopAngle = direction + (degrees / 2);
|
||||
|
||||
return this.redraw();
|
||||
},
|
||||
getDirection: function () {
|
||||
return this.stopAngle() - (this.stopAngle() - this.startAngle()) / 2;
|
||||
},
|
||||
|
||||
isSemicircle: function () {
|
||||
var startAngle = this.options.startAngle,
|
||||
stopAngle = this.options.stopAngle;
|
||||
|
||||
return (
|
||||
!(startAngle === 0 && stopAngle > 359) &&
|
||||
!(startAngle === stopAngle)
|
||||
);
|
||||
},
|
||||
_containsPoint: function (p) {
|
||||
function normalize (angle) {
|
||||
while (angle <= -Math.PI) {
|
||||
angle += 2.0 * Math.PI;
|
||||
}
|
||||
while (angle > Math.PI) {
|
||||
angle -= 2.0 * Math.PI;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
var angle = Math.atan2(p.y - this._point.y, p.x - this._point.x);
|
||||
var nStart = normalize(this.startAngle());
|
||||
var nStop = normalize(this.stopAngle());
|
||||
if (nStop <= nStart) {
|
||||
nStop += 2.0 * Math.PI;
|
||||
}
|
||||
if (angle <= nStart) {
|
||||
angle += 2.0 * Math.PI;
|
||||
}
|
||||
return (
|
||||
nStart < angle && angle <= nStop &&
|
||||
p.distanceTo(this._point) <= this._radius + this._clickTolerance()
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
L.SemiCircle = L.Circle.extend(semicircle);
|
||||
L.SemiCircleMarker = L.CircleMarker.extend(semicircle);
|
||||
|
||||
L.semiCircle = function (latlng, options) {
|
||||
return new L.SemiCircle(latlng, options);
|
||||
};
|
||||
L.semiCircleMarker = function (latlng, options) {
|
||||
return new L.SemiCircleMarker(latlng, options);
|
||||
};
|
||||
|
||||
var _updateCircleSVG = L.SVG.prototype._updateCircle;
|
||||
var _updateCircleCanvas = L.Canvas.prototype._updateCircle;
|
||||
|
||||
L.SVG.include({
|
||||
_updateCircle: function (layer) {
|
||||
// If we want a circle, we use the original function
|
||||
if (!(layer instanceof L.SemiCircle || layer instanceof L.SemiCircleMarker) ||
|
||||
!layer.isSemicircle()) {
|
||||
return _updateCircleSVG.call(this, layer);
|
||||
}
|
||||
if (layer._empty()) {
|
||||
return this._setPath(layer, 'M0 0');
|
||||
}
|
||||
|
||||
var p = layer._map.latLngToLayerPoint(layer._latlng),
|
||||
r = layer._radius,
|
||||
r2 = Math.round(layer._radiusY || r),
|
||||
start = p.rotated(layer.startAngle(), r),
|
||||
end = p.rotated(layer.stopAngle(), r);
|
||||
|
||||
var largeArc = (layer.options.stopAngle - layer.options.startAngle >= 180) ? '1' : '0';
|
||||
|
||||
var d = 'M' + p.x + ',' + p.y +
|
||||
// line to first start point
|
||||
'L' + start.x + ',' + start.y +
|
||||
'A ' + r + ',' + r2 + ',0,' + largeArc + ',1,' + end.x + ',' + end.y +
|
||||
' z';
|
||||
|
||||
this._setPath(layer, d);
|
||||
}
|
||||
});
|
||||
|
||||
L.Canvas.include({
|
||||
_updateCircle: function (layer) {
|
||||
// If we want a circle, we use the original function
|
||||
if (!(layer instanceof L.SemiCircle || layer instanceof L.SemiCircleMarker) ||
|
||||
!layer.isSemicircle()) {
|
||||
return _updateCircleCanvas.call(this, layer);
|
||||
}
|
||||
|
||||
if (!this._drawing || layer._empty()) { return; }
|
||||
|
||||
var p = layer._point,
|
||||
ctx = this._ctx,
|
||||
r = layer._radius,
|
||||
s = (layer._radiusY || r) / r,
|
||||
start = p.rotated(layer.startAngle(), r);
|
||||
|
||||
if (s !== 1) {
|
||||
ctx.save();
|
||||
ctx.scale(1, s);
|
||||
}
|
||||
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(p.x, p.y);
|
||||
ctx.lineTo(start.x, start.y);
|
||||
ctx.arc(p.x, p.y, r, layer.startAngle(), layer.stopAngle());
|
||||
ctx.lineTo(p.x, p.y);
|
||||
|
||||
if (s !== 1) {
|
||||
ctx.restore();
|
||||
}
|
||||
|
||||
this._fillStroke(ctx, layer);
|
||||
}
|
||||
});
|
||||
});
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable no-undef */
|
||||
|
||||
var startpos = [51.03, -1.379]; // Start location - somewhere in UK :-)
|
||||
var startzoom = 10;
|
||||
@ -147,6 +148,23 @@ var yellowButton = L.easyButton('fa-square wm-yellow', function(btn) { console.l
|
||||
var blackButton = L.easyButton('fa-square wm-black', function(btn) { console.log("BLACK",btn); })
|
||||
var colorControl = L.easyBar([redButton,blueButton,greenButton,yellowButton,blackButton]);
|
||||
|
||||
|
||||
function onLocationFound(e) {
|
||||
var radius = e.accuracy;
|
||||
//L.marker(e.latlng).addTo(map).bindPopup("You are within " + radius + " meters from this point").openPopup();
|
||||
L.circle(e.latlng, radius, {color:"cyan", weight:4, opacity:0.8, fill:false, clickable:false}).addTo(map);
|
||||
if (e.hasOwnProperty("heading")) {
|
||||
var lengthAsDegrees = e.speed * 60 / 110540;
|
||||
var ya = e.latlng.lat + Math.sin((90-e.heading)/180*Math.PI)*lengthAsDegrees*Math.cos(e.latlng.lng/180*Math.PI);
|
||||
var xa = e.latlng.lng + Math.cos((90-e.heading)/180*Math.PI)*lengthAsDegrees;
|
||||
var lla = new L.LatLng(ya,xa);
|
||||
L.polygon([ e.latlng, lla ], {color:"cyan", weight:3, opacity:0.8, clickable:false}).addTo(map);
|
||||
}
|
||||
ws.send(JSON.stringify({action:"point", lat:e.latlng.lat.toFixed(5), lon:e.latlng.lng.toFixed(5), point:"self", bearing:e.heading, speed:(e.speed*3.6 || undefined)}));
|
||||
}
|
||||
|
||||
function onLocationError(e) { console.log(e.message); }
|
||||
|
||||
// Move some bits around if in an iframe
|
||||
if (window.self !== window.top) {
|
||||
console.log("IN an iframe");
|
||||
@ -174,20 +192,7 @@ else {
|
||||
L.easyButton( 'fa-crosshairs fa-lg', function() {
|
||||
map.locate({setView:true, maxZoom:16});
|
||||
}, "Locate me").addTo(map);
|
||||
function onLocationFound(e) {
|
||||
var radius = e.accuracy;
|
||||
//L.marker(e.latlng).addTo(map).bindPopup("You are within " + radius + " meters from this point").openPopup();
|
||||
L.circle(e.latlng, radius, {color:"cyan", weight:4, opacity:0.8, fill:false, clickable:false}).addTo(map);
|
||||
if (e.hasOwnProperty("heading")) {
|
||||
var lengthAsDegrees = e.speed * 60 / 110540;
|
||||
var ya = e.latlng.lat + Math.sin((90-e.heading)/180*Math.PI)*lengthAsDegrees*Math.cos(e.latlng.lng/180*Math.PI);
|
||||
var xa = e.latlng.lng + Math.cos((90-e.heading)/180*Math.PI)*lengthAsDegrees;
|
||||
var lla = new L.LatLng(ya,xa);
|
||||
L.polygon([ e.latlng, lla ], {color:"cyan", weight:3, opacity:0.8, clickable:false}).addTo(map);
|
||||
}
|
||||
ws.send(JSON.stringify({action:"point", lat:e.latlng.lat.toFixed(5), lon:e.latlng.lng.toFixed(5), point:"self", bearing:e.heading, speed:(e.speed*3.6 || undefined)}));
|
||||
}
|
||||
function onLocationError(e) { console.log(e.message); }
|
||||
|
||||
map.on('locationfound', onLocationFound);
|
||||
map.on('locationerror', onLocationError);
|
||||
|
||||
@ -233,15 +238,15 @@ if (showUserMenu) {
|
||||
// Add graticule
|
||||
var showGrid = false;
|
||||
var Lgrid = L.latlngGraticule({
|
||||
font: "Verdana",
|
||||
font: "Verdana",
|
||||
fontColor: "#666",
|
||||
zoomInterval: [
|
||||
{start:1, end:2, interval:40},
|
||||
{start:3, end:3, interval:20},
|
||||
{start:4, end:4, interval:10},
|
||||
{start:5, end:7, interval:5},
|
||||
{start:8, end:20, interval:1}
|
||||
]
|
||||
{start:1, end:2, interval:40},
|
||||
{start:3, end:3, interval:20},
|
||||
{start:4, end:4, interval:10},
|
||||
{start:5, end:7, interval:5},
|
||||
{start:8, end:20, interval:1}
|
||||
]
|
||||
});
|
||||
|
||||
var panit = false;
|
||||
@ -352,22 +357,22 @@ function doSearch() {
|
||||
var searchUrl = protocol + "//nominatim.openstreetmap.org/search?format=json&limit=1&q=";
|
||||
|
||||
fetch(searchUrl + value) // Call the fetch function passing the url of the API as a parameter
|
||||
.then(function(resp) { return resp.json(); })
|
||||
.then(function(data) {
|
||||
if (data.length > 0) {
|
||||
var bb = data[0].boundingbox;
|
||||
map.fitBounds([ [bb[0],bb[2]], [bb[1],bb[3]] ]);
|
||||
map.panTo([data[0].lat, data[0].lon]);
|
||||
}
|
||||
else {
|
||||
document.getElementById('searchResult').innerHTML = " <font color='#ff0'>Not Found</font>";
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
if (err.toString() === "TypeError: Failed to fetch") {
|
||||
document.getElementById('searchResult').innerHTML = " <font color='#ff0'>Not Found</font>";
|
||||
}
|
||||
});
|
||||
.then(function(resp) { return resp.json(); })
|
||||
.then(function(data) {
|
||||
if (data.length > 0) {
|
||||
var bb = data[0].boundingbox;
|
||||
map.fitBounds([ [bb[0],bb[2]], [bb[1],bb[3]] ]);
|
||||
map.panTo([data[0].lat, data[0].lon]);
|
||||
}
|
||||
else {
|
||||
document.getElementById('searchResult').innerHTML = " <font color='#ff0'>Not Found</font>";
|
||||
}
|
||||
})
|
||||
.catch(function(err) {
|
||||
if (err.toString() === "TypeError: Failed to fetch") {
|
||||
document.getElementById('searchResult').innerHTML = " <font color='#ff0'>Not Found</font>";
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
if (lockit) {
|
||||
@ -512,7 +517,16 @@ function showMapCurrentZoom() {
|
||||
polygons[key].setStyle({opacity:0});
|
||||
}
|
||||
}
|
||||
polygons[key].redraw();
|
||||
try {
|
||||
if (polygons[key].hasOwnProperty("_layers")) {
|
||||
polygons[key].eachLayer(function(layer) { layer.redraw(); });
|
||||
}
|
||||
else {
|
||||
polygons[key].redraw();
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(key,polygons[key],e)
|
||||
}
|
||||
}
|
||||
}
|
||||
},750);
|
||||
@ -911,6 +925,26 @@ var editPoly = function(pname) {
|
||||
editHandler.enable();
|
||||
}
|
||||
|
||||
var rangerings = function(latlng, options) {
|
||||
options = L.extend({
|
||||
ranges: [250,500,750,1000],
|
||||
pan: 0,
|
||||
fov: 60,
|
||||
color: '#910000'
|
||||
}, options);
|
||||
var rings = L.featureGroup();
|
||||
if (typeof options.ranges === "number") { options.ranges = [ options.ranges ]; }
|
||||
for (var i = 0; i < options.ranges.length; i++) {
|
||||
L.semiCircle(latlng, {
|
||||
radius: options.ranges[i],
|
||||
fill: false,
|
||||
color: options.color,
|
||||
weight: 1
|
||||
}).setDirection(options.pan, options.fov).addTo(rings);
|
||||
}
|
||||
return rings;
|
||||
}
|
||||
|
||||
// the MAIN add something to map function
|
||||
function setMarker(data) {
|
||||
var rightmenu = function(m) {
|
||||
@ -1019,6 +1053,7 @@ function setMarker(data) {
|
||||
catch(e) { console.log("OOPS"); }
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof polygons[data.name] != "undefined") { layers[lay].removeLayer(polygons[data.name]); }
|
||||
|
||||
if (data.hasOwnProperty("line") && Array.isArray(data.line)) {
|
||||
@ -1052,19 +1087,23 @@ function setMarker(data) {
|
||||
polygons[data.name] = polycirc;
|
||||
}
|
||||
}
|
||||
else if (data.hasOwnProperty("arc")) {
|
||||
if (data.hasOwnProperty("lat") && data.hasOwnProperty("lon")) {
|
||||
polygons[data.name] = rangerings(new L.LatLng((data.lat*1), (data.lon*1)), data.arc);
|
||||
}
|
||||
}
|
||||
|
||||
if (polygons[data.name] !== undefined) {
|
||||
polygons[data.name].lay = lay;
|
||||
if (opt.clickable === true) {
|
||||
var words = "<b>"+data.name+"</b>";
|
||||
if (data.popup) { var words = words + "<br/>" + data.popup; }
|
||||
if (data.popup) { words = words + "<br/>" + data.popup; }
|
||||
polygons[data.name].bindPopup(words, {autoClose:false, closeButton:true, closeOnClick:false, minWidth:200});
|
||||
}
|
||||
//polygons[data.name] = rightmenu(polygons[data.name]); // DCJ Investigate
|
||||
layers[lay].addLayer(polygons[data.name]);
|
||||
}
|
||||
|
||||
|
||||
if (typeof data.coordinates == "object") { ll = new L.LatLng(data.coordinates[1],data.coordinates[0]); }
|
||||
else if (data.hasOwnProperty("position") && data.position.hasOwnProperty("lat") && data.position.hasOwnProperty("lon")) {
|
||||
data.lat = data.position.lat*1;
|
||||
@ -1444,6 +1483,7 @@ function setMarker(data) {
|
||||
var llc = data.lineColor || data.color;
|
||||
delete data.lat;
|
||||
delete data.lon;
|
||||
if (data.arc) { delete data.arc; }
|
||||
if (data.layer) { delete data.layer; }
|
||||
if (data.lineColor) { delete data.lineColor; }
|
||||
if (data.color) { delete data.color; }
|
||||
@ -1481,7 +1521,9 @@ function setMarker(data) {
|
||||
if (data.bearing != null) { // if there is a heading
|
||||
if (data.speed != null) { data.length = parseFloat(data.speed || "0") * 50; } // and a speed
|
||||
if (data.length != null) {
|
||||
if (polygons[data.name] != null) { map.removeLayer(polygons[data.name]); }
|
||||
if (polygons[data.name] != null && !polygons[data.name].hasOwnProperty("_layers")) {
|
||||
map.removeLayer(polygons[data.name]);
|
||||
}
|
||||
var x = ll.lng * 1; // X coordinate
|
||||
var y = ll.lat * 1; // Y coordinate
|
||||
var ll1 = ll;
|
||||
@ -1490,16 +1532,16 @@ function setMarker(data) {
|
||||
var polygon = null;
|
||||
if (data.accuracy != null) {
|
||||
data.accuracy = Number(data.accuracy);
|
||||
var y2 = y + Math.sin((90-angle+data.accuracy)/180*Math.PI)*lengthAsDegrees*Math.cos(y/180*Math.PI);
|
||||
var x2 = x + Math.cos((90-angle+data.accuracy)/180*Math.PI)*lengthAsDegrees;
|
||||
var y2 = y + Math.sin((90-angle+data.accuracy)/180*Math.PI)*lengthAsDegrees;
|
||||
var x2 = x + Math.cos((90-angle+data.accuracy)/180*Math.PI)*lengthAsDegrees/Math.cos(y/180*Math.PI);
|
||||
var ll2 = new L.LatLng(y2,x2);
|
||||
var y3 = y + Math.sin((90-angle-data.accuracy)/180*Math.PI)*lengthAsDegrees*Math.cos(y/180*Math.PI);
|
||||
var x3 = x + Math.cos((90-angle-data.accuracy)/180*Math.PI)*lengthAsDegrees;
|
||||
var y3 = y + Math.sin((90-angle-data.accuracy)/180*Math.PI)*lengthAsDegrees;
|
||||
var x3 = x + Math.cos((90-angle-data.accuracy)/180*Math.PI)*lengthAsDegrees/Math.cos(y/180*Math.PI);
|
||||
var ll3 = new L.LatLng(y3,x3);
|
||||
polygon = L.polygon([ ll1, ll2, ll3 ], {weight:2, color:llc||'#f30', fillOpacity:0.06, clickable:false});
|
||||
} else {
|
||||
var ya = y + Math.sin((90-angle)/180*Math.PI)*lengthAsDegrees*Math.cos(y/180*Math.PI);
|
||||
var xa = x + Math.cos((90-angle)/180*Math.PI)*lengthAsDegrees;
|
||||
var ya = y + Math.sin((90-angle)/180*Math.PI)*lengthAsDegrees;
|
||||
var xa = x + Math.cos((90-angle)/180*Math.PI)*lengthAsDegrees/Math.cos(y/180*Math.PI);
|
||||
var lla = new L.LatLng(ya,xa);
|
||||
polygon = L.polygon([ ll1, lla ], {weight:2, color:llc||'#f30', clickable:false});
|
||||
}
|
||||
@ -1509,7 +1551,12 @@ function setMarker(data) {
|
||||
polygon.setStyle({opacity:0});
|
||||
}
|
||||
}
|
||||
polygons[data.name] = polygon;
|
||||
if (polygons[data.name] != null && polygons[data.name].hasOwnProperty("_layers")) {
|
||||
polygons[data.name].addLayer(polygon);
|
||||
}
|
||||
else {
|
||||
polygons[data.name] = polygon;
|
||||
}
|
||||
polygons[data.name].lay = lay;
|
||||
layers[lay].addLayer(polygon);
|
||||
}
|
||||
|
@ -41,6 +41,7 @@
|
||||
<script src="leaflet/leaflet-omnivore.min.js"></script>
|
||||
<script src="leaflet/Leaflet.Coordinates.js"></script>
|
||||
<script src="leaflet/leaflet.latlng-graticule.js"></script>
|
||||
<script src="leaflet/Semicircle.js"></script>
|
||||
<script src="leaflet/dialog-polyfill.js"></script>
|
||||
|
||||
<script src="images/emoji.js"></script>
|
||||
|
Loading…
Reference in New Issue
Block a user