1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-01 21:54:55 -04:00

Map: Add save to KML. Support MUF/foF2 varying with time. Support VLF transmitters being read from .csv.

This commit is contained in:
srcejon
2024-04-05 10:41:24 +01:00
parent c137faf012
commit 4955e6ab08
20 changed files with 449 additions and 350 deletions
+65 -31
View File
@@ -48,6 +48,7 @@
#include "util/maidenhead.h"
#include "util/morse.h"
#include "util/navtex.h"
#include "util/vlftransmitters.h"
#include "maplocationdialog.h"
#include "mapmaidenheaddialog.h"
#include "mapsettingsdialog.h"
@@ -306,6 +307,9 @@ MapGUI::MapGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet, Feature *featur
connect(ui->web->page(), &QWebEnginePage::loadingChanged, this, &MapGUI::loadingChanged);
connect(ui->web, &QWebEngineView::renderProcessTerminated, this, &MapGUI::renderProcessTerminated);
#endif
QWebEngineProfile *profile = QWebEngineProfile::defaultProfile();
connect(profile, &QWebEngineProfile::downloadRequested, this, &MapGUI::downloadRequested);
#endif
// Get station position
@@ -489,41 +493,24 @@ void MapGUI::addIBPBeacons()
}
}
// https://sidstation.loudet.org/stations-list-en.xhtml
// https://core.ac.uk/download/pdf/224769021.pdf -- Table 1
// GQD/GQZ callsigns: https://groups.io/g/VLF/message/19212?p=%2C%2C%2C20%2C0%2C0%2C0%3A%3Arecentpostdate%2Fsticky%2C%2C19.6%2C20%2C2%2C0%2C38924431
const QList<RadioTimeTransmitter> MapGUI::m_vlfTransmitters = {
// Other signals possibly seen: 13800, 19000
{"VTX2", 17000, 8.387015, 77.752762, -1}, // South Vijayanarayanam, India
{"GQD", 19580, 54.911643, -3.278456, 100}, // Anthorn, UK, Often referred to as GBZ
{"NWC", 19800, -21.816325, 114.16546, 1000}, // Exmouth, Aus
{"ICV", 20270, 40.922946, 9.731881, 50}, // Isola di Tavolara, Italy (Can be distorted on 3D map if terrain used)
{"FTA", 20900, 48.544632, 2.579429, 50}, // Sainte-Assise, France (Satellite imagary obfuscated)
{"NPM", 21400, 21.420166, -158.151140, 600}, // Pearl Harbour, Lualuahei, USA (Not seen?)
{"HWU", 21750, 46.713129, 1.245248, 200}, // Rosnay, France
{"GQZ", 22100, 54.731799, -2.883033, 100}, // Skelton, UK (GVT in paper)
{"DHO38", 23400, 53.078900, 7.615000, 300}, // Rhauderfehn, Germany - Off air 7-8 UTC - Not seen on air!
{"NAA", 24000, 44.644506, -67.284565, 1000}, // Cutler, Maine, USA
{"TFK/NRK", 37500, 63.850365, -22.466773, 100}, // Grindavik, Iceland
{"SRC/SHR", 38000, 57.120328, 16.153083, -1}, // Ruda, Sweden
};
void MapGUI::addVLF()
{
for (int i = 0; i < m_vlfTransmitters.size(); i++)
for (int i = 0; i < VLFTransmitters::m_transmitters.size(); i++)
{
SWGSDRangel::SWGMapItem vlfMapItem;
// Need to suffix frequency, as there are multiple becaons with same callsign at different locations
QString name = QString("%1").arg(m_vlfTransmitters[i].m_callsign);
QString name = QString("%1").arg(VLFTransmitters::m_transmitters[i].m_callsign);
vlfMapItem.setName(new QString(name));
vlfMapItem.setLatitude(m_vlfTransmitters[i].m_latitude);
vlfMapItem.setLongitude(m_vlfTransmitters[i].m_longitude);
vlfMapItem.setLatitude(VLFTransmitters::m_transmitters[i].m_latitude);
vlfMapItem.setLongitude(VLFTransmitters::m_transmitters[i].m_longitude);
vlfMapItem.setAltitude(0.0);
vlfMapItem.setImage(new QString("antenna.png"));
vlfMapItem.setImageRotation(0);
QString text = QString("VLF Transmitter\nCallsign: %1\nFrequency: %2 kHz")
.arg(m_vlfTransmitters[i].m_callsign)
.arg(m_vlfTransmitters[i].m_frequency/1000.0);
.arg(VLFTransmitters::m_transmitters[i].m_callsign)
.arg(VLFTransmitters::m_transmitters[i].m_frequency/1000.0);
if (VLFTransmitters::m_transmitters[i].m_power > 0) {
text.append(QString("\nPower: %1 kW").arg(VLFTransmitters::m_transmitters[i].m_power));
}
vlfMapItem.setText(new QString(text));
vlfMapItem.setModel(new QString("antenna.glb"));
vlfMapItem.setFixedPosition(true);
@@ -535,7 +522,6 @@ void MapGUI::addVLF()
}
}
const QList<RadioTimeTransmitter> MapGUI::m_radioTimeTransmitters = {
{"MSF", 60000, 54.9075f, -3.27333f, 17}, // UK
{"DCF77", 77500, 50.01611111f, 9.00805556f, 50}, // Germany
@@ -722,12 +708,17 @@ void MapGUI::addIonosonde()
m_giro = GIRO::create();
if (m_giro)
{
connect(m_giro, &GIRO::indexUpdated, this, &MapGUI::giroIndexUpdated);
connect(m_giro, &GIRO::dataUpdated, this, &MapGUI::giroDataUpdated);
connect(m_giro, &GIRO::mufUpdated, this, &MapGUI::mufUpdated);
connect(m_giro, &GIRO::foF2Updated, this, &MapGUI::foF2Updated);
}
}
void MapGUI::giroIndexUpdated(const QList<GIRO::DataSet>& data)
{
}
void MapGUI::giroDataUpdated(const GIRO::GIROStationData& data)
{
if (!data.m_station.isEmpty())
@@ -761,6 +752,8 @@ void MapGUI::giroDataUpdated(const GIRO::GIROStationData& data)
ionosondeStationMapItem.setLabel(new QString(station->m_label));
ionosondeStationMapItem.setLabelAltitudeOffset(4.5);
ionosondeStationMapItem.setAltitudeReference(1);
ionosondeStationMapItem.setAvailableFrom(new QString(data.m_dateTime.toString(Qt::ISODateWithMs)));
ionosondeStationMapItem.setAvailableUntil(new QString(data.m_dateTime.addDays(3).toString(Qt::ISODateWithMs))); // Remove after data is too old
update(m_map, &ionosondeStationMapItem, "Ionosonde Stations");
}
}
@@ -786,6 +779,24 @@ void MapGUI::foF2Updated(const QJsonDocument& document)
}
}
void MapGUI::updateGIRO(const QDateTime& mapDateTime)
{
if (m_giro)
{
if (m_settings.m_displayMUF || m_settings.m_displayfoF2)
{
QString giroRunId = m_giro->getRunId(mapDateTime);
if (m_giroRunId.isEmpty() || (!giroRunId.isEmpty() && (giroRunId != m_giroRunId)))
{
m_giro->getMUF(giroRunId);
m_giro->getMUF(giroRunId);
m_giroRunId = giroRunId;
m_giroDateTime = mapDateTime;
}
}
}
}
void MapGUI::pathUpdated(const QString& radarPath, const QString& satellitePath)
{
m_radarPath = radarPath;
@@ -1683,6 +1694,7 @@ void MapGUI::displayToolbar()
ui->displayNASAGlobalImagery->setVisible(overlayButtons);
ui->displayMUF->setVisible(!narrow && m_settings.m_map3DEnabled);
ui->displayfoF2->setVisible(!narrow && m_settings.m_map3DEnabled);
ui->save->setVisible(m_settings.m_map3DEnabled);
}
void MapGUI::setEnableOverlay()
@@ -1803,11 +1815,10 @@ void MapGUI::applyMap3DSettings(bool reloadMap)
m_polylineMapModel.allUpdated();
}
MapSettings::MapItemSettings *ionosondeItemSettings = getItemSettings("Ionosonde Stations");
m_giro->getIndexPeriodically((m_settings.m_displayMUF || m_settings.m_displayfoF2) ? 15 : 0);
if (ionosondeItemSettings) {
m_giro->getDataPeriodically(ionosondeItemSettings->m_enabled ? 2 : 0);
}
m_giro->getMUFPeriodically(m_settings.m_displayMUF ? 15 : 0);
m_giro->getfoF2Periodically(m_settings.m_displayfoF2 ? 15 : 0);
#else
ui->displayMUF->setVisible(false);
ui->displayfoF2->setVisible(false);
@@ -2211,7 +2222,7 @@ void MapGUI::on_displayMUF_clicked(bool checked)
m_settings.m_displayMUF = checked;
// Only call show if disabling, so we don't get two updates
// (as getMUFPeriodically results in a call to showMUF when the data is available)
m_giro->getMUFPeriodically(m_settings.m_displayMUF ? 15 : 0);
m_giro->getIndexPeriodically((m_settings.m_displayMUF || m_settings.m_displayfoF2) ? 15 : 0);
if (m_cesium && !m_settings.m_displayMUF) {
m_cesium->showMUF(m_settings.m_displayMUF);
}
@@ -2226,7 +2237,7 @@ void MapGUI::on_displayfoF2_clicked(bool checked)
m_displayfoF2->setChecked(checked);
}
m_settings.m_displayfoF2 = checked;
m_giro->getfoF2Periodically(m_settings.m_displayfoF2 ? 15 : 0);
m_giro->getIndexPeriodically((m_settings.m_displayMUF || m_settings.m_displayfoF2) ? 15 : 0);
if (m_cesium && !m_settings.m_displayfoF2) {
m_cesium->showfoF2(m_settings.m_displayfoF2);
}
@@ -2442,6 +2453,22 @@ void MapGUI::track3D(const QString& target)
}
}
void MapGUI::on_save_clicked()
{
if (m_cesium)
{
m_fileDialog.setAcceptMode(QFileDialog::AcceptSave);
m_fileDialog.setNameFilter("*.kml *.kmz");
if (m_fileDialog.exec())
{
QStringList fileNames = m_fileDialog.selectedFiles();
if (fileNames.size() > 0) {
m_cesium->save(fileNames[0], getDataDir());
}
}
}
}
void MapGUI::on_deleteAll_clicked()
{
m_objectMapModel.removeAll();
@@ -2543,6 +2570,7 @@ void MapGUI::receivedCesiumEvent(const QJsonObject &obj)
bool canAnimate = obj.value("canAnimate").toBool();
bool shouldAnimate = obj.value("shouldAnimate").toBool();
m_map->setMapDateTime(mapDateTime, systemDateTime, canAnimate && shouldAnimate ? multiplier : 0.0);
updateGIRO(mapDateTime);
}
}
else if (event == "link")
@@ -2715,6 +2743,11 @@ void MapGUI::fullScreenRequested(QWebEngineFullScreenRequest fullScreenRequest)
ui->splitter->addWidget(ui->web);
}
}
void MapGUI::downloadRequested(QWebEngineDownloadItem *download)
{
download->accept();
}
#endif
void MapGUI::preferenceChanged(int elementType)
@@ -2787,6 +2820,7 @@ void MapGUI::makeUIConnections()
QObject::connect(ui->displayfoF2, &ButtonSwitch::clicked, this, &MapGUI::on_displayfoF2_clicked);
QObject::connect(ui->find, &QLineEdit::returnPressed, this, &MapGUI::on_find_returnPressed);
QObject::connect(ui->maidenhead, &QToolButton::clicked, this, &MapGUI::on_maidenhead_clicked);
QObject::connect(ui->save, &QToolButton::clicked, this, &MapGUI::on_save_clicked);
QObject::connect(ui->deleteAll, &QToolButton::clicked, this, &MapGUI::on_deleteAll_clicked);
QObject::connect(ui->displaySettings, &QToolButton::clicked, this, &MapGUI::on_displaySettings_clicked);
QObject::connect(ui->mapTypes, qOverload<int>(&QComboBox::currentIndexChanged), this, &MapGUI::on_mapTypes_currentIndexChanged);