1 /*  Ekos GuideView
2     Child of FITSView with few additions necessary for Internal Guider
3 
4     SPDX-FileCopyrightText: 2020 Hy Murveit <hy@murveit.com>
5 
6     SPDX-License-Identifier: GPL-2.0-or-later
7 */
8 
9 #include "guideview.h"
10 
11 #include <QPainter>
12 #include <math.h>
13 
GuideView(QWidget * parent,FITSMode mode,FITSScale filter)14 GuideView::GuideView(QWidget *parent, FITSMode mode, FITSScale filter) : FITSView(parent, mode, filter)
15 {
16 }
17 
drawOverlay(QPainter * painter,double scale)18 void GuideView::drawOverlay(QPainter *painter, double scale)
19 {
20     Q_UNUSED(scale);
21 
22     FITSView::drawOverlay(painter, getScale());
23 
24     for (const auto &neighbor : neighbors)
25         drawNeighbor(painter, neighbor);
26 }
27 
addGuideStarNeighbor(double targetX,double targetY,bool found,double detectedX,double detectedY,bool isGuideStar)28 void GuideView::addGuideStarNeighbor(double targetX, double targetY, bool found,
29                                      double detectedX, double detectedY, bool isGuideStar)
30 {
31     Neighbor n;
32     n.targetX = targetX;
33     n.targetY = targetY;
34     n.found = found;
35     n.detectedX = detectedX;
36     n.detectedY = detectedY;
37     n.isGuideStar = isGuideStar;
38     neighbors.append(n);
39 }
40 
clearNeighbors()41 void GuideView::clearNeighbors()
42 {
43     neighbors.clear();
44 }
45 
46 // We draw a circle around each "neighbor" star and draw a line from the guide star to the neighbor
47 // Which starts at the reticle around the guide star and ends at the circle around the neighbor.
drawNeighbor(QPainter * painter,const Neighbor & neighbor)48 void GuideView::drawNeighbor(QPainter *painter, const Neighbor &neighbor)
49 {
50     double origOpacity = painter->opacity();
51     QPen pen(neighbor.found ? Qt::green : Qt::red);
52     pen.setWidth(2);
53     pen.setStyle(Qt::SolidLine);
54     painter->setPen(pen);
55     painter->setBrush(Qt::NoBrush);
56     const double scale = getScale();
57 
58     if (!neighbor.isGuideStar)
59     {
60         const QPointF center(neighbor.targetX * scale, neighbor.targetY * scale);
61         const double r = 10.0 * scale;
62         painter->drawEllipse(center, r, r);
63 
64         const QRect &box = getTrackingBox();
65         const int x1 = (box.x() + box.width() / 2.0) * scale;
66         const int y1 = (box.y() + box.height() / 2.0) * scale;
67         painter->setOpacity(0.25);
68         const double dx = neighbor.targetX * scale - x1;
69         const double dy = neighbor.targetY * scale - y1;
70 
71         const double lineLength = std::hypotf(fabs(dx), fabs(dy));
72 
73         // f1 indicates the place along line between the guide star and the neighbor star
74         // where the line should start because it intersects the reticle box around the guide star.
75         double f1;
76         if (std::fabs(dx) > std::fabs(dy))
77         {
78             const double rBox = scale * box.width() / 2.0;
79             f1 = std::hypot(rBox, std::fabs(dy) * rBox / std::fabs(dx)) / lineLength;
80         }
81         else
82         {
83             const double rBox = scale * box.height() / 2.0;
84             f1 = std::hypotf(rBox, std::fabs(dx) * rBox / std::fabs(dy)) / lineLength;
85         }
86         // f2 indicates the place along line between the guide star and the neighbor star
87         // where the line should stop because it intersects the circle around the neighbor.
88         const double f2 = 1.0 - (r / lineLength);
89 
90         if (f1 < 1 && lineLength > r)
91             painter->drawLine(x1 + dx * f1, y1 + dy * f1, x1 + dx * f2, y1 + dy * f2);
92     }
93     painter->setOpacity(origOpacity);
94 }
95