StrengthLine.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. /*********************************************************************/
  2. /* */
  3. /* Copyright 2022-2023 Rémi Synave - remi.synave@univ-littoral.fr */
  4. /* */
  5. /* This file is part of DSL. */
  6. /* This software uses Qt to build the Graphical User Interface */
  7. /* https://www.qt.io/ */
  8. /* */
  9. /* DSL is free software: you can redistribute it and/or modify */
  10. /* it under the terms of the GNU General Public License as published */
  11. /* by the Free Software Foundation, either version 3 of the License, */
  12. /* or (at your option) any later version. */
  13. /* */
  14. /* DSL is distributed in the hope that it will be useful, */
  15. /* but WITHOUT ANY WARRANTY; without even the implied warranty of */
  16. /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
  17. /* GNU General Public License for more details. */
  18. /* */
  19. /* You should have received a copy of the GNU General Public License */
  20. /* along with DSL. If not, see <http://www.gnu.org/licenses/>. */
  21. /* */
  22. /*********************************************************************/
  23. #include <cstdlib>
  24. #include <ctime>
  25. #include <stdexcept>
  26. #include <QDebug>
  27. #include "StrengthLine.hpp"
  28. StrengthLine::StrengthLine (double ax, double ay, double bx, double by)
  29. {
  30. if (ax == bx && ay == by)
  31. throw std::
  32. invalid_argument ("Points defining a strength line can't be equals.");
  33. this->p1 = new QPoint(ax, ay);
  34. this->p2 = new QPoint(bx, by);
  35. }
  36. StrengthLine::StrengthLine (QPoint * p1, QPoint * p2)
  37. {
  38. if (p1 == NULL || p2 == NULL)
  39. throw std::
  40. invalid_argument ("Points defining a strength line can't be NULL.");
  41. if (p1->x () == p2->x () && p1->y () == p2->y ())
  42. throw std::
  43. invalid_argument ("Points defining a strength line can't be equals.");
  44. this->p1 = p1;
  45. this->p2 = p2;
  46. }
  47. QPoint*
  48. StrengthLine::getP1() const
  49. {
  50. return new QPoint(*p1);
  51. }
  52. QPoint*
  53. StrengthLine::getP2() const
  54. {
  55. return new QPoint(*p2);
  56. }
  57. std::pair < float, float >
  58. StrengthLine::equation () const
  59. {
  60. // This method can be called only if a and b are
  61. // not aligned into a vertical or horizontal line
  62. float a = ((p1->y () - p2->y ()) * 1.0) / (p1->x () - p2->x ());
  63. float b = p1->y () - a * p1->x ();
  64. return std::make_pair (a, b);
  65. }
  66. std::pair < QPoint *, QPoint * >StrengthLine::toDraw (QImage * img) const
  67. {
  68. return this->toDraw(img->width(), img->height());
  69. }
  70. std::pair < QPoint *, QPoint * >StrengthLine::toDraw (int imgWidth, int imgHeight) const
  71. {
  72. // Methode qui va calculer les points pour l'affichage des droites
  73. // sur l'image passées en paramètre. Calcul rapide donc
  74. // les points peuvent sortir de l'image.
  75. // ligne verticale
  76. if (p1->x () == p2->x ())
  77. return std::make_pair (new QPoint (p1->x (), 0),
  78. new QPoint (p1->x (), imgHeight));
  79. // ligne horizontale
  80. if (p1->y () == p2->y ())
  81. return std::make_pair (new QPoint (0, p1->y ()),
  82. new QPoint (imgWidth, p1->y ()));
  83. // Equation de la droite et on prend les points gauche et droite de la ligne
  84. std::pair < float, float >
  85. eq = this->equation ();
  86. float
  87. a = std::get < 0 > (eq);
  88. float
  89. b = std::get < 1 > (eq);
  90. return std::make_pair (new QPoint (0, b),
  91. new QPoint (imgWidth, imgWidth * a + b));
  92. }
  93. std::pair < QPoint *, QPoint * >StrengthLine::interpolateToEdge (QImage * img) const
  94. {
  95. return this->interpolateToEdge(img->width(), img->height());
  96. }
  97. std::pair < QPoint *, QPoint * >StrengthLine::interpolateToEdge (int imgWidth, int imgHeight) const
  98. {
  99. // Methode qui va calculer les points sur les bords des images
  100. // en fonction des deux points attributs qui définissent
  101. // la ligne.
  102. // ligne verticale
  103. if (p1->x () == p2->x ())
  104. return std::make_pair (new QPoint (p1->x (), 0),
  105. new QPoint (p1->x (), imgHeight));
  106. // ligne horizontale
  107. if (p1->y () == p2->y ())
  108. return std::make_pair (new QPoint (0, p1->y ()),
  109. new QPoint (imgWidth, p1->y ()));
  110. // Equation de la droite et on prend les points gauche et droite de la ligne
  111. std::pair < float, float >
  112. eq = this->equation ();
  113. float
  114. a = std::get < 0 > (eq);
  115. float
  116. b = std::get < 1 > (eq);
  117. QPoint *p1 = new QPoint(0, b);
  118. QPoint *p2 = new QPoint(imgWidth, imgWidth * a + b);
  119. // Si le point de gauche est trop bas
  120. if(b < 0)
  121. {
  122. p1->setX(-b/a);
  123. p1->setY(0);
  124. }
  125. // Si le point de gauche est trop haut
  126. if(b > imgHeight)
  127. {
  128. p1->setX((imgHeight-b)/a);
  129. p1->setY(imgHeight);
  130. }
  131. // Si le point de droite est trop bas
  132. if((imgWidth * a + b) < 0)
  133. {
  134. p2->setX(-b/a);
  135. p2->setY(0);
  136. }
  137. // Si le point de droite est trop haut
  138. if((imgWidth * a + b) > imgHeight)
  139. {
  140. p2->setX((imgHeight-b)/a);
  141. p2->setY(imgHeight);
  142. }
  143. return std::make_pair (p1, p2);
  144. }
  145. float StrengthLine::ea_score(const StrengthLine *sl, double imgWidth, double imgHeight) const
  146. {
  147. std::pair < QPoint*, QPoint* > pointsSL1 = this->interpolateToEdge (imgWidth, imgHeight);
  148. std::pair < QPoint*, QPoint* > pointsSL2 = sl->interpolateToEdge (imgWidth, imgHeight);
  149. QPoint* p1SL1 = std::get < 0 > (pointsSL1);
  150. QPoint* p2SL1 = std::get < 1 > (pointsSL1);
  151. QPoint* p1SL2 = std::get < 0 > (pointsSL2);
  152. QPoint* p2SL2 = std::get < 1 > (pointsSL2);
  153. float u[2] = {p2SL1->x()-p1SL1->x(), p2SL1->y()-p1SL1->y()};
  154. float v[2] = {p2SL2->x()-p1SL2->x(), p2SL2->y()-p1SL2->y()};
  155. float normU = sqrt(u[0]*u[0]+u[1]*u[1]);
  156. float normV = sqrt(v[0]*v[0]+v[1]*v[1]);
  157. u[0]=u[0]/normU;
  158. u[1]=u[1]/normU;
  159. v[0]=v[0]/normV;
  160. v[1]=v[1]/normV;
  161. float angle = 0;
  162. if((u[0]!=v[0]) || (u[1]!=v[1]))
  163. {
  164. float prodScal=u[0]*v[0]+u[1]*v[1];
  165. // In case of number approximation...
  166. if(prodScal>1)
  167. prodScal=1;
  168. if(prodScal<-1)
  169. prodScal=-1;
  170. angle = acos(prodScal);
  171. }
  172. float sT = 1 - (angle/(M_PI/2));
  173. float midSL1X = ((p1SL1->x() + p2SL1->x())/2.0)/(imgWidth*1.0);
  174. float midSL1Y = ((p1SL1->y() + p2SL1->y())/2.0)/(imgHeight*1.0);
  175. float midSL2X = ((p1SL2->x() + p2SL2->x())/2.0)/(imgWidth*1.0);
  176. float midSL2Y = ((p1SL2->y() + p2SL2->y())/2.0)/(imgHeight*1.0);
  177. float sd = 1 - sqrt(((midSL1X-midSL2X)*(midSL1X-midSL2X))+((midSL1Y-midSL2Y)*(midSL1Y-midSL2Y)));
  178. return ((sT*sd)*(sT*sd));
  179. }
  180. float StrengthLine::distance(const StrengthLine *sl, double imgWidth, double imgHeight) const
  181. {
  182. return (1 - ea_score(sl, imgWidth, imgHeight));
  183. }
  184. StrengthLine* StrengthLine::getRandomLine (QImage * img)
  185. {
  186. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  187. int x1rand = std::rand() % img->width();
  188. int x2rand = std::rand() % img->width();
  189. int y1rand = std::rand() % img->height();
  190. int y2rand = std::rand() % img->height();
  191. while ( x1rand == x2rand && y1rand==y2rand )
  192. {
  193. x2rand = std::rand() % img->width();
  194. y2rand = std::rand() % img->height();
  195. }
  196. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  197. }
  198. StrengthLine* StrengthLine::getRandomLine (int width, int height)
  199. {
  200. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  201. int x1rand = std::rand() % width;
  202. int x2rand = std::rand() % width;
  203. int y1rand = std::rand() % height;
  204. int y2rand = std::rand() % height;
  205. while ( x1rand == x2rand && y1rand==y2rand )
  206. {
  207. x2rand = std::rand() % width;
  208. y2rand = std::rand() % height;
  209. }
  210. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  211. }
  212. std::ostream& operator<<(std::ostream &o, const StrengthLine sl) {
  213. return o << "(" << sl.p1->x() << " , " << sl.p1->y() << ") - (" << sl.p2->x() << " , " << sl.p2->y() << ")";
  214. }