From ae1455389162cb4d1d5be6da2930d28fedd90a73 Mon Sep 17 00:00:00 2001 From: Adam Goldsmith Date: Sat, 21 Jul 2018 12:07:23 -0400 Subject: [PATCH] Add digipeater and packet path plotting --- src/map.js | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 108 insertions(+), 1 deletion(-) diff --git a/src/map.js b/src/map.js index 304dd0c..6c905f1 100644 --- a/src/map.js +++ b/src/map.js @@ -4,7 +4,8 @@ import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer'; import {OSM, Vector as VectorSource} from 'ol/source'; import Feature from 'ol/Feature'; import {fromLonLat} from 'ol/proj'; -import {Icon, Stroke, Style} from 'ol/style'; +import {Icon, Fill, Stroke, Style, Text} from 'ol/style'; +import CircleStyle from 'ol/style/Circle'; import Projection from 'ol/proj/Projection'; import {LineString, Point} from 'ol/geom'; @@ -105,6 +106,111 @@ function plotPaths(packets) { }); } +function plotPacketPaths(packets) { + function pathToString(path) { + return path + .filter(station => !station.call.match(/WIDE[12]|qA?|UV[123]|.*\*$|UNCAN/)) + .map(station => station.toString().trim().replace(/\*$/, "")); + } + + let digiCalls = + new Set(packets + .map(packet => pathToString(packet.via)) + .reduce((acc, stations) => acc.concat(stations))); + + let digiPos = packets + // filter to digis + .filter(packet => digiCalls.has(packet.from.toString().trim())) + // filter to just positional data + .filter(packet => 'data' in packet && 'latitude' in packet.data) + // convert to callsign -> position mapping + .reduce((stations, packet) => + stations.set(packet.from.toString().trim(), + [packet.data.longitude, packet.data.latitude]), + new Map()); + + // TODO: merge with ColorGenerator + let mult = Math.floor(360 / digiPos.size); + let colors = Array.from(Array(digiPos.size).keys()) .map(x => x * mult); + let colorMap = Array.from(digiPos.keys()) + .reduce((acc, callsign, index) => acc.set(callsign, colors[index]), new Map()); + + console.log(colorMap); + + // plot digis + // TODO: icons + let digi_style = new Style({ + image: new CircleStyle({ + radius: 5, + fill: new Fill({color: 'grey'}) + }), + text: new Text({ + font: 'bold 11px "Open Sans", "Arial Unicode MS", "sans-serif"', + overflow: true, + fill: new Fill({color: 'black'}) + }) + }); + let digi_layer = new VectorLayer({ + zIndex: 1, // TODO: probably not the best way to do this + source: new VectorSource(), + style: feature => { + digi_style.getText().setText(feature.get('callsign')); + return digi_style; + } + }); + map.addLayer(digi_layer); + + digiPos.forEach((position, callsign) => { + let feature = new Feature({ + geometry: new Point(position), + callsign: callsign + }); + + digi_layer.getSource().addFeature(feature); + feature.getGeometry().transform(new Projection({code: "EPSG:4326"}), + tile_layer.getSource().getProjection()); + }); + + let packet_path_layer = new VectorLayer({source: new VectorSource()}); + map.addLayer(packet_path_layer); + packets + .filter(packet => packet.date > new Date("2018-07-14") && packet.date < new Date("2018-07-15")) + // filter by callsign + //.filter(packet => packet.from.toString() === "W1HS-9") + // filter to just positional data + .filter(packet => 'data' in packet && 'latitude' in packet.data) + .forEach(packet => { + pathToString(packet.via) + .forEach((station, index, stations) => { + if (digiPos.get(station) === undefined) { + console.log(station); + } + let previous; + if (index === 0) { + previous = [packet.data.longitude, packet.data.latitude]; + } + else { + previous = digiPos.get(stations[index - 1]) || [0, 0]; + } + + let pathFeature = new Feature( + new LineString([previous, digiPos.get(station) || [0, 0]])); + + // TODO: want to color per station that hears it, probably means + // making a lot more features + let color = colorMap.get(station); + pathFeature.setStyle(new Style( + {stroke: new Stroke( + {color: 'hsl(' + color + ', 60%, 60%)', width: 2} + )})); + + packet_path_layer.getSource().addFeature(pathFeature); + pathFeature.getGeometry().transform(new Projection({code: "EPSG:4326"}), + tile_layer.getSource().getProjection()); + }); + }); +} + function parsePackets(packetLog) { let parser = new APRSParser(); return packetLog.trim().split("\n") @@ -118,3 +224,4 @@ function parsePackets(packetLog) { let packets = parsePackets(packetLog); plotPaths(packets); +plotPacketPaths(packets);