File indexing completed on 2024-04-28 15:09:53

0001 /*
0002     SPDX-FileCopyrightText: 2012 Jasem Mutlaq <mutlaqja@ikarustech.com>
0003     SPDX-FileCopyrightText: 2021 Wolfgang Reissenberger <sterne-jaeger@openfuture.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 
0009 #include "guidetargetplot.h"
0010 #include "guidegraph.h"
0011 #include "klocalizedstring.h"
0012 #include "kstarsdata.h"
0013 #include "Options.h"
0014 
0015 
0016 GuideTargetPlot::GuideTargetPlot(QWidget *parent) : QCustomPlot (parent)
0017 {
0018     Q_UNUSED(parent);
0019     //drift plot
0020     double accuracyRadius = Options::guiderAccuracyThreshold();
0021 
0022     setBackground(QBrush(Qt::black));
0023     setSelectionTolerance(10);
0024 
0025     xAxis->setBasePen(QPen(Qt::white, 1));
0026     yAxis->setBasePen(QPen(Qt::white, 1));
0027 
0028     xAxis->setTickPen(QPen(Qt::white, 1));
0029     yAxis->setTickPen(QPen(Qt::white, 1));
0030 
0031     xAxis->setSubTickPen(QPen(Qt::white, 1));
0032     yAxis->setSubTickPen(QPen(Qt::white, 1));
0033 
0034     xAxis->setTickLabelColor(Qt::white);
0035     yAxis->setTickLabelColor(Qt::white);
0036 
0037     xAxis->setLabelColor(Qt::white);
0038     yAxis->setLabelColor(Qt::white);
0039 
0040     xAxis->setLabelFont(QFont(font().family(), 9));
0041     yAxis->setLabelFont(QFont(font().family(), 9));
0042     xAxis->setTickLabelFont(QFont(font().family(), 9));
0043     yAxis->setTickLabelFont(QFont(font().family(), 9));
0044 
0045     xAxis->setLabelPadding(2);
0046     yAxis->setLabelPadding(2);
0047 
0048     xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
0049     yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
0050     xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
0051     yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
0052     xAxis->grid()->setZeroLinePen(QPen(Qt::gray));
0053     yAxis->grid()->setZeroLinePen(QPen(Qt::gray));
0054 
0055     xAxis->setLabel(i18n("dRA (arcsec)"));
0056     yAxis->setLabel(i18n("dDE (arcsec)"));
0057 
0058     xAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0059     yAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0060 
0061     setInteractions(QCP::iRangeZoom);
0062     setInteraction(QCP::iRangeDrag, true);
0063 
0064     addGraph();
0065     graph(GuideGraph::G_RA)->setLineStyle(QCPGraph::lsNone);
0066     graph(GuideGraph::G_RA)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssStar, Qt::gray, 5));
0067 
0068     addGraph();
0069     graph(GuideGraph::G_DEC)->setLineStyle(QCPGraph::lsNone);
0070     graph(GuideGraph::G_DEC)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssPlusCircle, QPen(Qt::yellow, 2), QBrush(),
0071             10));
0072 
0073     setupNSEWLabels();
0074 
0075     // resize(190, 190);
0076     replot();
0077 }
0078 
0079 void GuideTargetPlot::showPoint(double ra, double de)
0080 {
0081     graph(GuideGraph::G_DEC)->data()->clear(); //Clear Guide highlighted point
0082     graph(GuideGraph::G_DEC)->addData(ra, de); //Set guide highlighted point
0083     replot();
0084 }
0085 
0086 void GuideTargetPlot::connectGuider(Ekos::GuideInterface *guider)
0087 {
0088     connect(guider, &Ekos::GuideInterface::newAxisDelta, this, &GuideTargetPlot::setAxisDelta);
0089 }
0090 
0091 void GuideTargetPlot::handleHorizontalPlotSizeChange()
0092 {
0093     resize(size().width(), size().height());
0094     replot();
0095 }
0096 
0097 void GuideTargetPlot::handleVerticalPlotSizeChange()
0098 {
0099     resize(size().width(), size().height());
0100     replot();
0101 }
0102 
0103 void GuideTargetPlot::resize(int w, int h)
0104 {
0105     QCustomPlot::resize(w, h);
0106 
0107     const int accuracyRadius = Options::guiderAccuracyThreshold();
0108     if (w > h)
0109     {
0110         yAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0111         xAxis->setScaleRatio(yAxis, 1.0);
0112     }
0113     else
0114     {
0115         xAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0116         yAxis->setScaleRatio(xAxis, 1.0);
0117     }
0118     replot();
0119 }
0120 
0121 void GuideTargetPlot::buildTarget(double accuracyRadius)
0122 {
0123     if (centralTarget)
0124     {
0125         concentricRings->data()->clear();
0126         redTarget->data()->clear();
0127         yellowTarget->data()->clear();
0128         centralTarget->data()->clear();
0129     }
0130     else
0131     {
0132         concentricRings = new QCPCurve(xAxis, yAxis);
0133         redTarget       = new QCPCurve(xAxis, yAxis);
0134         yellowTarget    = new QCPCurve(xAxis, yAxis);
0135         centralTarget   = new QCPCurve(xAxis, yAxis);
0136     }
0137     const int pointCount = 200;
0138     QVector<QCPCurveData> circleRings(
0139         pointCount * (5)); //Have to multiply by the number of rings, Rings at : 25%, 50%, 75%, 125%, 175%
0140     QVector<QCPCurveData> circleCentral(pointCount);
0141     QVector<QCPCurveData> circleYellow(pointCount);
0142     QVector<QCPCurveData> circleRed(pointCount);
0143 
0144     int circleRingPt = 0;
0145     for (int i = 0; i < pointCount; i++)
0146     {
0147         double theta = i / static_cast<double>(pointCount) * 2 * M_PI;
0148 
0149         for (double ring = 1; ring < 8; ring++)
0150         {
0151             if (ring != 4 && ring != 6)
0152             {
0153                 if (i % (9 - static_cast<int>(ring)) == 0) //This causes fewer points to draw on the inner circles.
0154                 {
0155                     circleRings[circleRingPt] = QCPCurveData(circleRingPt, accuracyRadius * ring * 0.25 * qCos(theta),
0156                                                 accuracyRadius * ring * 0.25 * qSin(theta));
0157                     circleRingPt++;
0158                 }
0159             }
0160         }
0161 
0162         circleCentral[i] = QCPCurveData(i, accuracyRadius * qCos(theta), accuracyRadius * qSin(theta));
0163         circleYellow[i]  = QCPCurveData(i, accuracyRadius * 1.5 * qCos(theta), accuracyRadius * 1.5 * qSin(theta));
0164         circleRed[i]     = QCPCurveData(i, accuracyRadius * 2 * qCos(theta), accuracyRadius * 2 * qSin(theta));
0165     }
0166 
0167     concentricRings->setLineStyle(QCPCurve::lsNone);
0168     concentricRings->setScatterSkip(0);
0169     concentricRings->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, QColor(255, 255, 255, 150), 1));
0170 
0171     concentricRings->data()->set(circleRings, true);
0172     redTarget->data()->set(circleRed, true);
0173     yellowTarget->data()->set(circleYellow, true);
0174     centralTarget->data()->set(circleCentral, true);
0175 
0176     concentricRings->setPen(QPen(Qt::white));
0177     redTarget->setPen(QPen(Qt::red));
0178     yellowTarget->setPen(QPen(Qt::yellow));
0179     centralTarget->setPen(QPen(Qt::green));
0180 
0181     concentricRings->setBrush(Qt::NoBrush);
0182     redTarget->setBrush(QBrush(QColor(255, 0, 0, 50)));
0183     yellowTarget->setBrush(
0184         QBrush(QColor(0, 255, 0, 50))); //Note this is actually yellow.  It is green on top of red with equal opacity.
0185     centralTarget->setBrush(QBrush(QColor(0, 255, 0, 50)));
0186 
0187     if (size().width() > 0)
0188         resize(size().width(), size().height());
0189 }
0190 
0191 void GuideTargetPlot::setupNSEWLabels()
0192 {
0193     //Labels for N/S/E/W
0194     QColor raLabelColor(KStarsData::Instance()->colorScheme()->colorNamed("RAGuideError"));
0195     QColor deLabelColor(KStarsData::Instance()->colorScheme()->colorNamed("DEGuideError"));
0196 
0197     QCPItemText *northLabel = new QCPItemText(this);
0198     northLabel->setColor(deLabelColor);
0199     northLabel->setFont(QFont(font().family(), 9));
0200     northLabel->setText(i18nc("North", "N"));
0201     northLabel->position->setType(QCPItemPosition::ptViewportRatio);
0202     northLabel->position->setCoords(0.25, 0.2);
0203     northLabel->setVisible(true);
0204 
0205     QCPItemText *southLabel = new QCPItemText(this);
0206     southLabel->setColor(deLabelColor);
0207     southLabel->setFont(QFont(font().family(), 9));
0208     southLabel->setText(i18nc("South", "S"));
0209     southLabel->position->setType(QCPItemPosition::ptViewportRatio);
0210     southLabel->position->setCoords(0.25, 0.7);
0211     southLabel->setVisible(true);
0212 
0213     QCPItemText *westLabel = new QCPItemText(this);
0214     westLabel->setColor(raLabelColor);
0215     westLabel->setFont(QFont(font().family(), 9));
0216     westLabel->setText(i18nc("West", "W"));
0217     westLabel->position->setType(QCPItemPosition::ptViewportRatio);
0218     westLabel->position->setCoords(0.8, 0.75);
0219     westLabel->setVisible(true);
0220 
0221     QCPItemText *eastLabel = new QCPItemText(this);
0222     eastLabel->setColor(raLabelColor);
0223     eastLabel->setFont(QFont(font().family(), 9));
0224     eastLabel->setText(i18nc("East", "E"));
0225     eastLabel->position->setType(QCPItemPosition::ptViewportRatio);
0226     eastLabel->position->setCoords(0.3, 0.75);
0227     eastLabel->setVisible(true);
0228 }
0229 
0230 void GuideTargetPlot::autoScaleGraphs(double accuracyRadius)
0231 {
0232     xAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0233     yAxis->setRange(-accuracyRadius * 3, accuracyRadius * 3);
0234     yAxis->setScaleRatio(xAxis, 1.0);
0235     xAxis->setScaleRatio(yAxis, 1.0);
0236     replot();
0237 }
0238 
0239 void GuideTargetPlot::clear()
0240 {
0241     graph(GuideGraph::G_RA)->data()->clear(); //Guide data
0242     graph(GuideGraph::G_DEC)->data()->clear(); //Guide highlighted point
0243     setupNSEWLabels();
0244     replot();
0245 }
0246 
0247 void GuideTargetPlot::setAxisDelta(double ra, double de)
0248 {
0249     //Add to Drift Plot
0250     graph(GuideGraph::G_RA)->addData(ra, de);
0251     if(graphOnLatestPt)
0252     {
0253         graph(GuideGraph::G_DEC)->data()->clear(); //Clear highlighted point
0254         graph(GuideGraph::G_DEC)->addData(ra, de); //Set highlighted point to latest point
0255     }
0256 
0257     if (xAxis->range().contains(ra) == false || yAxis->range().contains(de) == false)
0258     {
0259         setBackground(QBrush(Qt::gray));
0260         QTimer::singleShot(300, this, [ = ]()
0261         {
0262             setBackground(QBrush(Qt::black));
0263             replot();
0264         });
0265     }
0266 
0267     replot();
0268 }