mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-26 09:48:45 -05:00
Merge pull request #910 from srcejon/star_tracker_drift_scan
Star tracker updates
This commit is contained in:
commit
8d09a82f4e
BIN
doc/img/StarTracker_driftscan.png
Normal file
BIN
doc/img/StarTracker_driftscan.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 128 KiB |
Binary file not shown.
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 18 KiB |
BIN
doc/img/StarTracker_elevationvstime_polar.png
Normal file
BIN
doc/img/StarTracker_elevationvstime_polar.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 20 KiB |
@ -4,6 +4,7 @@
|
||||
|
||||
The Star Tracker feature plugin is for use in radio astronomy and EME (Earth-Moon-Earth) communication.
|
||||
It calculates the azimuth and elevation of celestial objects and can send them to the Rotator Controller or other plugins to point an antenna at that object.
|
||||
It can plot drift scan paths in both equatorial and galactic charts.
|
||||
The overhead position of the Sun, Moon and selected star can be displayed on the Map Feature.
|
||||
It can display local Sidereal time, solar flux density and sky temperature.
|
||||
The plugin can communicate with Stellarium, allowing Stellarium to control SDRangel as though it was a telescope and for the direction the antenna is pointing to be displayed in Stellarium.
|
||||
@ -72,8 +73,8 @@ Displays the Solar flux density. The observatory where the data is sourced from,
|
||||
<h3>11: Target</h3>
|
||||
|
||||
Select a target object to track from the list.
|
||||
To manually enter RA (right ascension) and Dec (declination) of an unlisted target, select Custom.
|
||||
To allow Stellarium to set the RA and Dec, select Custom, and ensure the Stellarium Server option is checked in the Star Tracker Settings dialog.
|
||||
To manually enter RA (right ascension) and Dec (declination) of an unlisted target, select Custom RA/Dec.
|
||||
To allow Stellarium to set the RA and Dec, select Custom RA/Dec, and ensure the Stellarium Server option is checked in the Star Tracker Settings dialog.
|
||||
|
||||
| Target | Type | Details | Flux density (Jy) |
|
||||
|------------------|-------------------|------------------------------------------------|---------------------------------------------
|
||||
@ -86,7 +87,8 @@ To allow Stellarium to set the RA and Dec, select Custom, and ensure the Stellar
|
||||
| Cygnus A | Galaxy | First radio galaxy | 22k (50MHz), 11k (150MHz), 1579 (1.4GHz) |
|
||||
| Taurus A (M1) | Supernova/Pulsar | Crab Nebular | 2008 (50MHz), 1368 (150MHz), 829 (1.4GHz) |
|
||||
| Virgo A (M87) | Galaxy | | 2635 (50MHz), 1209 (150MHz), 212 (1.4GHz) |
|
||||
| Custom | | Manually enter RA and Dec | |
|
||||
| Custom RA/Dec | | Manually enter RA and Dec | |
|
||||
| Custom Az/El | | Manually enter azimuth and elevation | |
|
||||
|
||||
References:
|
||||
|
||||
@ -104,31 +106,40 @@ Enter the half power (-3dB) beamwidth of your antenna. This value is used for sk
|
||||
|
||||
<h3>14: Right Ascension</h3>
|
||||
|
||||
When target is set to Custom, you can specify the right ascension in hours of the target object. This can be specified as a decimal (E.g. 12.23, from 0 to 24) or in hours, minutes and seconds (E.g. 12h05m10.2s or 12 05 10.2). Whether the epoch is J2000 or JNOW can be set in the Star Tracker Settings dialog.
|
||||
When target is set to Custom RA/Dec, you can specify the right ascension in hours of the target object. This can be specified as a decimal (E.g. 12.23, from 0 to 24) or in hours, minutes and seconds (E.g. 12h05m10.2s or 12 05 10.2). Whether the epoch is J2000 or JNOW can be set in the Star Tracker Settings dialog.
|
||||
|
||||
When target is set to Custom Az/El, this will display the corresponding right ascension.
|
||||
|
||||
<h3>15: Declination</h3>
|
||||
|
||||
When target is set to Custom, you can specify the declination in degrees of the target object. This can be specified as a decimal (E.g. 34.6, from -90.0 to 90.0) or in degrees, minutes and seconds (E.g. 34d12m5.6s, 34d12'5.6" 34 12 5.6). Whether the epoch is J2000 or JNOW can be set in the Star Tracker Settings dialog.
|
||||
When target is set to Custom RA/Dec, you can specify the declination in degrees of the target object. This can be specified as a decimal (E.g. 34.6, from -90.0 to 90.0) or in degrees, minutes and seconds (E.g. 34d12m5.6s, 34d12'5.6" 34 12 5.6). Whether the epoch is J2000 or JNOW can be set in the Star Tracker Settings dialog.
|
||||
|
||||
When target is set to Custom Az/El, this will display the corresponding declination.
|
||||
|
||||
<h3>16: Azimuth</h3>
|
||||
|
||||
Displays the calculated azimuth (angle in degrees, clockwise from North) to the object.
|
||||
When target is set to Custom Az/El, you specify the azimuth in degrees of the target object. The corresponding RA/Dec will be calculated and displayed.
|
||||
|
||||
For all other target settings, this displays the calculated azimuth (angle in degrees, clockwise from North) to the object.
|
||||
|
||||
<h3>17: Elevation</h3>
|
||||
|
||||
Displays the calculated elevation (angle in degrees - 0 to horizon and 90 to zenith) to the object.
|
||||
When target is set to Custom Az/El, you specify the elevation in degrees of the target object. The corresponding RA/Dec will be calculated and displayed.
|
||||
|
||||
For all other target settings, this displays the calculated elevation (angle in degrees - 0 to horizon and 90 to zenith) to the object.
|
||||
|
||||
<h2>Plots</h2>
|
||||
|
||||
<h3>Light or dark theme</h3>
|
||||
|
||||
click on this icon ![Star Tracker Chart theme](../../../doc/img/StarTracker_chart_theme.png) to switch between light and dark themes for the charts.
|
||||
Click on this icon ![Star Tracker Chart theme](../../../doc/img/StarTracker_chart_theme.png) to switch between light and dark themes for the charts.
|
||||
|
||||
<h3>Elevation vs time</h3>
|
||||
|
||||
![Star Tracker Elevation vs Time](../../../doc/img/StarTracker_elevationvstime.png)
|
||||
![Star Tracker Elevation vs Time](../../../doc/img/StarTracker_elevationvstime.png) ![Star Tracker Elevation vs Time Polar](../../../doc/img/StarTracker_elevationvstime_polar.png)
|
||||
|
||||
In order to assist in determining whether and when observations of the target object may be possible, an elevation vs time plot is drawn for the 24 hours encompassing the selected date and time.
|
||||
This can be plotted on Cartesian or polar axis.
|
||||
Some objects may not be visible from a particular latitude for the specified time, in which case, the graph title will indicate the object is not visible on that particular date.
|
||||
|
||||
<h3>Solar flux vs frequency</h3>
|
||||
@ -148,6 +159,17 @@ This temperature is therefore valid for a beamwidth of less than 1 degree.
|
||||
The Star Tracker plugin can also estimate a sky temperature based on the user entered observation frequency and beamwidth.
|
||||
To see this figure, which will be typically lower than the above, select one of the last two temperature maps from the right hand combo box.
|
||||
|
||||
<h3>Drift scan path</h3>
|
||||
|
||||
When the target (11) is set to Custom Az/El and the Sky temperature plot is displayed, a curve showing the drift scan path over a 24 hour period will be displayed.
|
||||
This assumes the azimuth and elevation will be held constant and the path shows the part of the sky the antenna will point to as the Earth rotates.
|
||||
|
||||
![Drift scan path](../../../doc/img/StarTracker_driftscan.png)
|
||||
|
||||
To setup a drift scan through a particular target object, first set the target (11) to that object. This will set the azimuth and elevation to point at the object.
|
||||
You may want to set the Time (8) to Custom and a few hours in the future, so that the elevation is at a maximum when pointing at the target.
|
||||
Then switch the target to Custom Az/El and Time back to Now, and the drift scan path that sweeps through the object will displayed.
|
||||
|
||||
<h2>Map</h2>
|
||||
|
||||
The Star Tracker feature can send the overhead position of the Sun, Moon and target Star to the Map. These can be enabled individually in the settings dialog. The Moon should be displayed with an approximate phase. Stars (or galaxies) are displayed as an image of a pulsar.
|
||||
@ -160,7 +182,7 @@ When using the Find feature in the Map GUI, you can search for "Sun", "Moon" or
|
||||
|
||||
In Star Tracker:
|
||||
|
||||
* Set target to Custom
|
||||
* Set target to Custom RA/Dec
|
||||
* Press Show settings dialog and ensure Stellarium server is checked
|
||||
* Press Start
|
||||
|
||||
@ -186,7 +208,7 @@ Then select the SDRangel telescope reticle and press Ocular view.
|
||||
|
||||
<h2>Attribution</h2>
|
||||
|
||||
Solar radio flux measurement at 10.7cm/2800MHz is from National Research Council Canada and Natural Resources Canada: https://www.spaceweather.gc.ca/solarflux/sx-4-en.php
|
||||
Solar radio flux measurement at 10.7cm/2800MHz is from National Research Council Canada and Natural Resources Canada: https://www.spaceweather.gc.ca/forecast-prevision/solar-solaire/solarflux/sx-4-en.php
|
||||
|
||||
Solar radio flux measurements at 245, 410, 610, 1415, 2695, 4995, 8800 and 15400MHz from the Learmonth Observatory: http://www.sws.bom.gov.au/World_Data_Centre/1/10
|
||||
|
||||
|
@ -141,6 +141,8 @@ void StarTracker::applySettings(const StarTrackerSettings& settings, bool force)
|
||||
<< " m_target: " << settings.m_target
|
||||
<< " m_ra: " << settings.m_ra
|
||||
<< " m_dec: " << settings.m_dec
|
||||
<< " m_az: " << settings.m_az
|
||||
<< " m_el: " << settings.m_el
|
||||
<< " m_latitude: " << settings.m_latitude
|
||||
<< " m_longitude: " << settings.m_longitude
|
||||
<< " m_serverPort: " << settings.m_serverPort
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "feature/featureuiset.h"
|
||||
#include "feature/featurewebapiutils.h"
|
||||
#include "gui/basicfeaturesettingsdialog.h"
|
||||
#include "gui/dmsspinbox.h"
|
||||
#include "mainwindow.h"
|
||||
#include "device/deviceuiset.h"
|
||||
#include "util/units.h"
|
||||
@ -93,18 +94,6 @@ bool StarTrackerGUI::deserialize(const QByteArray& data)
|
||||
}
|
||||
}
|
||||
|
||||
QString StarTrackerGUI::convertDegreesToText(double degrees)
|
||||
{
|
||||
if (m_settings.m_azElUnits == StarTrackerSettings::DMS)
|
||||
return Units::decimalDegreesToDegreeMinutesAndSeconds(degrees);
|
||||
else if (m_settings.m_azElUnits == StarTrackerSettings::DM)
|
||||
return Units::decimalDegreesToDegreesAndMinutes(degrees);
|
||||
else if (m_settings.m_azElUnits == StarTrackerSettings::D)
|
||||
return Units::decimalDegreesToDegrees(degrees);
|
||||
else
|
||||
return QString("%1").arg(degrees, 0, 'f', 2);
|
||||
}
|
||||
|
||||
bool StarTrackerGUI::handleMessage(const Message& message)
|
||||
{
|
||||
if (StarTracker::MsgConfigureStarTracker::match(message))
|
||||
@ -121,8 +110,10 @@ bool StarTrackerGUI::handleMessage(const Message& message)
|
||||
else if (StarTrackerReport::MsgReportAzAl::match(message))
|
||||
{
|
||||
StarTrackerReport::MsgReportAzAl& azAl = (StarTrackerReport::MsgReportAzAl&) message;
|
||||
ui->azimuth->setText(convertDegreesToText(azAl.getAzimuth()));
|
||||
ui->elevation->setText(convertDegreesToText(azAl.getElevation()));
|
||||
blockApplySettings(true);
|
||||
ui->azimuth->setValue(azAl.getAzimuth());
|
||||
ui->elevation->setValue(azAl.getElevation());
|
||||
blockApplySettings(false);
|
||||
return true;
|
||||
}
|
||||
else if (StarTrackerReport::MsgReportRADec::match(message))
|
||||
@ -197,6 +188,10 @@ StarTrackerGUI::StarTrackerGUI(PluginAPI* pluginAPI, FeatureUISet *featureUISet,
|
||||
connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus()));
|
||||
m_statusTimer.start(1000);
|
||||
|
||||
connect(ui->azimuth, SIGNAL(valueChanged(double)), this, SLOT(on_azimuth_valueChanged(double)));
|
||||
ui->azimuth->setRange(0, 360.0);
|
||||
ui->elevation->setRange(-90.0, 90.0);
|
||||
|
||||
// Intialise chart
|
||||
m_chart.legend()->hide();
|
||||
ui->chart->setChart(&m_chart);
|
||||
@ -310,11 +305,18 @@ void StarTrackerGUI::displaySettings()
|
||||
ui->latitude->setValue(m_settings.m_latitude);
|
||||
ui->longitude->setValue(m_settings.m_longitude);
|
||||
ui->target->setCurrentIndex(ui->target->findText(m_settings.m_target));
|
||||
if (m_settings.m_target == "Custom")
|
||||
ui->azimuth->setUnits((DMSSpinBox::DisplayUnits)m_settings.m_azElUnits);
|
||||
ui->elevation->setUnits((DMSSpinBox::DisplayUnits)m_settings.m_azElUnits);
|
||||
if (m_settings.m_target == "Custom RA/Dec")
|
||||
{
|
||||
ui->rightAscension->setText(m_settings.m_ra);
|
||||
ui->declination->setText(m_settings.m_dec);
|
||||
}
|
||||
else if (m_settings.m_target == "Custom Az/El")
|
||||
{
|
||||
ui->azimuth->setValue(m_settings.m_az);
|
||||
ui->elevation->setValue(m_settings.m_el);
|
||||
}
|
||||
if (m_settings.m_dateTime == "")
|
||||
{
|
||||
ui->dateTimeSelect->setCurrentIndex(0);
|
||||
@ -413,6 +415,20 @@ void StarTrackerGUI::on_declination_editingFinished()
|
||||
plotChart();
|
||||
}
|
||||
|
||||
void StarTrackerGUI::on_azimuth_valueChanged(double value)
|
||||
{
|
||||
m_settings.m_az = value;
|
||||
applySettings();
|
||||
plotChart();
|
||||
}
|
||||
|
||||
void StarTrackerGUI::on_elevation_valueChanged(double value)
|
||||
{
|
||||
m_settings.m_el = value;
|
||||
applySettings();
|
||||
plotChart();
|
||||
}
|
||||
|
||||
void StarTrackerGUI::updateForTarget()
|
||||
{
|
||||
if (m_settings.m_target == "Sun")
|
||||
@ -429,7 +445,7 @@ void StarTrackerGUI::updateForTarget()
|
||||
ui->rightAscension->setText("");
|
||||
ui->declination->setText("");
|
||||
}
|
||||
else if (m_settings.m_target == "Custom")
|
||||
else if (m_settings.m_target == "Custom RA/Dec")
|
||||
{
|
||||
ui->rightAscension->setReadOnly(false);
|
||||
ui->declination->setReadOnly(false);
|
||||
@ -476,9 +492,21 @@ void StarTrackerGUI::updateForTarget()
|
||||
on_rightAscension_editingFinished();
|
||||
on_declination_editingFinished();
|
||||
}
|
||||
// Clear as no longer valid when target has changed
|
||||
ui->azimuth->setText("");
|
||||
ui->elevation->setText("");
|
||||
if (m_settings.m_target != "Custom Az/El")
|
||||
{
|
||||
ui->azimuth->setReadOnly(true);
|
||||
ui->elevation->setReadOnly(true);
|
||||
// Clear as no longer valid when target has changed
|
||||
ui->azimuth->setText("");
|
||||
ui->elevation->setText("");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->rightAscension->setReadOnly(true);
|
||||
ui->declination->setReadOnly(true);
|
||||
ui->azimuth->setReadOnly(false);
|
||||
ui->elevation->setReadOnly(false);
|
||||
}
|
||||
}
|
||||
|
||||
void StarTrackerGUI::on_target_currentTextChanged(const QString &text)
|
||||
@ -572,6 +600,8 @@ void StarTrackerGUI::on_displaySettings_clicked()
|
||||
if (dialog.exec() == QDialog::Accepted)
|
||||
{
|
||||
applySettings();
|
||||
ui->elevation->setUnits((DMSSpinBox::DisplayUnits)m_settings.m_azElUnits);
|
||||
ui->azimuth->setUnits((DMSSpinBox::DisplayUnits)m_settings.m_azElUnits);
|
||||
displaySolarFlux();
|
||||
if (ui->chartSelect->currentIndex() == 1)
|
||||
plotChart();
|
||||
@ -691,6 +721,116 @@ void StarTrackerGUI::plotSolarFluxChart()
|
||||
// disconnect(&m_chart, SIGNAL(plotAreaChanged(QRectF)), this, SLOT(plotAreaChanged(QRectF)));
|
||||
}
|
||||
|
||||
QList<QLineSeries*> StarTrackerGUI::createDriftScan(bool galactic)
|
||||
{
|
||||
QList<QLineSeries *>list;
|
||||
QLineSeries *series = new QLineSeries();
|
||||
list.append(series);
|
||||
|
||||
QDateTime dt;
|
||||
|
||||
// Get date and time to calculate position at
|
||||
if (m_settings.m_dateTime == "") {
|
||||
dt = QDateTime::currentDateTime();
|
||||
} else {
|
||||
dt = QDateTime::fromString(m_settings.m_dateTime, Qt::ISODateWithMs);
|
||||
}
|
||||
|
||||
// Create a list of RA/Dec points of drift scan path
|
||||
AzAlt aa;
|
||||
aa.alt = m_settings.m_el;
|
||||
aa.az = m_settings.m_az;
|
||||
double prevX, prevY;
|
||||
// Plot every 30min over a day
|
||||
for (int i = 0; i <= 24*2; i++)
|
||||
{
|
||||
dt = dt.addSecs(30*60);
|
||||
RADec rd = Astronomy::azAltToRaDec(aa, m_settings.m_latitude, m_settings.m_longitude, dt);
|
||||
double x, y;
|
||||
mapRaDec(rd.ra, rd.dec, galactic, x, y);
|
||||
if (i == 0)
|
||||
{
|
||||
series->append(x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for crossing edge of chart
|
||||
if (galactic)
|
||||
{
|
||||
if (((prevX < 90.0) && (x > 270.0)) || ((prevX > 270.0) && (x < 90.0)))
|
||||
{
|
||||
// Start new series, so we don't have lines crossing across the chart
|
||||
series = new QLineSeries();
|
||||
list.append(series);
|
||||
}
|
||||
}
|
||||
series->append(x, y);
|
||||
}
|
||||
prevX = x;
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
void StarTrackerGUI::mapRaDec(double ra, double dec, bool galactic, double& x, double& y)
|
||||
{
|
||||
if (galactic)
|
||||
{
|
||||
// Convert to category coordinates
|
||||
double l, b;
|
||||
Astronomy::equatorialToGalactic(ra, dec, l, b);
|
||||
// Map to linear axis
|
||||
double lAxis;
|
||||
if (l < 180.0) {
|
||||
lAxis = 180.0 - l;
|
||||
} else {
|
||||
lAxis = 360.0 - l + 180.0;
|
||||
}
|
||||
|
||||
x = lAxis;
|
||||
y = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map to category axis
|
||||
double raAxis;
|
||||
if (ra <= 12.0) {
|
||||
raAxis = 12.0 - ra;
|
||||
} else {
|
||||
raAxis = 24 - ra + 12;
|
||||
}
|
||||
|
||||
x = raAxis;
|
||||
y = dec;
|
||||
}
|
||||
}
|
||||
|
||||
// Is there a way to get this from the theme? Got these values from the source
|
||||
QColor StarTrackerGUI::getSeriesColor(int series)
|
||||
{
|
||||
if (m_settings.m_chartsDarkTheme)
|
||||
{
|
||||
if (series == 0) {
|
||||
return QColor(0x38ad6b);
|
||||
} else if (series == 1) {
|
||||
return QColor(0x3c84a7);
|
||||
} else {
|
||||
return QColor(0xeb8817);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (series == 0) {
|
||||
return QColor(0x209fdf);
|
||||
} else if (series == 1) {
|
||||
return QColor(0x99ca53);
|
||||
} else {
|
||||
return QColor(0xf6a625);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
{
|
||||
bool galactic = (ui->chartSubSelect->currentIndex() & 1) == 1;
|
||||
@ -698,6 +838,16 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
m_chart.removeAllSeries();
|
||||
removeAllAxes();
|
||||
|
||||
// Plot drift scan path
|
||||
QList<QLineSeries*> lineSeries;
|
||||
if (m_settings.m_target == "Custom Az/El") {
|
||||
lineSeries = createDriftScan(galactic);
|
||||
QPen pen(getSeriesColor(1), 2, Qt::SolidLine);
|
||||
for (int i = 0; i < lineSeries.length(); i++) {
|
||||
lineSeries[i]->setPen(pen);
|
||||
}
|
||||
}
|
||||
|
||||
QScatterSeries *series = new QScatterSeries();
|
||||
float ra = Astronomy::raToDecimal(m_settings.m_ra);
|
||||
float dec = Astronomy::decToDecimal(m_settings.m_dec);
|
||||
@ -709,30 +859,9 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
double degPerPixel = std::min(degPerPixelW, degPerPixelH);
|
||||
double markerSize;
|
||||
|
||||
if (galactic)
|
||||
{
|
||||
// Convert to category coordinates
|
||||
double l, b;
|
||||
Astronomy::equatorialToGalactic(ra, dec, l, b);
|
||||
|
||||
// Map to linear axis
|
||||
double lAxis;
|
||||
if (l < 180.0)
|
||||
lAxis = 180.0 - l;
|
||||
else
|
||||
lAxis = 360.0 - l + 180.0;
|
||||
series->append(lAxis, b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Map to category axis
|
||||
double raAxis;
|
||||
if (ra <= 12.0)
|
||||
raAxis = 12.0 - ra;
|
||||
else
|
||||
raAxis = 24 - ra + 12;
|
||||
series->append(raAxis, dec);
|
||||
}
|
||||
double x, y;
|
||||
mapRaDec(ra, dec, galactic, x, y);
|
||||
series->append(x, y);
|
||||
|
||||
// Get temperature
|
||||
int idx = ui->chartSubSelect->currentIndex();
|
||||
@ -757,10 +886,12 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
double degreesPerPixelV = abs(fits->degreesPerPixelV());
|
||||
int numberOfCoeffsH = ceil(beamwidth/degreesPerPixelH);
|
||||
int numberOfCoeffsV = ceil(beamwidth/degreesPerPixelV);
|
||||
if ((numberOfCoeffsH & 1) == 0)
|
||||
if ((numberOfCoeffsH & 1) == 0) {
|
||||
numberOfCoeffsH++;
|
||||
if ((numberOfCoeffsV & 1) == 0)
|
||||
}
|
||||
if ((numberOfCoeffsV & 1) == 0) {
|
||||
numberOfCoeffsV++;
|
||||
}
|
||||
double *beam = new double[numberOfCoeffsH*numberOfCoeffsV];
|
||||
double sum = 0.0;
|
||||
int y0 = numberOfCoeffsV/2;
|
||||
@ -780,16 +911,19 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
nonZeroCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
beam[y*numberOfCoeffsH+x] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Get centre pixel coordinates
|
||||
double centreX;
|
||||
if (ra <= 12.0)
|
||||
if (ra <= 12.0) {
|
||||
centreX = (12.0 - ra) / 24.0;
|
||||
else
|
||||
} else {
|
||||
centreX = (24 - ra + 12) / 24.0;
|
||||
}
|
||||
double centreY = (90.0-dec) / 180.0;
|
||||
int imgX = centreX * fits->width();
|
||||
int imgY = centreY * fits->height();
|
||||
@ -831,12 +965,13 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
else
|
||||
{
|
||||
// See https://arxiv.org/abs/1812.10084 fig 2
|
||||
if (m_settings.m_frequency < 200e6)
|
||||
if (m_settings.m_frequency < 200e6) {
|
||||
spectralIndex = 2.55;
|
||||
else if (m_settings.m_frequency < 20e9)
|
||||
} else if (m_settings.m_frequency < 20e9) {
|
||||
spectralIndex = 2.695;
|
||||
else
|
||||
} else {
|
||||
spectralIndex = 3.1;
|
||||
}
|
||||
}
|
||||
double galactic480 = temp408 - cmbT - iso408;
|
||||
double galacticT = galactic480 * pow(408e6/m_settings.m_frequency, spectralIndex); // Scale galactic contribution by frequency
|
||||
@ -860,16 +995,19 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
QImage *img = &m_images[idx];
|
||||
FITS *fits = &m_temps[idx/2];
|
||||
double x;
|
||||
if (ra <= 12.0)
|
||||
if (ra <= 12.0) {
|
||||
x = (12.0 - ra) / 24.0;
|
||||
else
|
||||
} else {
|
||||
x = (24 - ra + 12) / 24.0;
|
||||
int imgX = x * img->width();
|
||||
if (imgX >= img->width())
|
||||
imgX = img->width();
|
||||
int imgY = (90.0-dec)/180.0 * img->height();
|
||||
if (imgY >= img->height())
|
||||
imgY = img->height();
|
||||
}
|
||||
int imgX = x * (img->width() - 1);
|
||||
if (imgX >= img->width()) {
|
||||
imgX = img->width() - 1;
|
||||
}
|
||||
int imgY = (90.0-dec)/180.0 * (img->height() - 1);
|
||||
if (imgY >= img->height()) {
|
||||
imgY = img->height() - 1;
|
||||
}
|
||||
|
||||
if (fits->valid())
|
||||
{
|
||||
@ -883,8 +1021,13 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
markerSize = 5;
|
||||
}
|
||||
series->setMarkerSize(markerSize);
|
||||
series->setColor(getSeriesColor(0));
|
||||
|
||||
m_chart.setTitle("");
|
||||
// We want scatter to be on top of line, but same color even when no drift line
|
||||
for (int i = 0; i < lineSeries.length(); i++) {
|
||||
m_chart.addSeries(lineSeries[i]);
|
||||
}
|
||||
m_chart.addSeries(series);
|
||||
if (galactic)
|
||||
{
|
||||
@ -894,6 +1037,12 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
m_skyTempYAxis.setTitleText(QString("Galactic latitude (%1)").arg(QChar(0xb0)));
|
||||
m_chart.addAxis(&m_skyTempYAxis, Qt::AlignLeft);
|
||||
series->attachAxis(&m_skyTempYAxis);
|
||||
|
||||
for (int i = 0; i < lineSeries.length(); i++)
|
||||
{
|
||||
lineSeries[i]->attachAxis(&m_skyTempGalacticLXAxis);
|
||||
lineSeries[i]->attachAxis(&m_skyTempYAxis);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -903,6 +1052,12 @@ void StarTrackerGUI::plotSkyTemperatureChart()
|
||||
m_skyTempYAxis.setTitleText(QString("Declination (%1)").arg(QChar(0xb0)));
|
||||
m_chart.addAxis(&m_skyTempYAxis, Qt::AlignLeft);
|
||||
series->attachAxis(&m_skyTempYAxis);
|
||||
|
||||
for (int i = 0; i < lineSeries.length(); i++)
|
||||
{
|
||||
lineSeries[i]->attachAxis(&m_skyTempRAXAxis);
|
||||
lineSeries[i]->attachAxis(&m_skyTempYAxis);
|
||||
}
|
||||
}
|
||||
ui->chart->setChart(&m_chart);
|
||||
plotAreaChanged(m_chart.plotArea());
|
||||
@ -965,7 +1120,7 @@ void StarTrackerGUI::plotElevationLineChart()
|
||||
QList<QLineSeries *> azSeriesList;
|
||||
QLineSeries *azSeries = new QLineSeries();
|
||||
azSeriesList.append(azSeries);
|
||||
QPen pen(QColor(153, 202, 83), 2, Qt::SolidLine);
|
||||
QPen pen(getSeriesColor(1), 2, Qt::SolidLine);
|
||||
azSeries->setPen(pen);
|
||||
|
||||
QDateTime dt;
|
||||
@ -1172,7 +1327,7 @@ void StarTrackerGUI::plotElevationPolarChart()
|
||||
QList<QLineSeries *> series;
|
||||
series.append(new QLineSeries());
|
||||
QLineSeries *s = series.first();
|
||||
QPen pen(QColor(32, 159, 223), 2, Qt::SolidLine);
|
||||
QPen pen(getSeriesColor(0), 2, Qt::SolidLine);
|
||||
s->setPen(pen);
|
||||
|
||||
qreal prevAz = polarSeries->at(0).x();
|
||||
@ -1467,7 +1622,7 @@ void StarTrackerGUI::updateSolarFlux(bool all)
|
||||
}
|
||||
if ((m_settings.m_solarFluxData == StarTrackerSettings::DRAO_2800) || all)
|
||||
{
|
||||
m_networkRequest.setUrl(QUrl("https://www.spaceweather.gc.ca/solarflux/sx-4-en.php"));
|
||||
m_networkRequest.setUrl(QUrl("https://www.spaceweather.gc.ca/forecast-prevision/solar-solaire/solarflux/sx-4-en.php"));
|
||||
m_networkManager->get(m_networkRequest);
|
||||
}
|
||||
}
|
||||
|
@ -102,9 +102,11 @@ private:
|
||||
void applySettings(bool force = false);
|
||||
void displaySettings();
|
||||
void updateForTarget();
|
||||
QString convertDegreesToText(double degrees);
|
||||
bool handleMessage(const Message& message);
|
||||
void updateLST();
|
||||
void mapRaDec(double ra, double dec, bool galactic, double& x, double& y);
|
||||
QList<QLineSeries*> createDriftScan(bool galactic);
|
||||
QColor getSeriesColor(int series);
|
||||
void plotElevationLineChart();
|
||||
void plotElevationPolarChart();
|
||||
void plotSkyTemperatureChart();
|
||||
@ -133,6 +135,8 @@ private slots:
|
||||
void on_longitude_valueChanged(double value);
|
||||
void on_rightAscension_editingFinished();
|
||||
void on_declination_editingFinished();
|
||||
void on_azimuth_valueChanged(double value);
|
||||
void on_elevation_valueChanged(double value);
|
||||
void on_frequency_valueChanged(int value);
|
||||
void on_beamwidth_valueChanged(double value);
|
||||
void on_target_currentTextChanged(const QString &text);
|
||||
|
@ -67,13 +67,17 @@
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lst">
|
||||
<property name="toolTip">
|
||||
<string>Local sidereal time for selected date, time and longitude</string>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="beamwidthLabel">
|
||||
<property name="text">
|
||||
<string>Beamwidth</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="timeLabel">
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -84,86 +88,6 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="dateTimeSelect">
|
||||
<property name="toolTip">
|
||||
<string>Select time to calculate target's position at</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Now</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="frequencyLabel">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2">
|
||||
<widget class="WrappingDateTimeEdit" name="dateTime">
|
||||
<property name="toolTip">
|
||||
<string>Date and time to use when calculating target's position</string>
|
||||
</property>
|
||||
<property name="displayFormat">
|
||||
<string>dd/MM/yyyy HH:mm:ss</string>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="3">
|
||||
<widget class="QLineEdit" name="declination">
|
||||
<property name="toolTip">
|
||||
<string>Declination of the target object
|
||||
|
||||
This can be specified as a decimal (E.g. 34.23) or in degrees, minutes and seconds (E.g. 34d12m10.2s, 34d12'10.2" 34 12 10.2)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>-90d59'59.59"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="rightAscension">
|
||||
<property name="toolTip">
|
||||
<string>Right Ascension of the target object.
|
||||
|
||||
This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds (E.g. 12h05m10.2s or 12 05 10.2)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>23h59m59.59s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QDoubleSpinBox" name="longitude">
|
||||
<property name="toolTip">
|
||||
<string>Longitude in decimal degress (East positive) of observation point / antenna location</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QSpinBox" name="frequency">
|
||||
<property name="toolTip">
|
||||
@ -177,40 +101,6 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lstLabel">
|
||||
<property name="text">
|
||||
<string>LST</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="longitudeLabel">
|
||||
<property name="text">
|
||||
<string>Longitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="targetLabel">
|
||||
<property name="text">
|
||||
<string>Target</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="QLineEdit" name="azimuth">
|
||||
<property name="toolTip">
|
||||
<string>Computed azimuth in degrees to the target from the observation point</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>360</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="azimuthtLabel">
|
||||
<property name="text">
|
||||
@ -218,95 +108,26 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="solarFluxLabel">
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="rightAscensionLabel">
|
||||
<property name="text">
|
||||
<string>Solar Flux</string>
|
||||
<string>RA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<layout class="QHBoxLayout" name="targetLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="target">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target object</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sun</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Moon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PSR B0329+54</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PSR B0833-45</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sagittarius A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cassiopeia A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cygnus A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Taurus A (M1)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Virgo A (M87)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="lstLabel">
|
||||
<property name="text">
|
||||
<string>LST</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="elevationLabel">
|
||||
<property name="text">
|
||||
<string>Elevation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="4">
|
||||
<layout class="QHBoxLayout" name="buttonLayout">
|
||||
@ -396,80 +217,32 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="latitude">
|
||||
<property name="toolTip">
|
||||
<string>Latitude in decimal degrees (North positive) of observation point / antenna location</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-90.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>90.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-90.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="timeLabel">
|
||||
<property name="text">
|
||||
<string>Time</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="elevationLabel">
|
||||
<property name="text">
|
||||
<string>Elevation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="beamwidthLabel">
|
||||
<property name="text">
|
||||
<string>Beamwidth</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="rightAscensionLabel">
|
||||
<property name="text">
|
||||
<string>RA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="3">
|
||||
<widget class="QLineEdit" name="elevation">
|
||||
<widget class="DMSSpinBox" name="elevation" native="true">
|
||||
<property name="toolTip">
|
||||
<string>Computed elevation in degrees to the target from the observation point</string>
|
||||
<string>Elevation in degrees to the target from the observation point</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>90</string>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLineEdit" name="lst">
|
||||
<property name="toolTip">
|
||||
<string>Local sidereal time for selected date, time and longitude</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLineEdit" name="solarFlux">
|
||||
<item row="7" column="3">
|
||||
<widget class="QLineEdit" name="declination">
|
||||
<property name="toolTip">
|
||||
<string>Solar flux density</string>
|
||||
<string>Declination of the target object
|
||||
|
||||
This can be specified as a decimal (E.g. 34.23) or in degrees, minutes and seconds (E.g. 34d12m10.2s, 34d12'10.2" 34 12 10.2)</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="latitudeLabel">
|
||||
<property name="text">
|
||||
<string>Latitude</string>
|
||||
<string>-90d59'59.59"</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -492,6 +265,226 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1" colspan="3">
|
||||
<layout class="QHBoxLayout" name="targetLayout">
|
||||
<item>
|
||||
<widget class="QComboBox" name="target">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Target object</string>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sun</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Moon</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PSR B0329+54</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>PSR B0833-45</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Sagittarius A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cassiopeia A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Cygnus A</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Taurus A (M1)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Virgo A (M87)</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom RA/Dec</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom Az/El</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="dateTimeSelect">
|
||||
<property name="toolTip">
|
||||
<string>Select time to calculate target's position at</string>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Now</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Custom</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="latitudeLabel">
|
||||
<property name="text">
|
||||
<string>Latitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="frequencyLabel">
|
||||
<property name="text">
|
||||
<string>Frequency</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2" colspan="2">
|
||||
<widget class="WrappingDateTimeEdit" name="dateTime">
|
||||
<property name="toolTip">
|
||||
<string>Date and time to use when calculating target's position</string>
|
||||
</property>
|
||||
<property name="displayFormat">
|
||||
<string>dd/MM/yyyy HH:mm:ss</string>
|
||||
</property>
|
||||
<property name="calendarPopup">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLineEdit" name="solarFlux">
|
||||
<property name="toolTip">
|
||||
<string>Solar flux density</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="targetLabel">
|
||||
<property name="text">
|
||||
<string>Target</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="1">
|
||||
<widget class="QLineEdit" name="rightAscension">
|
||||
<property name="toolTip">
|
||||
<string>Right Ascension of the target object.
|
||||
|
||||
This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds (E.g. 12h05m10.2s or 12 05 10.2)</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>23h59m59.59s</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="longitudeLabel">
|
||||
<property name="text">
|
||||
<string>Longitude</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QDoubleSpinBox" name="longitude">
|
||||
<property name="toolTip">
|
||||
<string>Longitude in decimal degress (East positive) of observation point / antenna location</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>180.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-180.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="solarFluxLabel">
|
||||
<property name="text">
|
||||
<string>Solar Flux</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QDoubleSpinBox" name="latitude">
|
||||
<property name="toolTip">
|
||||
<string>Latitude in decimal degrees (North positive) of observation point / antenna location</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<double>-90.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>90.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>-90.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="1">
|
||||
<widget class="DMSSpinBox" name="azimuth" native="true">
|
||||
<property name="toolTip">
|
||||
<string>Azimuth in degrees to the target from the observation point</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
@ -619,6 +612,11 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
<header>gui/wrappingdatetimeedit.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DMSSpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>gui/dmsspinbox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>startStop</tabstop>
|
||||
@ -637,10 +635,9 @@ This can be specified as a decimal (E.g. 12.23) or in hours, minutes and seconds
|
||||
<tabstop>beamwidth</tabstop>
|
||||
<tabstop>rightAscension</tabstop>
|
||||
<tabstop>declination</tabstop>
|
||||
<tabstop>azimuth</tabstop>
|
||||
<tabstop>elevation</tabstop>
|
||||
<tabstop>chartSelect</tabstop>
|
||||
<tabstop>chartSubSelect</tabstop>
|
||||
<tabstop>darkTheme</tabstop>
|
||||
<tabstop>chart</tabstop>
|
||||
</tabstops>
|
||||
<resources>
|
||||
|
@ -20,8 +20,10 @@
|
||||
#define INCLUDE_FEATURE_STARTRACKERREPORT_H_
|
||||
|
||||
#include <QObject>
|
||||
#include <QList>
|
||||
|
||||
#include "util/message.h"
|
||||
#include "util/astronomy.h"
|
||||
|
||||
class StarTrackerReport : public QObject
|
||||
{
|
||||
|
@ -62,6 +62,8 @@ void StarTrackerSettings::resetToDefaults()
|
||||
m_reverseAPIPort = 8888;
|
||||
m_reverseAPIFeatureSetIndex = 0;
|
||||
m_reverseAPIFeatureIndex = 0;
|
||||
m_az = 0.0;
|
||||
m_el = 0.0;
|
||||
}
|
||||
|
||||
QByteArray StarTrackerSettings::serialize() const
|
||||
@ -100,6 +102,8 @@ QByteArray StarTrackerSettings::serialize() const
|
||||
s.writeDouble(30, m_beamwidth);
|
||||
s.writeU32(31, m_solarFluxData);
|
||||
s.writeBool(32, m_chartsDarkTheme);
|
||||
s.writeDouble(33, m_az);
|
||||
s.writeDouble(34, m_el);
|
||||
|
||||
return s.final();
|
||||
}
|
||||
@ -169,6 +173,9 @@ bool StarTrackerSettings::deserialize(const QByteArray& data)
|
||||
d.readU32(31, (quint32 *)&m_solarFluxData, DRAO_2800);
|
||||
d.readBool(32, &m_chartsDarkTheme, true);
|
||||
|
||||
d.readDouble(33, &m_az, 0.0);
|
||||
d.readDouble(34, &m_el, 0.0);
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -44,7 +44,7 @@ struct StarTrackerSettings
|
||||
double m_beamwidth; // Beamwidth in degrees
|
||||
uint16_t m_serverPort;
|
||||
bool m_enableServer; // Enable Stellarium server
|
||||
enum AzElUnits {DMS, DM, D, Decimal} m_azElUnits;
|
||||
enum AzElUnits {DMS, DM, D, Decimal} m_azElUnits; // This needs to match DMSSpinBox::DisplayUnits
|
||||
enum SolarFluxData {DRAO_2800, L_245, L_410, L_610, L_1415, L2695, L_4995, L_8800, L_15400, TARGET_FREQ} m_solarFluxData; // What Solar flux density data to display
|
||||
enum SolarFluxUnits {SFU, JANSKY, WATTS_M_HZ} m_solarFluxUnits;
|
||||
float m_updatePeriod;
|
||||
@ -53,7 +53,6 @@ struct StarTrackerSettings
|
||||
bool m_drawMoonOnMap;
|
||||
bool m_drawStarOnMap;
|
||||
bool m_chartsDarkTheme; // Dark theme for charts
|
||||
|
||||
QString m_title;
|
||||
quint32 m_rgbColor;
|
||||
bool m_useReverseAPI;
|
||||
@ -61,6 +60,8 @@ struct StarTrackerSettings
|
||||
uint16_t m_reverseAPIPort;
|
||||
uint16_t m_reverseAPIFeatureSetIndex;
|
||||
uint16_t m_reverseAPIFeatureIndex;
|
||||
double m_az; // Azimuth for Custom Az/El
|
||||
double m_el; // Elevation for Custom Az/El
|
||||
|
||||
StarTrackerSettings();
|
||||
void resetToDefaults();
|
||||
|
@ -463,6 +463,13 @@ void StarTrackerWorker::update()
|
||||
rd = moonRD;
|
||||
aa = moonAA;
|
||||
}
|
||||
else if (m_settings.m_target == "Custom Az/El")
|
||||
{
|
||||
// Convert Alt/Az to RA/Dec
|
||||
aa.alt = m_settings.m_el;
|
||||
aa.az = m_settings.m_az;
|
||||
rd = Astronomy::azAltToRaDec(aa, m_settings.m_latitude, m_settings.m_longitude, dt);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert RA/Dec to Alt/Az
|
||||
@ -491,8 +498,11 @@ void StarTrackerWorker::update()
|
||||
// Send to GUI
|
||||
if (getMessageQueueToGUI())
|
||||
{
|
||||
StarTrackerReport::MsgReportAzAl *msg = StarTrackerReport::MsgReportAzAl::create(aa.az, aa.alt);
|
||||
getMessageQueueToGUI()->push(msg);
|
||||
if (m_settings.m_target == "Custom Az/El") {
|
||||
getMessageQueueToGUI()->push(StarTrackerReport::MsgReportRADec::create(rd.ra, rd.dec));
|
||||
} else {
|
||||
getMessageQueueToGUI()->push(StarTrackerReport::MsgReportAzAl::create(aa.az, aa.alt));
|
||||
}
|
||||
}
|
||||
|
||||
// Send Az/El to Rotator Controllers
|
||||
@ -542,7 +552,7 @@ void StarTrackerWorker::update()
|
||||
{
|
||||
double starLongitude = Astronomy::lstAndRAToLongitude(lst, rd.ra);
|
||||
double starLatitude = rd.dec;
|
||||
QString text = m_settings.m_target == "Custom" ? "Star" : m_settings.m_target;
|
||||
QString text = m_settings.m_target.startsWith("Custom") ? "Star" : m_settings.m_target;
|
||||
sendToMap(mapMessageQueues, "Star", "qrc:///startracker/startracker/pulsar-32.png", text, starLatitude, starLongitude);
|
||||
}
|
||||
}
|
||||
|
@ -216,6 +216,47 @@ AzAlt Astronomy::raDecToAzAlt(RADec rd, double latitude, double longitude, QDate
|
||||
return aa;
|
||||
}
|
||||
|
||||
// Convert from altitude and azimuth, for location (decimal degrees) and time, to Jnow right ascension (decimal hours) and declination (decimal degrees)
|
||||
// See: http://jonvoisey.net/blog/2018/07/data-converting-alt-az-to-ra-dec-example/
|
||||
RADec Astronomy::azAltToRaDec(AzAlt aa, double latitude, double longitude, QDateTime dt)
|
||||
{
|
||||
RADec rd;
|
||||
double lst_deg; // Local sidereal time
|
||||
double ha_rad, ha_deg; // Hour angle
|
||||
double alt_rad, az_rad, lat_rad, dec_rad; // Corresponding variables as radians
|
||||
|
||||
// Calculate local mean sidereal time (LMST) in degrees (see raDecToAzAlt)
|
||||
lst_deg = Astronomy::localSiderealTime(dt, longitude);
|
||||
|
||||
// Convert degrees to radians
|
||||
alt_rad = Units::degreesToRadians(aa.alt);
|
||||
az_rad = Units::degreesToRadians(aa.az);
|
||||
lat_rad = Units::degreesToRadians(latitude);
|
||||
|
||||
// Calculate declination
|
||||
dec_rad = asin(sin(lat_rad)*sin(alt_rad)+cos(lat_rad)*cos(alt_rad)*cos(az_rad));
|
||||
|
||||
// Calculate hour angle
|
||||
double quotient = (sin(alt_rad)-sin(lat_rad)*sin(dec_rad))/(cos(lat_rad)*cos(dec_rad));
|
||||
// At extreme altitudes, we seem to get small numerical errors that causes values to be out of range, so clip to [-1,1]
|
||||
if (quotient < -1.0) {
|
||||
ha_rad = acos(-1.0);
|
||||
} else if (quotient > 1.0) {
|
||||
ha_rad = acos(1.0);
|
||||
} else {
|
||||
ha_rad = acos(quotient);
|
||||
}
|
||||
|
||||
// Convert radians to degrees
|
||||
rd.dec = Units::radiansToDegrees(dec_rad);
|
||||
ha_deg = Units::radiansToDegrees(ha_rad);
|
||||
|
||||
// Calculate right ascension in decimal hours
|
||||
rd.ra = modulo((lst_deg - ha_deg) / (360.0/24.0), 24.0);
|
||||
|
||||
return rd;
|
||||
}
|
||||
|
||||
// Needs to work for negative a
|
||||
double Astronomy::modulo(double a, double b)
|
||||
{
|
||||
@ -493,10 +534,11 @@ double Astronomy::lstAndRAToLongitude(double lst, double raHours)
|
||||
}
|
||||
|
||||
// Return right ascension and declination of North Galactic Pole in J2000 Epoch
|
||||
// http://www.lsc-group.phys.uwm.edu/lal/lsd/node1777.html
|
||||
void Astronomy::northGalacticPoleJ2000(double& ra, double& dec)
|
||||
{
|
||||
ra = 12 + 51.4 / 60.0;
|
||||
dec = 27.13;
|
||||
ra = 192.8594813/15.0;
|
||||
dec = 27.1282511;
|
||||
}
|
||||
|
||||
// Convert from equatorial to Galactic coordinates, J2000 Epoch
|
||||
@ -511,40 +553,24 @@ void Astronomy::equatorialToGalactic(double ra, double dec, double& l, double& b
|
||||
const double ngpRaRad = Units::degreesToRadians(ngpRa * 15.0);
|
||||
const double ngpDecRad = Units::degreesToRadians(ngpDec);
|
||||
|
||||
// Calculate galactic latitude for North Celestial pole, J2000
|
||||
const double ncpLRad = Units::degreesToRadians(122.93192);
|
||||
|
||||
// Calculate galactic longitude in radians
|
||||
double bRad = asin(sin(ngpDecRad)*sin(decRad)+cos(ngpDecRad)*cos(decRad)*cos(raRad - ngpRaRad));
|
||||
|
||||
// Find the two possible solutions for galactic longitude in radians
|
||||
double rhs1 = cos(decRad)*sin(raRad-ngpRaRad)/cos(bRad);
|
||||
double rhs2 = (-cos(decRad)*sin(ngpDecRad)*cos(raRad-ngpRaRad)+sin(decRad)*cos(ngpDecRad))/cos(bRad);
|
||||
double l1 = ncpLRad - asin(rhs1);
|
||||
double l2 = ncpLRad - acos(rhs2);
|
||||
// Calculate galactic latitiude in radians
|
||||
double lRad = atan2(sin(decRad)-sin(bRad)*sin(ngpDecRad), cos(decRad)*cos(ngpDecRad)*sin(raRad - ngpRaRad));
|
||||
|
||||
// Plug them back in and select solution which is valid for both equations
|
||||
// (Error should be 0, but we have to allow for small numerical differences)
|
||||
// There's probably a better way to solve this.
|
||||
double l1lhs1 = sin(ncpLRad - l1);
|
||||
double l1lhs2 = cos(ncpLRad - l1);
|
||||
double l2lhs1 = sin(ncpLRad - l2);
|
||||
double l2lhs2 = cos(ncpLRad - l2);
|
||||
double l1Diff = abs(l1lhs1 - rhs1) + abs(l1lhs2 - rhs2);
|
||||
double l2Diff = abs(l2lhs1 - rhs1) + abs(l2lhs2 - rhs2);
|
||||
double lRad;
|
||||
if (l1Diff < l2Diff)
|
||||
lRad = l1;
|
||||
else
|
||||
lRad = l2;
|
||||
// Ascending node of the galactic plane in degrees
|
||||
double lAscend = 33.0;
|
||||
|
||||
// Convert to degrees in range -90,90 and 0,360
|
||||
b = Units::radiansToDegrees(bRad);
|
||||
l = Units::radiansToDegrees(lRad);
|
||||
if (l < 0.0)
|
||||
l = Units::radiansToDegrees(lRad) + lAscend;
|
||||
if (l < 0.0) {
|
||||
l += 360.0;
|
||||
if (l > 360.0)
|
||||
}
|
||||
if (l > 360.0) {
|
||||
l -= 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
// The following functions are from Starlink Positional Astronomy Library
|
||||
|
@ -46,6 +46,7 @@ public:
|
||||
|
||||
static RADec precess(RADec rd_in, double jd_from, double jd_to);
|
||||
static AzAlt raDecToAzAlt(RADec rd, double latitude, double longitude, QDateTime dt, bool j2000=true);
|
||||
static RADec azAltToRaDec(AzAlt aa, double latitude, double longitude, QDateTime dt);
|
||||
|
||||
static double localSiderealTime(QDateTime dateTime, double longitude);
|
||||
|
||||
|
@ -142,9 +142,50 @@ public:
|
||||
return hours + minutes * 1.0f/60.0f + seconds * 1.0f/(60.0f*60.0f);
|
||||
}
|
||||
|
||||
// Also supports decimal degrees
|
||||
static bool degreeMinuteAndSecondsToDecimalDegrees(const QString& string, float& degrees)
|
||||
{
|
||||
QRegExp decimal("(-?[0-9]+(\\.[0-9]+)?)");
|
||||
if (decimal.exactMatch(string))
|
||||
{
|
||||
degrees = decimal.capturedTexts()[1].toFloat();
|
||||
return true;
|
||||
}
|
||||
QRegExp dms(QString("(-)?([0-9]+)[%1d](([0-9]+)['m](([0-9]+(\\.[0-9]+)?)[\"s])?)?").arg(QChar(0xb0)));
|
||||
if (dms.exactMatch(string))
|
||||
{
|
||||
float d = 0.0f;
|
||||
bool neg = false;
|
||||
for (int i = 0; i < dms.captureCount(); i++) {
|
||||
qDebug() << dms.capturedTexts()[i];
|
||||
}
|
||||
if (dms.captureCount() >= 1) {
|
||||
neg = dms.capturedTexts()[1] == "-";
|
||||
}
|
||||
if (dms.captureCount() >= 3) {
|
||||
d = dms.capturedTexts()[2].toFloat();
|
||||
}
|
||||
float m = 0.0f;
|
||||
if (dms.captureCount() >= 5) {
|
||||
m = dms.capturedTexts()[4].toFloat();
|
||||
}
|
||||
float s = 0.0f;
|
||||
if (dms.captureCount() >= 7) {
|
||||
s = dms.capturedTexts()[6].toFloat();
|
||||
}
|
||||
qDebug() << neg << d << m << s;
|
||||
degrees = d + m/60.0 + s/(60.0*60.0);
|
||||
if (neg) {
|
||||
degrees = -degrees;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static QString decimalDegreesToDegreeMinutesAndSeconds(float decimal, int secondsFieldWidth=5)
|
||||
{
|
||||
float v, d, m, s;
|
||||
double v, d, m, s;
|
||||
int neg;
|
||||
|
||||
v = decimal;
|
||||
@ -162,7 +203,7 @@ public:
|
||||
|
||||
static QString decimalDegreesToDegreesAndMinutes(float decimal)
|
||||
{
|
||||
float v, d, m;
|
||||
double v, d, m;
|
||||
int neg;
|
||||
|
||||
v = decimal;
|
||||
@ -172,12 +213,21 @@ public:
|
||||
v -= d;
|
||||
v *= 60.0;
|
||||
m = round(v);
|
||||
if (m == 60)
|
||||
{
|
||||
if (neg) {
|
||||
d--;
|
||||
} else {
|
||||
d++;
|
||||
}
|
||||
m = 0;
|
||||
}
|
||||
return QString("%1%2%3%4'").arg(neg ? "-" : "").arg((int)d).arg(QChar(0xb0)).arg((int)m, 2, 10, QChar('0'));
|
||||
}
|
||||
|
||||
static QString decimalDegreesToDegrees(float decimal)
|
||||
{
|
||||
float v, d;
|
||||
double v, d;
|
||||
int neg;
|
||||
|
||||
v = decimal;
|
||||
@ -189,7 +239,7 @@ public:
|
||||
|
||||
static QString decimalHoursToHoursMinutesAndSeconds(float decimal, int precision=2)
|
||||
{
|
||||
float v, h, m, s;
|
||||
double v, h, m, s;
|
||||
|
||||
v = decimal;
|
||||
v = fabs(v);
|
||||
@ -218,7 +268,6 @@ public:
|
||||
QRegExp dms(QString("([0-9]+)[%1d]([0-9]+)['m]([0-9]+(\\.[0-9]+)?)[\"s]([NS]) *,? *([0-9]+)[%1d]([0-9]+)['m]([0-9]+(\\.[0-9]+)?)[\"s]([EW])").arg(QChar(0xb0)));
|
||||
if (dms.exactMatch(string))
|
||||
{
|
||||
qDebug() << "Captured: " << dms.capturedTexts();
|
||||
float latD = dms.capturedTexts()[1].toFloat();
|
||||
float latM = dms.capturedTexts()[2].toFloat();
|
||||
float latS = dms.capturedTexts()[3].toFloat();
|
||||
@ -233,8 +282,6 @@ public:
|
||||
longitude = lonD + lonM/60.0 + lonS/(60.0*60.0);
|
||||
if (!east)
|
||||
longitude = -longitude;
|
||||
qDebug() << "Lat " << latitude;
|
||||
qDebug() << "Long " << longitude;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -28,6 +28,7 @@ set(sdrgui_SOURCES
|
||||
gui/cwkeyergui.cpp
|
||||
gui/devicestreamselectiondialog.cpp
|
||||
gui/deviceuserargsdialog.cpp
|
||||
gui/dmsspinbox.cpp
|
||||
gui/editcommanddialog.cpp
|
||||
gui/externalclockbutton.cpp
|
||||
gui/externalclockdialog.cpp
|
||||
@ -114,6 +115,7 @@ set(sdrgui_HEADERS
|
||||
gui/cwkeyergui.h
|
||||
gui/devicestreamselectiondialog.h
|
||||
gui/deviceuserargsdialog.h
|
||||
gui/dmsspinbox.h
|
||||
gui/doublevalidator.h
|
||||
gui/editcommanddialog.h
|
||||
gui/externalclockbutton.h
|
||||
|
126
sdrgui/gui/dmsspinbox.cpp
Normal file
126
sdrgui/gui/dmsspinbox.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2021 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <QLineEdit>
|
||||
|
||||
#include "util/units.h"
|
||||
|
||||
#include "dmsspinbox.h"
|
||||
|
||||
DMSSpinBox::DMSSpinBox(QWidget *parent) :
|
||||
QAbstractSpinBox(parent),
|
||||
m_value(0.0),
|
||||
m_minimum(0.0),
|
||||
m_maximum(360.0),
|
||||
m_units(DM)
|
||||
{
|
||||
setButtonSymbols(QAbstractSpinBox::UpDownArrows);
|
||||
connect(lineEdit(), SIGNAL(editingFinished()), this, SLOT(on_lineEdit_editingFinished()));
|
||||
}
|
||||
|
||||
bool DMSSpinBox::hasValue() const
|
||||
{
|
||||
return m_text.isNull();
|
||||
}
|
||||
|
||||
double DMSSpinBox::value() const
|
||||
{
|
||||
return m_value;
|
||||
}
|
||||
|
||||
void DMSSpinBox::setValue(double degrees)
|
||||
{
|
||||
if (m_value != degrees)
|
||||
{
|
||||
m_value = degrees;
|
||||
if (m_value < m_minimum) {
|
||||
m_value = m_minimum;
|
||||
}
|
||||
if (m_value > m_maximum) {
|
||||
m_value = m_maximum;
|
||||
}
|
||||
m_text = QString();
|
||||
emit valueChanged(m_value);
|
||||
}
|
||||
lineEdit()->setText(convertDegreesToText(m_value));
|
||||
}
|
||||
|
||||
void DMSSpinBox::setRange(double minimum, double maximum)
|
||||
{
|
||||
m_minimum = minimum;
|
||||
m_maximum = maximum;
|
||||
}
|
||||
|
||||
void DMSSpinBox::setUnits(DisplayUnits units)
|
||||
{
|
||||
m_units = units;
|
||||
if (hasValue()) {
|
||||
lineEdit()->setText(convertDegreesToText(m_value));
|
||||
}
|
||||
}
|
||||
|
||||
void DMSSpinBox::setText(QString text)
|
||||
{
|
||||
m_text = text;
|
||||
lineEdit()->setText(m_text);
|
||||
}
|
||||
|
||||
void DMSSpinBox::stepBy(int steps)
|
||||
{
|
||||
if (hasValue()) {
|
||||
setValue(m_value + (double)steps);
|
||||
}
|
||||
}
|
||||
|
||||
QAbstractSpinBox::StepEnabled DMSSpinBox::stepEnabled() const
|
||||
{
|
||||
QAbstractSpinBox::StepEnabled enabled = QAbstractSpinBox::StepNone;
|
||||
|
||||
if (hasValue() && (m_value < m_maximum)) {
|
||||
enabled |= QAbstractSpinBox::StepUpEnabled;
|
||||
}
|
||||
if (hasValue() && (m_value > m_minimum)) {
|
||||
enabled |= QAbstractSpinBox::StepDownEnabled;
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
QString DMSSpinBox::convertDegreesToText(double degrees)
|
||||
{
|
||||
if (m_units == DMS) {
|
||||
return Units::decimalDegreesToDegreeMinutesAndSeconds(degrees);
|
||||
} else if (m_units == DM) {
|
||||
return Units::decimalDegreesToDegreesAndMinutes(degrees);
|
||||
} else if (m_units == D) {
|
||||
return Units::decimalDegreesToDegrees(degrees);
|
||||
} else {
|
||||
return QString("%1").arg(degrees, 0, 'f', 2);
|
||||
}
|
||||
}
|
||||
|
||||
void DMSSpinBox::on_lineEdit_editingFinished()
|
||||
{
|
||||
QString text = lineEdit()->text().trimmed();
|
||||
float decimal;
|
||||
if (Units::degreeMinuteAndSecondsToDecimalDegrees(text, decimal)) {
|
||||
setValue(decimal);
|
||||
} else {
|
||||
qDebug() << "DMSSpinBox::on_lineEdit_editingFinished: Invalid format: " << text;
|
||||
}
|
||||
}
|
||||
|
62
sdrgui/gui/dmsspinbox.h
Normal file
62
sdrgui/gui/dmsspinbox.h
Normal file
@ -0,0 +1,62 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (C) 2021 Jon Beniston, M7RCE //
|
||||
// //
|
||||
// This program is free software; you can redistribute it and/or modify //
|
||||
// it under the terms of the GNU General Public License as published by //
|
||||
// the Free Software Foundation as version 3 of the License, or //
|
||||
// (at your option) any later version. //
|
||||
// //
|
||||
// This program is distributed in the hope that it will be useful, //
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
|
||||
// GNU General Public License V3 for more details. //
|
||||
// //
|
||||
// You should have received a copy of the GNU General Public License //
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef SDRGUI_GUI_DMSSPINBOX_H
|
||||
#define SDRGUI_GUI_DMSSPINBOX_H
|
||||
|
||||
#include <QAbstractSpinBox>
|
||||
|
||||
#include "export.h"
|
||||
|
||||
// Spin box for displaying degrees in decimal or degrees, minutes and seconds format
|
||||
// Can also be assigned a text string
|
||||
class SDRGUI_API DMSSpinBox : public QAbstractSpinBox {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum DisplayUnits {DMS, DM, D, Decimal};
|
||||
|
||||
explicit DMSSpinBox(QWidget *parent = nullptr);
|
||||
bool hasValue() const;
|
||||
double value() const;
|
||||
void setValue(double degrees);
|
||||
void setRange(double minimum, double maximum);
|
||||
void setUnits(DisplayUnits units);
|
||||
void setText(QString text);
|
||||
virtual void stepBy(int steps) override;
|
||||
|
||||
protected:
|
||||
|
||||
virtual QAbstractSpinBox::StepEnabled stepEnabled() const override;
|
||||
QString convertDegreesToText(double degrees);
|
||||
|
||||
private:
|
||||
QString m_text;
|
||||
double m_value;
|
||||
double m_minimum;
|
||||
double m_maximum;
|
||||
DisplayUnits m_units;
|
||||
|
||||
signals:
|
||||
void valueChanged(double newValue);
|
||||
|
||||
private slots:
|
||||
void on_lineEdit_editingFinished();
|
||||
|
||||
};
|
||||
|
||||
#endif // SDRGUI_GUI_DMSSPINBOX_H
|
Loading…
Reference in New Issue
Block a user