StrengthLine.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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. if(a>0)
  121. {
  122. if(b<0)
  123. {
  124. if((a*imgWidth+b) > imgHeight)
  125. {
  126. // |------------------------------------------|
  127. // | * |
  128. // | * |
  129. // | * |
  130. // | * |
  131. // | * |
  132. // | * |
  133. // | * |
  134. // | * |
  135. // | * |
  136. // |------------------------------------------|
  137. return std::make_pair (new QPoint (-1*(b/a), 0),
  138. new QPoint ((imgHeight-b)/a, imgHeight));
  139. }
  140. else
  141. {
  142. // |------------------------------------------|
  143. // | *** |
  144. // | *** |
  145. // | *** |
  146. // | *** |
  147. // | ***|
  148. // | |
  149. // | |
  150. // | |
  151. // | |
  152. // |------------------------------------------|
  153. return std::make_pair (new QPoint (-1*(b/a), 0),
  154. new QPoint (imgWidth, a * imgWidth + b));
  155. }
  156. }
  157. else // a>0 and b>0
  158. {
  159. if((a*imgWidth+b) > imgHeight)
  160. {
  161. // |------------------------------------------|
  162. // | |
  163. // | |
  164. // |* |
  165. // | * |
  166. // | * |
  167. // | * |
  168. // | * |
  169. // | * |
  170. // | * |
  171. // |------------------------------------------|
  172. return std::make_pair (new QPoint (0, b),
  173. new QPoint ((imgHeight -b )/a, imgHeight));
  174. }
  175. else
  176. {
  177. // |------------------------------------------|
  178. // | |
  179. // |******** |
  180. // | ******** |
  181. // | ******** |
  182. // | ******** |
  183. // | ******** |
  184. // | **|
  185. // | |
  186. // | |
  187. // |------------------------------------------|
  188. return std::make_pair (new QPoint (0, b),
  189. new QPoint (imgWidth, a*imgWidth+b));
  190. }
  191. }
  192. }
  193. else // a<0
  194. {
  195. if((a*imgWidth+b)>0)
  196. {
  197. if(b > imgHeight)
  198. {
  199. // |------------------------------------------|
  200. // | |
  201. // | |
  202. // | * |
  203. // | * |
  204. // | * |
  205. // | * |
  206. // | * |
  207. // | * |
  208. // | * |
  209. // |------------------------------------------|
  210. return std::make_pair (new QPoint ((imgHeight-b)/a, imgHeight),
  211. new QPoint (imgWidth, a*imgWidth+b));
  212. }
  213. else
  214. {
  215. // |------------------------------------------|
  216. // | |
  217. // | |
  218. // | **|
  219. // | ******** |
  220. // | ******** |
  221. // | ******** |
  222. // | ******** |
  223. // |******** |
  224. // | |
  225. // |------------------------------------------|
  226. return std::make_pair (new QPoint (0, b),
  227. new QPoint (imgWidth, a * imgWidth + b));
  228. }
  229. }
  230. else // a>0 and (a*imgWidth+b) < 0
  231. {
  232. if(b > imgHeight)
  233. {
  234. // |------------------------------------------|
  235. // | * |
  236. // | * |
  237. // | * |
  238. // | * |
  239. // | * |
  240. // | * |
  241. // | * |
  242. // | * |
  243. // | * |
  244. // |------------------------------------------|
  245. return std::make_pair (new QPoint (-1*(b/a), 0),
  246. new QPoint ((imgHeight-b)/a, imgHeight));
  247. }
  248. else
  249. {
  250. // |------------------------------------------|
  251. // | * |
  252. // | * |
  253. // | * |
  254. // | * |
  255. // |* |
  256. // | |
  257. // | |
  258. // | |
  259. // | |
  260. // |------------------------------------------|
  261. return std::make_pair (new QPoint (0, b),
  262. new QPoint (-1*(b/a), 0));
  263. }
  264. }
  265. }
  266. return std::make_pair (new QPoint (*p1),
  267. new QPoint (*p2));
  268. }
  269. float StrengthLine::ea_score(const StrengthLine *sl, double imgWidth, double imgHeight) const
  270. {
  271. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  272. std::pair < QPoint*, QPoint* > pointsSL1 = this->interpolateToEdge (imgWidth, imgHeight);
  273. std::pair < QPoint*, QPoint* > pointsSL2 = sl->interpolateToEdge (imgWidth, imgHeight);
  274. QPoint* p1SL1 = std::get < 0 > (pointsSL1);
  275. QPoint* p2SL1 = std::get < 1 > (pointsSL1);
  276. QPoint* p1SL2 = std::get < 0 > (pointsSL2);
  277. QPoint* p2SL2 = std::get < 1 > (pointsSL2);
  278. float u[2] = {p2SL1->x()-p1SL1->x(), p2SL1->y()-p1SL1->y()};
  279. float v[2] = {p2SL2->x()-p1SL2->x(), p2SL2->y()-p1SL2->y()};
  280. float normU = sqrt(u[0]*u[0]+u[1]*u[1]);
  281. float normV = sqrt(v[0]*v[0]+v[1]*v[1]);
  282. u[0]=u[0]/normU;
  283. u[1]=u[1]/normU;
  284. v[0]=v[0]/normV;
  285. v[1]=v[1]/normV;
  286. float angle = 0;
  287. if((u[0]!=v[0]) || (u[1]!=v[1]))
  288. {
  289. float prodScal=u[0]*v[0]+u[1]*v[1];
  290. // In case of number approximation...
  291. if(prodScal>1)
  292. prodScal=1;
  293. if(prodScal<-1)
  294. prodScal=-1;
  295. angle = acos(prodScal);
  296. }
  297. float sT = 1 - (angle/(M_PI/2));
  298. float midSL1X = ((p1SL1->x() + p2SL1->x())/2.0)/(imgWidth*1.0);
  299. float midSL1Y = ((p1SL1->y() + p2SL1->y())/2.0)/(imgHeight*1.0);
  300. float midSL2X = ((p1SL2->x() + p2SL2->x())/2.0)/(imgWidth*1.0);
  301. float midSL2Y = ((p1SL2->y() + p2SL2->y())/2.0)/(imgHeight*1.0);
  302. float sd = 1 - sqrt(((midSL1X-midSL2X)*(midSL1X-midSL2X))+((midSL1Y-midSL2Y)*(midSL1Y-midSL2Y)));
  303. return ((sT*sd)*(sT*sd));
  304. }
  305. StrengthLine* StrengthLine::getRandomLine (QImage * img)
  306. {
  307. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  308. int x1rand = std::rand() % img->width();
  309. int x2rand = std::rand() % img->width();
  310. int y1rand = std::rand() % img->height();
  311. int y2rand = std::rand() % img->height();
  312. while ( x1rand == x2rand && y1rand==y2rand )
  313. {
  314. x2rand = std::rand() % img->width();
  315. y2rand = std::rand() % img->height();
  316. }
  317. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  318. }
  319. StrengthLine* StrengthLine::getRandomLine (int width, int height)
  320. {
  321. std::srand(static_cast<unsigned int>(std::time(nullptr)+std::rand()));
  322. int x1rand = std::rand() % width;
  323. int x2rand = std::rand() % width;
  324. int y1rand = std::rand() % height;
  325. int y2rand = std::rand() % height;
  326. while ( x1rand == x2rand && y1rand==y2rand )
  327. {
  328. x2rand = std::rand() % width;
  329. y2rand = std::rand() % height;
  330. }
  331. return new StrengthLine( new QPoint(x1rand, y1rand), new QPoint(x2rand, y2rand) );
  332. }