Added separate map display for features.

This commit is contained in:
Marat Fayzullin 2023-07-10 22:25:02 -04:00
parent a57e1d00dc
commit 25167db8c6
5 changed files with 176 additions and 18 deletions

View File

@ -58,6 +58,17 @@ ul {
border-style: solid;
}
.openwebrx-map-legend li.square .feature {
display: inline-block;
width: 20px;
height: 20px;
margin-right: 10px;
border-width: 0;
border-style: none;
font-size: 24px;
text-alignment: center;
}
.openwebrx-map-legend select {
background-color: #FFF;
border-color: #DDD;

View File

@ -0,0 +1,58 @@
function FeatureMarker() {}
FeatureMarker.prototype = new google.maps.OverlayView();
FeatureMarker.prototype.draw = function() {
var div = this.div;
if (!div) return;
div.style.color = this.color? this.color : '#000000';
div.innerHTML = this.symbol? this.symbol : '●';
var point = this.getProjection().fromLatLngToDivPixel(this.position);
if (point) {
div.style.left = point.x - this.symWidth/2 + 'px';
div.style.top = point.y - this.symHeight/2 + 'px';
}
};
FeatureMarker.prototype.setOptions = function(options) {
google.maps.OverlayView.prototype.setOptions.apply(this, arguments);
this.draw();
};
FeatureMarker.prototype.onAdd = function() {
var div = this.div = document.createElement('div');
// Marker size
this.symWidth = 16;
this.symHeight = 16;
div.style.position = 'absolute';
div.style.cursor = 'pointer';
div.style.width = this.symWidth + 'px';
div.style.height = this.symHeight + 'px';
div.style.textAlign = 'center';
div.style.fontSize = this.symHeight + 'px';
div.style.lineHeight = this.symHeight + 'px';
var self = this;
google.maps.event.addDomListener(div, "click", function(event) {
event.stopPropagation();
google.maps.event.trigger(self, "click", event);
});
var panes = this.getPanes();
panes.overlayImage.appendChild(div);
};
FeatureMarker.prototype.remove = function() {
if (this.div) {
this.div.parentNode.removeChild(this.div);
this.div = null;
}
};
FeatureMarker.prototype.getAnchorPoint = function() {
return new google.maps.Point(0, -this.symHeight/2);
};

View File

@ -22,6 +22,13 @@
<option value="off">Off</option>
</select>
<div class="content"></div>
<h3>Features</h3>
<ul class="features">
<li class="square" data-selector="APRS"><span class="feature" style="color:#000000;">&#9671;</span>APRS</li>
<li class="square" data-selector="KiwiSDR"><span class="feature" style="color:#800000;">&tridot;</span>KiwiSDR</li>
<li class="square" data-selector="WebSDR"><span class="feature" style="color:#000080;">&tridot;</span>WebSDR</li>
<li class="square" data-selector="OpenWebRX"><span class="feature" style="color:#006000;">&tridot;</span>OWRX</li>
</ul>
</div>
</body>
</html>

View File

@ -41,6 +41,13 @@ $(function(){
var vessel_url = null;
var flight_url = null;
// colors used for features
var featureColors = {
'KiwiSDR' : '#800000',
'WebSDR' : '#000080',
'OpenWebRX' : '#006000'
};
var colorKeys = {};
var colorScale = chroma.scale(['red', 'blue', 'green']).mode('hsl');
var getColor = function(id){
@ -109,7 +116,7 @@ $(function(){
}
var processUpdates = function(updates) {
if (typeof(AprsMarker) == 'undefined') {
if ((typeof(AprsMarker) == 'undefined') || (typeof(FeatureMarker) == 'undefined')) {
updateQueue = updateQueue.concat(updates);
return;
}
@ -145,7 +152,6 @@ $(function(){
marker.mode = update.mode;
marker.hops = update.hops;
marker.band = update.band;
marker.url = update.location.url;
marker.comment = update.location.comment;
marker.weather = update.location.weather;
marker.altitude = update.location.altitude;
@ -154,8 +160,6 @@ $(function(){
marker.gain = update.location.gain;
marker.device = update.location.device;
marker.aircraft = update.location.aircraft;
marker.antenna = update.location.antenna;
marker.users = update.location.users;
marker.directivity = update.location.directivity;
if (expectedCallsign && expectedCallsign == update.callsign) {
@ -168,6 +172,49 @@ $(function(){
showMarkerInfoWindow(infowindow.callsign, pos);
}
break;
case 'feature':
var pos = new google.maps.LatLng(update.location.lat, update.location.lon);
var marker;
var markerClass = google.maps.Marker;
var options = {}
if (update.location.symbol) {
markerClass = FeatureMarker;
options.symbol = update.location.symbol;
options.color = update.mode in featureColors?
featureColors[update.mode] : '#000000';
}
if (markers[update.callsign]) {
marker = markers[update.callsign];
} else {
marker = new markerClass();
marker.addListener('click', function(){
showMarkerInfoWindow(update.callsign, pos);
});
markers[update.callsign] = marker;
}
marker.setOptions($.extend({
position: pos,
map: map,
title: update.callsign
}, options, getMarkerOpacityOptions(update.lastseen) ));
marker.lastseen = update.lastseen;
marker.mode = update.mode;
marker.url = update.location.url;
marker.comment = update.location.comment;
marker.altitude = update.location.altitude;
marker.device = update.location.device;
marker.antenna = update.location.antenna;
if (expectedCallsign && expectedCallsign == update.callsign) {
map.panTo(pos);
showMarkerInfoWindow(update.callsign, pos);
expectedCallsign = false;
}
if (infowindow && infowindow.callsign && infowindow.callsign == update.callsign) {
showMarkerInfoWindow(infowindow.callsign, pos);
}
break;
case 'locator':
var loc = update.location.locator;
var lat = (loc.charCodeAt(1) - 65 - 9) * 10 + Number(loc[3]);
@ -267,8 +314,16 @@ $(function(){
setInterval(function() { nite.refresh() }, 10000); // every 10s
});
$.getScript('static/lib/AprsMarker.js').done(function(){
processUpdates(updateQueue);
updateQueue = [];
if(typeof(FeatureMarker) != 'undefined') {
processUpdates(updateQueue);
updateQueue = [];
}
});
$.getScript('static/lib/FeatureMarker.js').done(function(){
if(typeof(AprsMarker) != 'undefined') {
processUpdates(updateQueue);
updateQueue = [];
}
});
var $legend = $(".openwebrx-map-legend");
@ -686,6 +741,25 @@ $(function(){
});
}
});
$content = $legend.find('.features');
$content.on('click', 'li', function() {
var $el = $(this);
$lis = $content.find('li');
if ($lis.hasClass('disabled') && !$el.hasClass('disabled')) {
$lis.removeClass('disabled');
// @@@ ADD CODE HERE
} else {
$el.removeClass('disabled');
$lis.filter(function() {
return this != $el[0]
}).addClass('disabled');
var key = colorMode.slice(2);
var selector = $el.data('selector');
// @@@ ADD CODE HERE
}
});
}
});

View File

@ -28,6 +28,9 @@ class ReceiverLocation(LatLngLocation):
def getId(self):
return re.sub(r"^.*://(.*)[/:].*$", r"\1", self.attrs["url"])
def getMode(self):
return re.sub(r"^([A-Za-z]+).*$", r"\1", self.attrs["device"])
def __dict__(self):
return self.attrs
@ -90,6 +93,7 @@ class ReceiverDatabase(object):
try:
with open(file, "w") as f:
json.dump(self, f, cls=ReceiverJSONEncoder, indent=2)
f.close()
except Exception as e:
logger.debug("Exception: {0}".format(e))
@ -101,13 +105,13 @@ class ReceiverDatabase(object):
logger.debug("Done refreshing receiver database.")
self.thread = None
def getSymbol(self, type: str):
def getColor(self, type: str):
if type.startswith("KiwiSDR"):
return getSymbolData('/', '/')
return "#800000"
elif type.startswith("WebSDR"):
return getSymbolData('/', '\\')
return "#000080"
else:
return getSymbolData('<', '\\')
return "#006000"
def loadFromFile(self, fileName: str = None):
# Get filename
@ -118,6 +122,7 @@ class ReceiverDatabase(object):
try:
with open(fileName, "r") as f:
content = f.read()
f.close()
if content:
db = json.loads(content)
except Exception as e:
@ -135,7 +140,7 @@ class ReceiverDatabase(object):
def updateMap(self):
for r in self.receivers.values():
Map.getSharedInstance().updateLocation(r.getId(), r, "Internet")
Map.getSharedInstance().updateLocation(r.getId(), r, r.getMode())
def scrapeOWRX(self, url: str = "https://www.receiverbook.de/map"):
patternJson = re.compile(r"^\s*var\s+receivers\s+=\s+(\[.*\]);\s*$")
@ -160,13 +165,14 @@ class ReceiverDatabase(object):
else:
dev = r["type"]
rl = ReceiverLocation(lat, lon, {
"type" : "latlon",
"type" : "feature",
"lat" : lat,
"lon" : lon,
"comment" : r["label"],
"url" : r["url"],
"device" : dev,
"symbol" : self.getSymbol(dev)
"symbol" : "&tridot;",
"color" : self.getColor(dev)
})
result[rl.getId()] = rl
# Offset colocated receivers by ~500m
@ -190,14 +196,15 @@ class ReceiverDatabase(object):
lat = entry["lat"]
lon = entry["lon"]
rl = ReceiverLocation(lat, lon, {
"type" : "latlon",
"type" : "feature",
"lat" : lat,
"lon" : lon,
"comment" : entry["desc"],
"url" : entry["url"],
#"users" : int(entry["users"]),
"device" : "WebSDR",
"symbol" : self.getSymbol("WebSDR")
"symbol" : "&tridot;",
"color" : self.getColor("WebSDR")
})
result[rl.getId()] = rl
@ -231,7 +238,7 @@ class ReceiverDatabase(object):
lat = float(m.group(1))
lon = float(m.group(2))
rl = ReceiverLocation(lat, lon, {
"type" : "latlon",
"type" : "feature",
"lat" : lat,
"lon" : lon,
"comment" : entry["name"],
@ -241,8 +248,9 @@ class ReceiverDatabase(object):
"loc" : entry["loc"],
"altitude": int(entry["asl"]),
"antenna" : entry["antenna"],
"device" : entry["sw_version"],
"symbol" : self.getSymbol("KiwiSDR")
"device" : re.sub("_v", " ", entry["sw_version"]),
"symbol" : "&tridot;",
"color" : self.getColor("KiwiSDR")
})
result[rl.getId()] = rl
# Clear current entry