Kstars

houghline.cpp
1/*
2 SPDX-FileCopyrightText: 2019 Patrick Molenaar <pr_molenaar@hotmail.com>
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 */
16HoughLine::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
27QPointF 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
52int HoughLine::getScore() const
53{
54 return score;
55}
56
57double HoughLine::getR() const
58{
59 return r;
60}
61
62double HoughLine::getTheta() const
63{
64 return theta;
65}
66
67void HoughLine::setTheta(const double theta)
68{
69 this->theta = theta;
70}
71
72bool HoughLine::compareByScore(const HoughLine *line1,const HoughLine *line2)
73{
74 return (line1->getScore() < line2->getScore());
75}
76
77bool HoughLine::compareByTheta(const HoughLine *line1,const HoughLine *line2)
78{
79 return (line1->getTheta() < line2->getTheta());
80}
81
82void 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 */
94HoughLine::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
128double 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
134bool 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
154void 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
160void 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}
Line representation for HoughTransform Based on the java implementation found on http://vase....
Definition houghline.h:23
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
HoughLine(double theta, double r, int width, int height, int score)
Initialises the hough line.
Definition houghline.cpp:16
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
qreal length() const const
QPointF p1() const const
QPointF p2() const const
void setP1(const QPointF &p1)
void setP2(const QPointF &p2)
qreal x1() const const
qreal x2() const const
qreal y2() const const
iterator begin()
iterator end()
QList< T > mid(qsizetype pos, qsizetype length) const const
void setX(qreal x)
void setY(qreal y)
qreal x() const const
qreal y() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Fri Jul 26 2024 11:59:52 by doxygen 1.11.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.