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

0001 /*  Ekos GuideView
0002     Child of FITSView with few additions necessary for Internal Guider
0003 
0004     SPDX-FileCopyrightText: 2020 Hy Murveit <hy@murveit.com>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "guideview.h"
0010 #include "fitsviewer/fitsdata.h"
0011 
0012 #include <QPainter>
0013 #include <math.h>
0014 
0015 GuideView::GuideView(QWidget *parent, FITSMode mode, FITSScale filter) : FITSView(parent, mode, filter)
0016 {
0017 }
0018 
0019 void GuideView::updateNeighbors()
0020 {
0021     if (newNeighbors)
0022         updateFrame(true);
0023 }
0024 
0025 void GuideView::drawOverlay(QPainter *painter, double scale)
0026 {
0027     Q_UNUSED(scale);
0028 
0029     FITSView::drawOverlay(painter, getScale());
0030 
0031     for (const auto &neighbor : neighbors)
0032         drawNeighbor(painter, neighbor);
0033     newNeighbors = false;
0034 
0035 }
0036 
0037 void GuideView::addGuideStarNeighbor(double targetX, double targetY, bool found,
0038                                      double detectedX, double detectedY, bool isGuideStar)
0039 {
0040     Neighbor n;
0041     n.targetX = targetX;
0042     n.targetY = targetY;
0043     n.found = found;
0044     n.detectedX = detectedX;
0045     n.detectedY = detectedY;
0046     n.isGuideStar = isGuideStar;
0047     neighbors.append(n);
0048     newNeighbors = true;
0049 }
0050 
0051 void GuideView::clearNeighbors()
0052 {
0053     neighbors.clear();
0054 }
0055 
0056 // We draw a circle around each "neighbor" star and draw a line from the guide star to the neighbor
0057 // Which starts at the reticle around the guide star and ends at the circle around the neighbor.
0058 void GuideView::drawNeighbor(QPainter *painter, const Neighbor &neighbor)
0059 {
0060     double origOpacity = painter->opacity();
0061     QPen pen(neighbor.found ? Qt::green : Qt::red);
0062     pen.setWidth(2);
0063     pen.setStyle(Qt::SolidLine);
0064     painter->setPen(pen);
0065     painter->setBrush(Qt::NoBrush);
0066     const double scale = getScale();
0067 
0068     if (!neighbor.isGuideStar)
0069     {
0070         const QPointF center(neighbor.targetX * scale, neighbor.targetY * scale);
0071 
0072         double rawRadius = 10;
0073         if (imageData() != nullptr)
0074             rawRadius = std::min(20.0, std::max(3.0, imageData()->width() / 150.0));
0075 
0076         const double r = rawRadius * scale;
0077         painter->drawEllipse(center, r, r);
0078 
0079         const QRect &box = getTrackingBox();
0080         const int x1 = (box.x() + box.width() / 2.0) * scale;
0081         const int y1 = (box.y() + box.height() / 2.0) * scale;
0082         painter->setOpacity(0.25);
0083         const double dx = neighbor.targetX * scale - x1;
0084         const double dy = neighbor.targetY * scale - y1;
0085 
0086         const double lineLength = std::hypotf(fabs(dx), fabs(dy));
0087 
0088         // f1 indicates the place along line between the guide star and the neighbor star
0089         // where the line should start because it intersects the reticle box around the guide star.
0090         double f1;
0091         if (std::fabs(dx) > std::fabs(dy))
0092         {
0093             const double rBox = scale * box.width() / 2.0;
0094             f1 = std::hypot(rBox, std::fabs(dy) * rBox / std::fabs(dx)) / lineLength;
0095         }
0096         else
0097         {
0098             const double rBox = scale * box.height() / 2.0;
0099             f1 = std::hypotf(rBox, std::fabs(dx) * rBox / std::fabs(dy)) / lineLength;
0100         }
0101         // f2 indicates the place along line between the guide star and the neighbor star
0102         // where the line should stop because it intersects the circle around the neighbor.
0103         const double f2 = 1.0 - (r / lineLength);
0104 
0105         if (f1 < 1 && lineLength > r)
0106             painter->drawLine(x1 + dx * f1, y1 + dy * f1, x1 + dx * f2, y1 + dy * f2);
0107     }
0108     painter->setOpacity(origOpacity);
0109 }