Kstars

houghline.cpp
1 /*
2  SPDX-FileCopyrightText: 2019 Patrick Molenaar <[email protected]>
3 
4  SPDX-License-Identifier: GPL-2.0-or-later
5 */
6 
7 #include "houghline.h"
8 
9 #include <qmath.h>
10 #include <QVector>
11 #include <fits_debug.h>
12 
13 /**
14  * Initialises the hough line
15  */
16 HoughLine::HoughLine(double theta, double r, int width, int height, int score)
17  : QLineF()
18 {
19  this->theta = theta;
20  this->r = r;
21  this->score = score;
22 
23  setP1(RotatePoint(0, r, theta, width, height));
24  setP2(RotatePoint(width - 1, r, theta, width, height));
25 }
26 
27 QPointF HoughLine::RotatePoint(int x1, double r, double theta, int width, int height)
28 {
29  int hx, hy;
30 
31  hx = qFloor((width + 1) / 2.0);
32  hy = qFloor((height + 1) / 2.0);
33 
34  double sinAngle = qSin(-theta);
35  double cosAngle = qCos(-theta);
36 
37  // translate point back to origin:
38  double x2 = x1 - hx;
39  double y2 = r - hy;
40 
41  // rotate point
42  double xnew = x2 * cosAngle - y2 * sinAngle;
43  double ynew = x2 * sinAngle + y2 * cosAngle;
44 
45  // translate point back:
46  x2 = xnew + hx;
47  y2 = ynew + hy;
48 
49  return QPointF(x2, y2);
50 }
51 
52 int HoughLine::getScore() const
53 {
54  return score;
55 }
56 
57 double HoughLine::getR() const
58 {
59  return r;
60 }
61 
62 double HoughLine::getTheta() const
63 {
64  return theta;
65 }
66 
67 void HoughLine::setTheta(const double theta)
68 {
69  this->theta = theta;
70 }
71 
72 bool HoughLine::compareByScore(const HoughLine *line1,const HoughLine *line2)
73 {
74  return (line1->getScore() < line2->getScore());
75 }
76 
77 bool HoughLine::compareByTheta(const HoughLine *line1,const HoughLine *line2)
78 {
79  return (line1->getTheta() < line2->getTheta());
80 }
81 
82 void HoughLine::printHoughLine()
83 {
84  qCDebug(KSTARS_FITS) << "Houghline: [score: " << score << ", r: " << r << ", theta: " << theta << " [rad]="
85  << (theta * 180.0 / M_PI) << " [deg], p1: " << p1().x() << ", " << p1().y() << ", p2: "
86  << p2().x() << ", " << p2().y() << "]";
87 }
88 
89 /**
90  * Sources for intersection and distance calculations came from
91  * http://paulbourke.net/geometry/pointlineplane/
92  * Also check https://doc.qt.io/archives/qt-4.8/qlinef.html for more line methods
93  */
94 HoughLine::IntersectResult HoughLine::Intersect(const HoughLine& other_line, QPointF& intersection)
95 {
96  double denom = ((other_line.p2().y() - other_line.p1().y()) * (p2().x() - p1().x())) -
97  ((other_line.p2().x() - other_line.p1().x()) * (p2().y() - p1().y()));
98 
99  double nume_a = ((other_line.p2().x() - other_line.p1().x()) * (p1().y() - other_line.p1().y())) -
100  ((other_line.p2().y() - other_line.p1().y()) * (p1().x() - other_line.p1().x()));
101 
102  double nume_b = ((p2().x() - p1().x()) * (p1().y() - other_line.p1().y())) -
103  ((p2().y() - p1().y()) * (p1().x() - other_line.p1().x()));
104 
105  if (denom == 0.0f)
106  {
107  if(nume_a == 0.0f && nume_b == 0.0f)
108  {
109  return COINCIDENT;
110  }
111  return PARALLEL;
112  }
113 
114  double ua = nume_a / denom;
115  double ub = nume_b / denom;
116 
117  if(ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f)
118  {
119  // Get the intersection point.
120  intersection.setX(qreal(p1().x() + ua * (p2().x() - p1().x())));
121  intersection.setY(qreal(p1().y() + ua * (p2().y() - p1().y())));
122  return INTERESECTING;
123  }
124 
125  return NOT_INTERESECTING;
126 }
127 
128 double HoughLine::Magnitude(const QPointF& point1, const QPointF& point2)
129 {
130  QPointF vector = point2 - point1;
131  return qSqrt(vector.x() * vector.x() + vector.y() * vector.y());
132 }
133 
134 bool HoughLine::DistancePointLine(const QPointF& point, QPointF& intersection, double& distance)
135 {
136  double lineMag = length();
137 
138  double U = qreal((((point.x() - p1().x()) * (p2().x() - p1().x())) +
139  ((point.y() - p1().y()) * (p2().y() - p1().y()))) /
140  (lineMag * lineMag));
141 
142  if (U < 0.0 || U > 1.0) {
143  return false; // closest point does not fall within the line segment
144  }
145 
146  intersection.setX(p1().x() + U * (p2().x() - p1().x()));
147  intersection.setY(p1().y() + U * (p2().y() - p1().y()));
148 
149  distance = Magnitude(point, intersection);
150 
151  return true;
152 }
153 
154 void HoughLine::Offset(const int offsetX, const int offsetY)
155 {
156  setP1(QPointF(p1().x() + offsetX, p1().y() + offsetY));
157  setP2(QPointF(p2().x() + offsetX, p2().y() + offsetY));
158 }
159 
160 void HoughLine::getSortedTopThreeLines(QVector<HoughLine*> &houghLines, QVector<HoughLine*> &top3Lines)
161 {
162  // Sort houghLines by score (highest scores are clearest lines)
163  // For use of sort compare methods see: https://www.off-soft.net/en/develop/qt/qtb1.html
164  std::sort(houghLines.begin(), houghLines.end(), HoughLine::compareByScore);
165 
166  // Get top three lines (these should represent the three lines matching the bahtinov mask lines
167  top3Lines = houghLines.mid(0, 3);
168  // Verify the angle of these lines with regard to the bahtinov mask angle, correct the angle if necessary
169  HoughLine* lineR = top3Lines[0];
170  HoughLine* lineG = top3Lines[1];
171  HoughLine* lineB = top3Lines[2];
172  double thetaR = lineR->getTheta();
173  double thetaG = lineG->getTheta();
174  double thetaB = lineB->getTheta();
175  // Calculate angle between each line
176  double bahtinovMaskAngle = qDegreesToRadians(20.0 + 5.0); // bahtinov mask angle plus 5 degree margin
177  double dGR = thetaR - thetaG;
178  double dBG = thetaB - thetaG;
179  double dBR = thetaB - thetaR;
180  if (dGR > bahtinovMaskAngle && dBR > bahtinovMaskAngle) {
181  // lineR has theta that is 180 degrees rotated
182  thetaR -= M_PI;
183  // update theta
184  lineR->setTheta(thetaR);
185  }
186  if (dBR > bahtinovMaskAngle && dBG > bahtinovMaskAngle) {
187  // lineB has theta that is 180 degrees rotated
188  thetaB -= M_PI;
189  // update theta
190  lineB->setTheta(thetaB);
191  }
192  if (dGR > bahtinovMaskAngle && dBG > bahtinovMaskAngle) {
193  // lineG has theta that is 180 degrees rotated
194  thetaG -= M_PI;
195  // update theta
196  lineG->setTheta(thetaG);
197  }
198  // Now sort top3lines array according to calculated new angles
199  std::sort(top3Lines.begin(),top3Lines.end(), HoughLine::compareByTheta);
200 }
QVector::iterator begin()
QVector< T > mid(int pos, int length) const const
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
void setX(qreal x)
void setY(qreal y)
qreal length() const const
HoughLine(double theta, double r, int width, int height, int score)
Initialises the hough line.
Definition: houghline.cpp:16
QVector::iterator end()
qreal x() const const
qreal y() const const
void setP1(const QPointF &p1)
void setP2(const QPointF &p2)
qreal y2() const const
IntersectResult Intersect(const HoughLine &other_line, QPointF &intersection)
Sources for intersection and distance calculations came from http://paulbourke.net/geometry/pointline...
Definition: houghline.cpp:94
qreal x1() const const
qreal x2() const const
QPointF p1() const const
QPointF p2() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2022 The KDE developers.
Generated on Fri Aug 12 2022 04:00:54 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.