StrengthLine.cpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  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 (p1 == NULL || p2 == NULL)
  31. throw std::
  32. invalid_argument ("Points defining a strength line can't be NULL.");
  33. if (ax == bx && ay == by)
  34. throw std::
  35. invalid_argument ("Points defining a strength line can't be equals.");
  36. this->p1 = new QPoint(ax, ay);
  37. this->p2 = new QPoint(bx, by);
  38. }
  39. StrengthLine::StrengthLine (QPoint * p1, QPoint * p2)
  40. {
  41. if (p1 == NULL || p2 == NULL)
  42. throw std::
  43. invalid_argument ("Points defining a strength line can't be NULL.");
  44. if (p1->x () == p2->x () && p1->y () == p2->y ())
  45. throw std::
  46. invalid_argument ("Points defining a strength line can't be equals.");
  47. this->p1 = p1;
  48. this->p2 = p2;
  49. }
  50. QPoint*
  51. StrengthLine::getP1() const
  52. {
  53. return new QPoint(*p1);
  54. }
  55. QPoint*
  56. StrengthLine::getP2() const
  57. {
  58. return new QPoint(*p2);
  59. }
  60. std::pair < float, float >
  61. StrengthLine::equation () const
  62. {
  63. // This method can be called only if a and b are
  64. // not aligned into a vertical or horizontal line
  65. float a = ((p1->y () - p2->y ()) * 1.0) / (p1->x () - p2->x ());
  66. float b = p1->y () - a * p1->x ();
  67. return std::make_pair (a, b);
  68. }
  69. std::pair < QPoint *, QPoint * >StrengthLine::toDraw (QImage * img) const
  70. {
  71. return this->toDraw(img->width(), img->height());
  72. }
  73. std::pair < QPoint *, QPoint * >StrengthLine::toDraw (int imgWidth, int imgHeight) const
  74. {
  75. // Methode qui va calculer les points pour l'affichage des droites
  76. // sur l'image passées en paramètre. Calcul rapide donc
  77. // les points peuvent sortir de l'image.
  78. // ligne verticale
  79. if (p1->x () == p2->x ())
  80. return std::make_pair (new QPoint (p1->x (), 0),
  81. new QPoint (p1->x (), imgHeight));
  82. // ligne horizontale
  83. if (p1->y () == p2->y ())
  84. return std::make_pair (new QPoint (0, p1->y ()),
  85. new QPoint (imgWidth, p1->y ()));
  86. // Equation de la droite et on prend les points gauche et droite de la ligne
  87. std::pair < float, float >
  88. eq = this->equation ();
  89. float
  90. a = std::get < 0 > (eq);
  91. float
  92. b = std::get < 1 > (eq);
  93. return std::make_pair (new QPoint (0, b),
  94. new QPoint (imgWidth, imgWidth * a + b));
  95. }
  96. std::pair < QPoint *, QPoint * >StrengthLine::interpolateToEdge (QImage * img) const
  97. {
  98. return this->interpolateToEdge(img->width(), img->height());
  99. }
  100. std::pair < QPoint *, QPoint * >StrengthLine::interpolateToEdge (int imgWidth, int imgHeight) const
  101. {
  102. // Methode qui va calculer les points sur les bords des images
  103. // en fonction des deux points attributs qui définissent
  104. // la ligne.
  105. // ligne verticale
  106. if (p1->x () == p2->x ())
  107. return std::make_pair (new QPoint (p1->x (), 0),
  108. new QPoint (p1->x (), imgHeight));
  109. // ligne horizontale
  110. if (p1->y () == p2->y ())
  111. return std::make_pair (new QPoint (0, p1->y ()),
  112. new QPoint (imgWidth, p1->y ()));
  113. // Equation de la droite et on prend les points gauche et droite de la ligne
  114. std::pair < float, float >
  115. eq = this->equation ();
  116. float
  117. a = std::get < 0 > (eq);
  118. float
  119. b = std::get < 1 > (eq);
  120. QPoint *p1 = new QPoint(0, b);
  121. QPoint *p2 = new QPoint(imgWidth, imgWidth * a + b);
  122. // Si le point de gauche est trop bas
  123. if(b < 0)
  124. {
  125. p1->setX(-b/a);
  126. p1->setY(0);
  127. }
  128. // Si le point de gauche est trop haut
  129. if(b > imgHeight)
  130. {
  131. p1->setX((imgHeight-b)/a);
  132. p1->setY(imgHeight);
  133. }
  134. // Si le point de droite est trop bas
  135. if((imgWidth * a + b) < 0)
  136. {
  137. p2->setX(-b/a);
  138. p2->setY(0);
  139. }
  140. // Si le point de droite est trop haut
  141. if((imgWidth * a + b) > imgHeight)
  142. {
  143. p2->setX((imgHeight-b)/a);
  144. p2->setY(imgHeight);
  145. }
  146. return std::make_pair (p1, p2);
  147. }
  148. float StrengthLine::ea_score(const StrengthLine *sl, double imgWidth, double imgHeight) const
  149. {
  150. std::pair < QPoint*, QPoint* > pointsSL1 = this->interpolateToEdge (imgWidth, imgHeight);
  151. std::pair < QPoint*, QPoint* > pointsSL2 = sl->interpolateToEdge (imgWidth, imgHeight);
  152. QPoint* p1SL1 = std::get < 0 > (pointsSL1);
  153. QPoint* p2SL1 = std::get < 1 > (pointsSL1);
  154. QPoint* p1SL2 = std::get < 0 > (pointsSL2);
  155. QPoint* p2SL2 = std::get < 1 > (pointsSL2);
  156. float u[2] = {p2SL1->x()-p1SL1->x(), p2SL1->y()-p1SL1->y()};
  157. float v[2] = {p2SL2->x()-p1SL2->x(), p2SL2->y()-p1SL2->y()};
  158. float normU = sqrt(u[0]*u[0]+u[1]*u[1]);
  159. float normV = sqrt(v[0]*v[0]+v[1]*v[1]);
  160. u[0]=u[0]/normU;
  161. u[1]=u[1]/normU;
  162. v[0]=v[0]/normV;
  163. v[1]=v[1]/normV;
  164. float angle = 0;
  165. if((u[0]!=v[0]) || (u[1]!=v[1]))
  166. {
  167. float prodScal=u[0]*v[0]+u[1]*v[1];
  168. // In case of number approximation...
  169. if(prodScal>1)
  170. prodScal=1;
  171. if(prodScal<-1)
  172. prodScal=-1;
  173. angle = acos(prodScal);
  174. }
  175. float sT = 1 - (angle/(M_PI/2));
  176. float midSL1X = ((p1SL1->x() + p2SL1->x())/2.0)/(imgWidth*1.0);
  177. float midSL1Y = ((p1SL1->y() + p2SL1->y())/2.0)/(imgHeight*1.0);
  178. float midSL2X = ((p1SL2->x() + p2SL2->x())/2.0)/(imgWidth*1.0);
  179. float midSL2Y = ((p1SL2->y() + p2SL2->y())/2.0)/(imgHeight*1.0);
  180. float sd = 1 - sqrt(((midSL1X-midSL2X)*(midSL1X-midSL2X))+((midSL1Y-midSL2Y)*(midSL1Y-midSL2Y)));
  181. return ((sT*sd)*(sT*sd));
  182. }
  183. StrengthLine* StrengthLine::getRandomLine (QImage * img)
  184. {
  185. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  186. int x1rand = std::rand() % img->width();
  187. int x2rand = std::rand() % img->width();
  188. int y1rand = std::rand() % img->height();
  189. int y2rand = std::rand() % img->height();
  190. while ( x1rand == x2rand && y1rand==y2rand )
  191. {
  192. x2rand = std::rand() % img->width();
  193. y2rand = std::rand() % img->height();
  194. }
  195. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  196. }
  197. StrengthLine* StrengthLine::getRandomLine (int width, int height)
  198. {
  199. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  200. int x1rand = std::rand() % width;
  201. int x2rand = std::rand() % width;
  202. int y1rand = std::rand() % height;
  203. int y2rand = std::rand() % height;
  204. while ( x1rand == x2rand && y1rand==y2rand )
  205. {
  206. x2rand = std::rand() % width;
  207. y2rand = std::rand() % height;
  208. }
  209. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  210. }