PlaqueBase.cpp 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992
  1. /**********************************************************************\
  2. Fichier : Plaque.cpp
  3. Date : 18/04/98
  4. Version : 1.100
  5. Description : classe de calcul & affichage d'une épaisseur de plaque
  6. |**********************************************************************|
  7. Bugs:
  8. Notes:
  9. |**********************************************************************|
  10. Historique :
  11. 18/04/98 1.100 : Optimisation (2x plus rapide)
  12. Suppression de l'utilisation d'une region pour la mesure,
  13. la figure est trop complexe est beaucoup de points sont
  14. oubliés (il suffit de l'afficher dans OnDraw pour s'en rendre
  15. compte).
  16. Suppression de m_nPointsDedans, qui au vu de l'algo était le nombre
  17. de points à l'extérieur de la plaque!!
  18. Réunion de tous les types de mesure de plaque (NB, RGB, manuel) dans
  19. cette classe
  20. 07/02/98 1.000 : Première version
  21. \*******************************************************************/
  22. /*------------------------------------------------------------------\
  23. Includes
  24. \------------------------------------------------------------------*/
  25. #include <QImage>
  26. #include "PlaqueBase.h"
  27. #include "Ressource.h"
  28. #include "MeanEstimate.h"
  29. #include "CPlaqueResult.h"
  30. #include "PlaqueResult.h"
  31. #include "ToolsMath.h"
  32. #include <stdlib.h>
  33. #include <stdio.h>
  34. #include <string.h>
  35. #define sqr(a) ((a) * (a))
  36. inline int Distance2D (const Point &pt1, const Point &pt2)
  37. {
  38. return int (sqrt((double) sqr(pt1.x - pt2.x) + (double) sqr(pt1.y - pt2.y)));
  39. }
  40. CPlaqueBase::CPlaqueBase()
  41. {
  42. m_etudie = NULL;
  43. RAZ();
  44. m_iTache = 0;
  45. m_clrVert = 0 | (255 << 16) | (0 << 8);
  46. m_clrBleue = 0 | (0 << 16) | (255 << 8);
  47. m_debug1 = 1;
  48. m_debug2 = 2;
  49. m_debug3 = 3;
  50. m_debug4 = 4;
  51. m_debug5 = 5;
  52. }
  53. CPlaqueBase::~CPlaqueBase()
  54. {
  55. delete[] m_etudie;
  56. }
  57. void CPlaqueBase::RAZ()
  58. {
  59. m_Etape = etapeRien;
  60. m_nVecteursTrouves = 0;
  61. m_nPtLongeantPlaque = 0;
  62. m_ptInferieur.x = 0;
  63. m_ptInferieur.y = 0;
  64. m_pointLimite1.x = 0;
  65. m_pointLimite1.y = 0;
  66. m_pointLimite2.x = 0;
  67. m_pointLimite2.y = 0;
  68. m_iMax = 0;
  69. m_IntervallesIntensite[0] = 0;
  70. m_IntervallesIntensite[1] = 0;
  71. m_IntervallesIntensite[2] = 0;
  72. // m_ptList.clear();
  73. }
  74. /*----------------------------------------------------------\
  75. | Mesurer |
  76. |-----------------------------------------------------------|
  77. | DESCRIPTION : |
  78. | On a saisi les segments. Mesurer l'épaisseur de droites |
  79. | perpendiculaires, jusqu'au 1° pt vert |
  80. | précédemment coloré par Threshold (). |
  81. |-----------------------------------------------------------|
  82. | PARAMETRES : |
  83. \----------------------------------------------------------*/
  84. const short NORTHOMAX = 1000;
  85. const short NMAXERREURS = 3; // Erreurs avant de déclarer le segment fini
  86. int CPlaqueBase::Mesurer_3 (int iMax)
  87. {
  88. short iVector;
  89. int retour;
  90. m_nSommeLongueurs = 0;
  91. m_nMesures = 0;
  92. m_nLongueurMax = 0;
  93. m_nVecteursTrouves = 0;
  94. m_nMesuresTotal = 0;
  95. // m_ptList.clear();
  96. // Seuillage par propagation
  97. retour = Threshold(iMax);
  98. // Mesurer les limites de la plaque
  99. for (iVector = 0; iVector < (m_nPtLongeantPlaque-1); iVector++)
  100. {
  101. retour = Mesurer_3_1Segment(m_tPtLongeantPlaque [iVector], m_tPtLongeantPlaque [iVector+1]);
  102. }
  103. // Et sa surface, son intensité
  104. retour = CalculerSurfaceEtIntensitePlaque (false);
  105. return retour;
  106. }
  107. //***** Mesurer 1 des segments définis / utilisateur
  108. int CPlaqueBase::Mesurer_3_1Segment (const Point &pt1, const Point &pt2)
  109. {
  110. CVector vectSegment(pt1.x, pt1.y, pt2.x, pt2.y);
  111. CVector vectOrtho;
  112. Point ptAVerifier;
  113. long iSegment, iLong;
  114. bool fFound; // Du segment à mesurer
  115. int nLongueurSegment;
  116. int retour;
  117. retour = 0;
  118. GraphMeanInit();
  119. Point pt( pt1.x, pt1.y );
  120. // Parcourir le segment et, tous les NINTERVALLE, calculer l'épaisseur
  121. vectOrtho = vectSegment.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  122. // la vérification de l'appartenance du point à la région de traitement ralentit certainement
  123. // mais je ne trace apparemment pas les droites de la même manière que Windows et certains
  124. // points des droites des extrémités n'appartiennent pas à la région
  125. for (iSegment = 0; iSegment < vectSegment.Norm (); iSegment++)
  126. {
  127. vectOrtho.MoveTo(vectSegment [iSegment]);
  128. m_nMesuresTotal ++;
  129. // on effectue une mesure seulement lorsque la plaque touche la paroi
  130. // autrement dit, le premier point du vecteur orthogonal ne doit pas être vert
  131. ptAVerifier.x = vectOrtho[1].x;
  132. ptAVerifier.y = vectOrtho[1].y;
  133. // seules les extrémités des segments devraient poser des problèmes d'appartenance
  134. if ( m_rgnATraiter.PtInRegion(&ptAVerifier)
  135. && PointInBufferResult(ptAVerifier)
  136. && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) != m_clrVert) // [LAU - 13/1/2006]
  137. )
  138. {
  139. fFound = false;
  140. // on cherche la fin de la plaque (<=> premier point vert rencontré)
  141. // on s'arrête dès que le point ne fait plus partie de la région de traitement
  142. for (iLong = 2;(!fFound )&& (iLong < NORTHOMAX) && m_rgnATraiter.PtInRegion (&ptAVerifier); iLong++)
  143. {
  144. ptAVerifier.x = vectOrtho [iLong].x;
  145. ptAVerifier.y = vectOrtho [iLong].y;
  146. if ( PointInBufferResult(ptAVerifier)
  147. && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) == m_clrVert)
  148. )
  149. {
  150. fFound = true;
  151. // On a une longueur
  152. nLongueurSegment = iLong - 1;
  153. m_nSommeLongueurs += nLongueurSegment;
  154. m_nMesures ++;
  155. if ((unsigned int) nLongueurSegment > (unsigned int) m_nLongueurMax)
  156. m_nLongueurMax = nLongueurSegment;
  157. if (nLongueurSegment)
  158. GraphMeanAddMeasure(true, nLongueurSegment);
  159. m_tbPtsTrouvesFin [m_nVecteursTrouves] = vectOrtho [iLong];
  160. // Ajouter le segment à ceux à afficher
  161. /* Point pt;
  162. pt.x = vectOrtho[iLong].x;
  163. pt.y = vectOrtho[iLong].y;
  164. m_ptList.push_back( pt );
  165. */
  166. if ((m_nVecteursTrouves + 1) < NBVECTEURSMAX)
  167. {
  168. m_nVecteursTrouves++;
  169. }
  170. }
  171. }
  172. }
  173. }
  174. return retour;
  175. }
  176. /*----------------------------------------------------------\
  177. | CalculerSensVecteurs |
  178. |-----------------------------------------------------------|
  179. | DESCRIPTION : |
  180. | Calcule de quel côté est le pt minimum par rapport aux |
  181. | segments définis par l'utilisateur -> m_nSensTrigo |
  182. |-----------------------------------------------------------|
  183. | PARAMETRES : |
  184. \----------------------------------------------------------*/
  185. void CPlaqueBase::CalculerSensVecteurs()
  186. {
  187. CVector vecteur1erSegment (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
  188. m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y);
  189. if (vecteur1erSegment.m_fHorizontal == true)
  190. {
  191. // Vecteur horizontal : au dessus ou en dessous ?
  192. if (m_tPtLongeantPlaque [0].y < m_ptInferieur.y)
  193. {
  194. // En dessous
  195. if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
  196. {
  197. m_nSensTrigo = 1;
  198. }
  199. else
  200. {
  201. m_nSensTrigo = 0;
  202. }
  203. }
  204. else
  205. {
  206. // Au dessus
  207. if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
  208. {
  209. m_nSensTrigo = 0;
  210. }
  211. else
  212. {
  213. m_nSensTrigo = 1;
  214. }
  215. }
  216. }
  217. else
  218. {
  219. // Vecteur vertical : à gauche ou à droite ?
  220. if (m_tPtLongeantPlaque [0].x < m_ptInferieur.x)
  221. {
  222. // à droite
  223. if (m_tPtLongeantPlaque [0].y > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y)
  224. {
  225. m_nSensTrigo = 0;
  226. }
  227. else
  228. {
  229. m_nSensTrigo = 1;
  230. }
  231. }
  232. else
  233. {
  234. // à gauche
  235. if (m_tPtLongeantPlaque[0].y > m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y)
  236. {
  237. m_nSensTrigo = 1;
  238. }
  239. else
  240. {
  241. m_nSensTrigo = 0;
  242. }
  243. }
  244. }
  245. }
  246. /*----------------------------------------------------------\
  247. | SetRegion |
  248. |-----------------------------------------------------------|
  249. | DESCRIPTION : |
  250. | Crée une région polygonale, composée des segments |
  251. | indiqués par l'utilisateur, de 2 segments sur les côtés, |
  252. | orthogonaux aux 1° et dernier segments utilisateur, |
  253. | et de taille suffisante pour que le m_ptInferieur |
  254. | soit dedans. |
  255. |-----------------------------------------------------------|
  256. | PARAMETRES : |
  257. \----------------------------------------------------------*/
  258. bool CPlaqueBase::SetRegion
  259. ( const CVector &vFirst,
  260. const CVector &vLast,
  261. int iLength )
  262. {
  263. CVector vOrtho;
  264. Point pt( m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y );
  265. vOrtho = vLast.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  266. m_pointLimite1.x = vOrtho[iLength].x;
  267. m_pointLimite1.x = vOrtho[iLength].x;
  268. m_pointLimite1.y = vOrtho[iLength].y;
  269. m_tPtLongeantPlaque[m_nPtLongeantPlaque] = m_pointLimite1;
  270. pt = Point( m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y );
  271. vOrtho = vFirst.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  272. m_pointLimite2.x = vOrtho[iLength].x;
  273. m_pointLimite2.y = vOrtho[iLength].y;
  274. m_tPtLongeantPlaque[m_nPtLongeantPlaque+1] = m_pointLimite2;
  275. // Créer le polygone
  276. m_rgnATraiter.DeleteObject ();
  277. /*
  278. m_debug1 = m_nPtLongeantPlaque;
  279. m_debug2 = m_pointLimite1.x;
  280. m_debug3 = m_pointLimite1.y;
  281. m_debug4 = m_pointLimite2.x;
  282. m_debug5 = m_pointLimite2.y;
  283. */
  284. return (m_rgnATraiter.CreatePolygonRgn (m_tPtLongeantPlaque, m_nPtLongeantPlaque + 2));
  285. } // fin de SetRegion
  286. int CPlaqueBase::ParametrerRegionATraiter ()
  287. {
  288. int retour;
  289. retour = 0;
  290. assert(m_nPtLongeantPlaque >= 2);
  291. // Vecteur entre le 1° et le dernier pt utilisateur
  292. CVector vGlobal (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
  293. m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].y),
  294. // Dernier vecteur tracé (peut être égal à vGlobal)
  295. vFirst (m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y,
  296. m_tPtLongeantPlaque[1].x, m_tPtLongeantPlaque[1].y),
  297. // Dernier vecteur tracé (peut être égal à vFirst)
  298. vLast (m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].y,
  299. m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].y);
  300. Point ptProjected;
  301. int nLongueurPlaque, nDistanceAPtInferieur;
  302. bool fResult;
  303. CalculerSensVecteurs ();
  304. // Longueur de la plaque indiquée par l'utilisateur
  305. nLongueurPlaque = int(vGlobal.Norm());
  306. // Limiter la longueur des segments de côté
  307. Point pti( m_ptInferieur.x, m_ptInferieur.y );
  308. ptProjected.x = vGlobal.Projected (pti).x;
  309. ptProjected.y = vGlobal.Projected (pti).y;
  310. nDistanceAPtInferieur = int (CVector (ptProjected.x, ptProjected.y, m_ptInferieur.x,m_ptInferieur.y).Norm () + 5);
  311. if (nDistanceAPtInferieur > nLongueurPlaque)
  312. nLongueurPlaque = nDistanceAPtInferieur;
  313. // pour optimiser, on diminue la taille des droites orthogonales d'encadrement
  314. // pour que la tache soit à la limite
  315. nLongueurPlaque++;
  316. do
  317. {
  318. nLongueurPlaque--;
  319. fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
  320. } while ((fResult == true) && m_rgnATraiter.PtInRegion (&m_ptInferieur) && (nLongueurPlaque > 1));
  321. if ((fResult == true) && (nLongueurPlaque > 1))
  322. {
  323. nLongueurPlaque++;
  324. fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
  325. }
  326. if (fResult == true)
  327. {
  328. retour = 40;
  329. m_debug1 = nLongueurPlaque;
  330. m_debug2 = ptProjected.x;
  331. m_debug3 = ptProjected.y;
  332. m_debug4 = nDistanceAPtInferieur;
  333. m_debug5 = 2222;
  334. }
  335. if ((fResult == false) || (nLongueurPlaque <= 1))
  336. {
  337. retour = 41;
  338. m_Etape = etapeSegments;
  339. m_nPtLongeantPlaque = 0;
  340. }
  341. else if (m_rgnATraiter.PtInRegion(&m_ptInferieur) == false)
  342. {
  343. retour = 42;
  344. m_Etape = etapeTacheSeuil; // Recommencer cette étape
  345. }
  346. return retour;
  347. }
  348. /*----------------------------------------------------------\
  349. | TraiterPoint |
  350. |-----------------------------------------------------------|
  351. | DESCRIPTION : |
  352. | Propagation à partir du pt minimal : colorer en vert les |
  353. | points sous le seuil indiqué |
  354. | |
  355. | modifié pour limiter la profondeur de récursion |
  356. |-----------------------------------------------------------|
  357. | PARAMETRES : |
  358. \----------------------------------------------------------*/
  359. int CPlaqueBase::TraiterPoint (int x, int y)
  360. {
  361. unsigned char bCheck[9];
  362. int i, xx, yy, xMin, yMin, xMax, yMax;
  363. int retour;
  364. bool bool0;
  365. bool bool1;
  366. bool bc0;
  367. retour = 0;
  368. m_debug1++;
  369. // m_wimg.SaveImgAsRaw();
  370. // if (m_debug1 == 40700)
  371. if (((m_debug1 % 2500) == 0) && (m_debug1 != 0))
  372. {
  373. m_debug1 = m_debug1;
  374. }
  375. assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
  376. SetPixelResult(x, y);
  377. xMin = max(0, x - 1);
  378. xMax = min(x + 1, GetWidth() - 1);
  379. yMin = max(0, y - 1);
  380. yMax = min(y + 1, GetHeight() - 1);
  381. i = 0;
  382. for (xx = xMin; xx <= xMax; xx++)
  383. {
  384. for (yy = yMin; yy <= yMax; yy++)
  385. {
  386. assert (PointInBufferResult(xx, yy));
  387. /* bCheck [i] = ((xx != x) || (yy != y))
  388. && ((m_type == typeRGB) ?
  389. IsColor (xx, yy) :
  390. (GetIntensityResult(xx, yy) <= m_iMax)
  391. )
  392. && (GetPixelResult(xx, yy) != m_clrVert) // [LAU - 13/1/2006]
  393. && m_rgnATraiter.PtInRegion0(xx, yy);
  394. */
  395. bool0 = ((xx != x) || (yy != y));
  396. if ((bool0) && (m_type == typeRGB))
  397. {
  398. bc0 = IsColor (xx, yy);
  399. }
  400. else
  401. {
  402. bc0 = (GetIntensityResult(xx, yy) <= m_iMax);
  403. }
  404. bool1 = (bool0) && (bc0) && (GetPixelResult(xx, yy) != m_clrVert) && m_rgnATraiter.PtInRegion0(xx, yy);
  405. bCheck [i] = bool1 ? 1:0;
  406. i++;
  407. }
  408. }
  409. i = 0;
  410. for (xx = xMin; xx <= xMax; xx++)
  411. {
  412. for (yy = yMin; yy <= yMax; yy++)
  413. {
  414. if ((int) bCheck [i++] > 0)
  415. {
  416. TraiterPoint(xx, yy);
  417. }
  418. }
  419. }
  420. return retour;
  421. }
  422. int CPlaqueBase::Threshold( int iMax )
  423. {
  424. int retour;
  425. // AffectLeadResult();
  426. // Décompte de la répartition des points
  427. m_iMax = iMax;
  428. if (!SuiviContour())
  429. {
  430. m_debug1 = 0;
  431. retour = TraiterPoint(m_ptInferieur.x, m_ptInferieur.y);
  432. }
  433. // Fermeture et effacement des petites régions.
  434. DoClosing();
  435. DoBlobColoring();
  436. return retour;
  437. } // fin de Threshold
  438. /*----------------------------------------------------------\
  439. | Surface de la plaque |
  440. |-----------------------------------------------------------|
  441. | DESCRIPTION : |
  442. | Crée une région polygonale, composée des segments |
  443. | indiqués par l'utilisateur, des extrémités trouvées. |
  444. |-----------------------------------------------------------|
  445. | PARAMETRES : |
  446. \----------------------------------------------------------*/
  447. int CPlaqueBase::CalculerSurfaceEtIntensitePlaque (bool bManuelle)
  448. {
  449. int nIntensite;
  450. Rect rectEnglobant;
  451. Point pt;
  452. int retour;
  453. retour = 0;
  454. if (bManuelle)
  455. {
  456. m_nSensTrigo = 0;
  457. assert (m_nVecteursTrouves == 0); // Pour être sûr
  458. }
  459. // Suppression de l'utilisation d'une region pour la mesure:
  460. // la figure est trop complexe et beaucoup de points sont oubliés
  461. // (il suffit de l'afficher dans OnDraw pour s'en rendre compte).
  462. // seule la région de traitement se monte fiable (peu de points, points éloignés)
  463. rectEnglobant = m_rgnATraiter.GetRgnBox();
  464. m_nPointsDansPlaque = 0;
  465. m_iSommeIntensitesPlaque = 0;
  466. memset (m_IntervallesIntensite, 0, sizeof (m_IntervallesIntensite));
  467. GraphMeanInit();
  468. // Calculer la surface & l'intensité & l'Histogramme.
  469. for (pt.y = rectEnglobant.top; pt.y < rectEnglobant.bottom; pt.y++)
  470. {
  471. for (pt.x = rectEnglobant.left; pt.x < rectEnglobant.right; pt.x++)
  472. {
  473. if ((GetPixelResult(pt.x, pt.y) != m_clrVert) && (m_rgnATraiter.PtInRegion(&pt)))
  474. {
  475. nIntensite = GetIntensityResult(pt); // - m_iTache;
  476. m_nPointsDansPlaque++;
  477. GraphMeanAddMeasure(true, nIntensite);
  478. m_iSommeIntensitesPlaque += nIntensite;
  479. if (nIntensite < 120)
  480. m_IntervallesIntensite [0]++;
  481. else if (nIntensite < 200)
  482. m_IntervallesIntensite [1]++;
  483. else
  484. m_IntervallesIntensite [2]++;
  485. }
  486. }
  487. }
  488. if (m_iSommeIntensitesPlaque < 0)
  489. {
  490. retour = 50;
  491. }
  492. if (bManuelle)
  493. {
  494. int i1, i2;
  495. int nPt1 = -1, nPt2 = -1;
  496. int nDistance = 0, nDistanceMax = 0;
  497. int iSegment, iOrtho1, iOrtho2;
  498. // Calculer la longueur de la plaque (les 2 pts les + éloignés)
  499. for (i1 = 0; i1 < m_nPtLongeantPlaque - 1; i1++)
  500. for (i2 = i1 + 1; i2 < m_nPtLongeantPlaque; i2++)
  501. if ((nDistance = Distance2D (m_tPtLongeantPlaque [i1], m_tPtLongeantPlaque [i2]))
  502. > nDistanceMax)
  503. {
  504. nDistanceMax = nDistance;
  505. nPt1 = i1;
  506. nPt2 = i2;
  507. }
  508. if (!bManuelle) GraphMeanInit();
  509. m_nLongueurMax = 0;
  510. m_nSommeLongueurs = 0;
  511. m_nMesures = 0;
  512. // Calculer la largeur
  513. if (nDistanceMax)
  514. {
  515. // Vecteur le long de la plaque
  516. CVector vectLong (m_tPtLongeantPlaque [nPt1].x,m_tPtLongeantPlaque [nPt1].y,
  517. m_tPtLongeantPlaque [nPt2].x, m_tPtLongeantPlaque [nPt2].y);
  518. CVector vectOrtho;
  519. // Pour essai
  520. if (m_rgnATraiter.PtInRegion0(vectLong [5].x, vectLong [5].y) )
  521. {
  522. retour = 52;
  523. }
  524. if (m_rgnATraiter.PtInRegion0(vectLong [0].x, vectLong [0].y))
  525. {
  526. retour = 52;
  527. }
  528. for (iSegment = 0; iSegment < vectLong.Norm () - 1; iSegment ++)
  529. {
  530. vectOrtho = vectLong.Orthogonal (vectLong [iSegment], 0);
  531. for ( iOrtho1 = 0;
  532. iOrtho1 < vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho1].x,vectOrtho [iOrtho1].y));
  533. iOrtho1 ++);
  534. for ( iOrtho2 = 0;
  535. iOrtho2 > -vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho2].x,vectOrtho [iOrtho2].y));
  536. iOrtho2 --);
  537. if (iOrtho1 - iOrtho2 > ((long) m_nLongueurMax))
  538. m_nLongueurMax = iOrtho1 - iOrtho2;
  539. m_nSommeLongueurs += iOrtho1 - iOrtho2;
  540. if (!bManuelle)
  541. {
  542. if (iOrtho1 - iOrtho2)
  543. GraphMeanAddMeasure(true, iOrtho1 - iOrtho2);
  544. }
  545. m_nMesures++;
  546. }
  547. }
  548. }
  549. return retour;
  550. }
  551. int CPlaqueBase::calculPlaque2(QImage *h_image, int nbPts, unsigned char *points)
  552. {
  553. unsigned char *dadd;
  554. unsigned char a, b, c, d;
  555. Point point;
  556. int npt;
  557. int retour;
  558. m_result = h_image;
  559. if ( !m_etudie )
  560. {
  561. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  562. }
  563. m_wimg.Del();
  564. m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
  565. m_wimg.Fill(0);
  566. m_type = typeManual;
  567. retour = 0;
  568. npt = 0;
  569. dadd = points;
  570. do
  571. {
  572. a = *dadd;
  573. dadd++;
  574. b = *dadd;
  575. dadd++;
  576. c = *dadd;
  577. dadd++;
  578. d = *dadd;
  579. dadd++;
  580. point.x = d;
  581. point.x = point.x | (c << 8);
  582. point.x = point.x | (b << 16);
  583. point.x = point.x | (a << 24);
  584. a = *dadd;
  585. dadd++;
  586. b = *dadd;
  587. dadd++;
  588. c = *dadd;
  589. dadd++;
  590. d = *dadd;
  591. dadd++;
  592. point.y = d;
  593. point.y = point.y | (c << 8);
  594. point.y = point.y | (b << 16);
  595. point.y = point.y | (a << 24);
  596. // if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
  597. {
  598. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
  599. m_nPtLongeantPlaque++;
  600. }
  601. npt++;
  602. } while (npt < nbPts);
  603. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
  604. m_nPtLongeantPlaque++;
  605. retour = CalculerPlaqueManuelle();
  606. return retour;
  607. }
  608. /*----------------------------------------------------------\
  609. | Surface de la plaque |
  610. |-----------------------------------------------------------|
  611. | DESCRIPTION : |
  612. | Crée une région polygonale, composée des segments |
  613. | indiqués par l'utilisateur, des extrémités trouvées. |
  614. |-----------------------------------------------------------|
  615. | PARAMETRES : |
  616. \----------------------------------------------------------*/
  617. int CPlaqueBase::CalculerPlaqueManuelle ()
  618. {
  619. int retour;
  620. // AffectLeadResult();
  621. // Créer le polygone
  622. m_rgnATraiter.DeleteObject();
  623. if (!m_rgnATraiter.CreatePolygonRgn(m_tPtLongeantPlaque, m_nPtLongeantPlaque))
  624. {
  625. retour = 31;
  626. return retour;
  627. }
  628. retour = CalculerSurfaceEtIntensitePlaque(true);
  629. return retour;
  630. }
  631. bool CPlaqueBase::IsBorder(int x, int y)
  632. {
  633. if (!((m_type == typeRGB) ? !IsColor(x, y) :
  634. (GetIntensityResult(x, y) > m_iMax)))
  635. { // On considère qu'il faut être dans la plaque!
  636. return false;
  637. }
  638. // L'aspect static de ces 7 variables est purement dans un but d'économie de mémoire...
  639. static int Xmin, Xmax, xx, Ymin, Ymax, yy, NbPoints;
  640. Xmin = max(0, x-1);
  641. Xmax = min(x+1, GetWidth() - 1);
  642. Ymin = max(0, y-1);
  643. Ymax = min(y+1, GetHeight() - 1);
  644. // On compte le nombre de points en-plaque autour du point étudié
  645. NbPoints = 0;
  646. for(xx = Xmin; xx <= Xmax; xx++)
  647. {
  648. for(yy = Ymin; yy <= Ymax; yy++)
  649. {
  650. if (((xx != x) || (yy != y)) &&
  651. ((m_type == typeRGB) ? !IsColor(xx, yy) :
  652. (GetIntensityResult(xx, yy) > m_iMax)))
  653. {
  654. NbPoints++;
  655. }
  656. }
  657. }
  658. // Ce point est considéré comme faisant partie de la frontière s'il possède
  659. // plus de 3 points en-plaque autour de lui, et s'il n'est pas au milieu de
  660. // la plaque (id est tout point autour de lui en-plaque!)
  661. if ((NbPoints < 3) || (NbPoints == (Xmax-Xmin+1)*(Ymax-Ymin+1)-1))
  662. {
  663. return false;
  664. }
  665. return true;
  666. }
  667. bool CPlaqueBase::SuiviContourLocal(int x, int y, double Xd, double Yd, bool Initialise)
  668. {
  669. static CVector VectBordFin;
  670. static int Width;
  671. static bool* TabPtParcourus = NULL;
  672. // (TabPtParcourus[x+Width*y] == true) s'il le point (x,y) à été parcourus
  673. if (Initialise)
  674. {
  675. Width = GetWidth();
  676. delete [] TabPtParcourus;
  677. TabPtParcourus = new bool[Width * GetHeight()];
  678. memset(TabPtParcourus, 0, Width * GetHeight());
  679. VectBordFin = CVector(m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y,
  680. m_pointLimite1.x,m_pointLimite1.y);
  681. return true;
  682. }
  683. static int xx, yy; // L'aspect static est purement dans un but d'économie de mémoire...
  684. // On marque ce point comme parcourus
  685. TabPtParcourus[x+y*Width] = true;
  686. // On conserve l'ancienne valeur de la couleur pour pouvoir la restaurer
  687. unsigned long OldPixelColor = GetPixelEtudie(x, y);
  688. // On dessine en bleu le point étudié (appartenant à priori au contour)
  689. SetPixelEtudie(x, y, m_clrBleue);
  690. // On a fini avec succes la mesure si le point étudié touche le 2nd bord jaune!
  691. Point pt = VectBordFin.Projected(Point(x,y));
  692. if (Distance2D(Point(pt.x,pt.y) , Point(x,y)) < 2) return true;
  693. int Xbest, Ybest;
  694. Xbest = 0;
  695. Ybest = 0;
  696. // L'aspect static de ces 6 variables est purement dans un but d'économie de mémoire...
  697. static double Vbest;
  698. static bool Valide;
  699. static int M;
  700. static double XdNew;
  701. static double YdNew;
  702. static double PScal;
  703. int dimension = 1;
  704. Valide = false; Vbest = 1;
  705. while (!Valide)
  706. {
  707. Vbest = 0.25 * (4 - dimension);
  708. // On cherche les coordonnées du point ou la "pertinence" est la plus elevé
  709. for(xx = -dimension; xx <= dimension; xx++)
  710. {
  711. for(yy = -dimension; yy <= dimension; yy++)
  712. {
  713. // On regarde la pertinence de ce point environnant...
  714. if ((xx) || (yy))
  715. {
  716. // PScal = (Xd *xx + Yd *yy)/sqrt(xx*xx+yy*yy);
  717. PScal = (Xd *xx + Yd *yy) / sqrt((double) xx * xx + (double) yy * yy); // MAJ2005
  718. if ((PScal > Vbest) &&
  719. (m_rgnATraiter.PtInRegion0(x+xx, y+yy)) &&
  720. (!TabPtParcourus[(x+xx)+(y+yy)*Width]) &&
  721. (IsBorder(x+xx, y+yy)))
  722. {
  723. Vbest = PScal;
  724. Xbest = xx;
  725. Ybest = yy;
  726. }
  727. }
  728. }
  729. }
  730. if (Vbest != 0.25*(4 - dimension))
  731. {
  732. M = max(abs(Xbest), abs(Ybest));
  733. XdNew = Xbest * M + Xd * 3 * dimension;
  734. YdNew = Ybest * M + Yd * 3 * dimension;
  735. PScal = sqrt(XdNew * XdNew + YdNew * YdNew);
  736. if (SuiviContourLocal(x + Xbest / M, y + Ybest / M, XdNew / PScal, YdNew / PScal))
  737. {
  738. Valide = true;
  739. break;
  740. }
  741. else
  742. {
  743. Valide = false; // On restaure cette variable static au cas où...
  744. TabPtParcourus[(x + Xbest) + (y + Ybest) * Width] = true;
  745. }
  746. }
  747. else
  748. {
  749. // On agrandi la fenetre de recherche...
  750. if (dimension < 4) dimension++;
  751. else break;
  752. }
  753. }
  754. if (!Valide)
  755. {
  756. // On remet la couleur initial du point
  757. SetPixelEtudie(x, y, OldPixelColor);
  758. return false;
  759. }
  760. return true;
  761. }
  762. bool CPlaqueBase::SuiviContour()
  763. {
  764. // On cherche le début de la plaque le long du 1er bord jaune
  765. CVector vectSegment(m_pointLimite2.x, m_pointLimite2.y, m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y);
  766. int i = 0;
  767. // On prend le premier point entrant dans la plaque!
  768. while(!((m_type == typeRGB) ?
  769. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  770. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
  771. {
  772. i++;
  773. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  774. }
  775. double Xd, Yd, d; // Direction initiale de recherche de contour...
  776. Xd = m_tPtLongeantPlaque[1].x - m_tPtLongeantPlaque[0].x;
  777. Yd = m_tPtLongeantPlaque[1].y - m_tPtLongeantPlaque[0].y;
  778. d = sqrt(Xd * Xd + Yd * Yd);
  779. Xd = Xd/d;
  780. Yd = Yd/d;
  781. int Compteur = 0;
  782. bool MesureValide = false;
  783. while ((!MesureValide) && (Compteur++ < 5)) // On fait 5 essais maximum...
  784. {
  785. CopyResultDansEtudie();
  786. // On espère avoir une frontière de la plaque valide en ce point...
  787. SuiviContourLocal(0, 0, 0, 0, true); // Initialisation de la fonction!
  788. MesureValide = SuiviContourLocal(vectSegment[i].x, vectSegment[i].y, Xd, Yd);
  789. if (!MesureValide)
  790. {
  791. // La première mesure n'est pas valide...
  792. // On cherche le premier point sortant de la plaque précedemment détectée!
  793. while ((m_type == typeRGB) ?
  794. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  795. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax))
  796. {
  797. i++;
  798. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  799. }
  800. // On cherche le premier point entrant dans la plaque!
  801. while(!((m_type == typeRGB) ?
  802. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  803. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
  804. {
  805. i++;
  806. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  807. }
  808. }
  809. }
  810. if (!MesureValide) return false;
  811. #ifdef _DEBUG
  812. // On affiche le résultat de l'algo de repérage du contour plaque.
  813. // m_pLeadResult->Copy(m_LeadEtudie);
  814. #endif // _DEBUG
  815. // Remplissage de la partie hors-plaque en vert
  816. SuiviContourRemplis(m_ptInferieur.x, m_ptInferieur.y);
  817. return true;
  818. }
  819. void CPlaqueBase::SuiviContourRemplis(int x, int y)
  820. {
  821. assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
  822. assert(GetPixelEtudie(x, y) != m_clrBleue);
  823. assert(GetPixelResult(x, y) != m_clrVert);
  824. int xx, Xmin, Xmax, yy, Ymin, Ymax;
  825. // On dessine en vert le point hors-plaque étudié
  826. SetPixelResult(x, y);
  827. Xmin = max(0, x-2);
  828. Xmax = min(x+2, GetWidth() - 1);
  829. Ymin = max(0, y-2);
  830. Ymax = min(y+2, GetHeight() - 1);
  831. // On compte le nombre de points frontière autour du point étudié
  832. double NbPoints = 0;
  833. for(xx = Xmin; xx <= Xmax; xx++)
  834. {
  835. for(yy = Ymin; yy <= Ymax; yy++)
  836. {
  837. if (((xx != x) || (yy != y)) &&
  838. (GetPixelEtudie(xx, yy) == m_clrBleue))
  839. {
  840. NbPoints++;
  841. }
  842. }
  843. }
  844. // Ce point est à la fin de l'arbre de parcours si il possède 2 points ou plus
  845. // appartenant à la frontières à coté de lui
  846. if (NbPoints > 0) return;
  847. Xmin = max(0, x-1);
  848. Xmax = min(x+1, GetWidth() - 1);
  849. Ymin = max(0, y-1);
  850. Ymax = min(y+1, GetHeight() - 1);
  851. for (xx = Xmin; xx <= Xmax; xx++)
  852. {
  853. for (yy = Ymin; yy <= Ymax; yy++)
  854. {
  855. if (((xx != x) || (yy != y)) &&
  856. (m_rgnATraiter.PtInRegion0(xx, yy)) &&
  857. (GetPixelEtudie(xx, yy) != m_clrBleue) &&
  858. (GetPixelResult(xx, yy) != m_clrVert))
  859. { // Le point (xx, yy) est donc hors-plaque et non traité
  860. SuiviContourRemplis(xx, yy);
  861. }
  862. }
  863. }
  864. }
  865. // [LAU - 2/5/2006] Calcule la somme des longeurs entre les points enregistrés longeant la plaque
  866. double CPlaqueBase::Get_SommeLongueurs()
  867. {
  868. double dist = 0;
  869. if (m_Etape == etapeRien)
  870. {
  871. return (int)dist;
  872. }
  873. for (int i = 0; i < m_nPtLongeantPlaque-1; i++)
  874. {
  875. dist += CVector (m_tPtLongeantPlaque[i].x, m_tPtLongeantPlaque[i].y, m_tPtLongeantPlaque[i+1].x, m_tPtLongeantPlaque[i+1].y).Norm (g_pCurrentScale);
  876. }
  877. return (int) dist;
  878. }
  879. // Algorithme de coloriage de blobs sur l'image d'entrée
  880. // Objectif : enlever les petites régions dans l'image seuillée
  881. bool CPlaqueBase::DoBlobColoring()
  882. {
  883. int x, y, i, indblob, nblob, realblob, ng;
  884. long taille;
  885. img lwimg, lwimg1;
  886. int wdimh, wdimv;
  887. blob m_tblob[MAXBLOB];
  888. Rect rectEnglobant;
  889. rectEnglobant = m_rgnATraiter.GetRgnBox();
  890. wdimh = GetWidth();
  891. wdimv = GetHeight();
  892. lwimg.Create(TYPE_UCHAR, wdimh, wdimv);
  893. lwimg1.Create(TYPE_INT, wdimh, wdimv); // On prend des ints
  894. lwimg.Fill(0);
  895. indblob = 0;
  896. nblob = 0;
  897. // Générer l'image binaire qui va aller à l'algo. du blob coloring
  898. // lwimg
  899. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  900. {
  901. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  902. {
  903. bool fGreen;
  904. fGreen = (GetPixelResult(x, y) == m_clrVert);
  905. if (!fGreen)
  906. {
  907. lwimg.SetValue(x, y, 1);
  908. }
  909. }
  910. }
  911. // Résultat : les blobs sont dans wimg1
  912. nblob = lwimg.BlobColoring(m_tblob, &lwimg1);
  913. // Elimination des petits blobs.
  914. realblob = nblob;
  915. for (i = 1; i <= nblob; i++)
  916. {
  917. taille = lwimg1.GetBlobSize(i);
  918. if ((taille < (wdimh * wdimv) - 1) && (taille <= 50))
  919. {
  920. lwimg1.RemplaceCouleur(i, MAXBLOB+1); // Sur int
  921. }
  922. }
  923. // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
  924. // Mise à jour de lwimg, puis transfert dans l'image d'origine
  925. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  926. {
  927. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  928. {
  929. ng = lwimg1.GetValue(x, y);
  930. if (ng == (MAXBLOB + 1))
  931. {
  932. SetPixelResult(x, y);
  933. }
  934. }
  935. }
  936. if (lwimg.init == 1) lwimg.Del();
  937. if (lwimg1.init == 1) lwimg1.Del();
  938. return true;
  939. }
  940. // Algorithme de fermeture
  941. bool CPlaqueBase::DoClosing()
  942. {
  943. int x, y, ng;
  944. img lwimg, lwimg1;
  945. int wdimh, wdimv;
  946. Rect rectEnglobant;
  947. rectEnglobant = m_rgnATraiter.GetRgnBox();
  948. wdimh = GetWidth();
  949. wdimv = GetHeight();
  950. lwimg.Create(TYPE_USHORT, wdimh, wdimv);
  951. lwimg1.Create(TYPE_USHORT, wdimh, wdimv); // On prend des ints
  952. lwimg.Fill(0);
  953. // Générer l'image binaire qui va aller à l'algo. du blob coloring
  954. // lwimg
  955. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  956. {
  957. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  958. {
  959. if (GetPixelResult(x, y) == m_clrVert)
  960. {
  961. lwimg.SetValue(x, y, 1);
  962. }
  963. }
  964. }
  965. lwimg.BinaryClosing(&lwimg1);
  966. // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
  967. // Mise à jour de lwimg, puis transfert dans l'image d'origine
  968. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  969. {
  970. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  971. {
  972. ng = lwimg1.GetValue(x, y);
  973. if (ng == 1)
  974. {
  975. SetPixelResult(x, y);
  976. }
  977. }
  978. }
  979. if (lwimg.init == 1) lwimg.Del();
  980. if (lwimg1.init == 1) lwimg1.Del();
  981. return true;
  982. }
  983. bool CPlaqueBase::PointInBufferResult(const int& x, const int& y)
  984. {
  985. Point pt(x, y);
  986. // pt.x = x;
  987. // pt.y = y;
  988. return PointInBufferResult(pt);
  989. }
  990. bool CPlaqueBase::PointInBufferResult(const Point& pt)
  991. {
  992. assert( m_result );
  993. int dx = GetWidth();
  994. int dy = GetHeight();
  995. return ( (pt.x >= 0) && (pt.y >= 0) && (pt.x < dx) && (pt.y < dy) );
  996. }
  997. bool CPlaqueBase::IsColor(int x, int y)
  998. {
  999. unsigned char bRed;
  1000. unsigned char bGreen;
  1001. unsigned char bBlue;
  1002. int iRed;
  1003. int iGreen;
  1004. int iBlue;
  1005. // AffectLeadResult();
  1006. QRgb rgb = m_result->pixel( x, y );
  1007. bRed = qRed(rgb);
  1008. bGreen = qGreen(rgb);
  1009. bBlue = qBlue(rgb);
  1010. iRed = (int) bRed;
  1011. iGreen = (int) bGreen;
  1012. iBlue = (int) bBlue;
  1013. // un niveau de gris implique bRed = bGreen = bBlue
  1014. // étant donné que l'image a été numérisé on autorise un delta de 10 entre chaque couleur
  1015. // ex : 190 197 185 est gris, 190 201 190 est en couleur
  1016. return ( (abs (iRed - iGreen) > 30)
  1017. || (abs (iRed - iBlue ) > 30)
  1018. || (abs (iGreen - iBlue ) > 30)
  1019. );
  1020. }
  1021. int CPlaqueBase::GetIntensityResult(const int& x, const int& y)
  1022. {
  1023. Point pt;
  1024. pt.x = x;
  1025. pt.y = y;
  1026. return GetIntensityResult(pt);
  1027. }
  1028. int CPlaqueBase::GetIntensityResult(const Point& pt)
  1029. {
  1030. assert( m_result );
  1031. return qGray(m_result->pixel( pt.x, pt.y ));
  1032. /*
  1033. value = (char) m_result->GetPixel( pt.x, pt.y );
  1034. col = (unsigned char)(value & 0xff);
  1035. return col;
  1036. */
  1037. /*
  1038. #if defined( WIN32 ) && !defined( IMT_DLL ) && !defined( PLAQUE_DLL )
  1039. return GetRValue( m_result->GetPixel( pt.x, pt.y ) );
  1040. #else
  1041. return *m_result->GetPixel( pt.x, pt.y );
  1042. #endif
  1043. */
  1044. }
  1045. unsigned int CPlaqueBase::GetErrorID(void)
  1046. {
  1047. return m_uErrorID;
  1048. }
  1049. /*int CPlaqueBase::TestFantome(QImage *h_image, CPlaqueResult *)
  1050. {
  1051. int i, x, y, nbPts;
  1052. unsigned char *points, *dadd;
  1053. int *input;
  1054. Point pts[12];
  1055. int retour;
  1056. m_result = h_image;
  1057. // m_result.Create(768, 576, 24);
  1058. // m_result.CopyFrom2(h_image);
  1059. //CopieResultSvg();
  1060. nbPts = 6;
  1061. retour = 0;
  1062. points = (unsigned char *) malloc( nbPts * sizeof(unsigned char *) );
  1063. input = (int *) malloc( 4 * sizeof(int) );
  1064. x = 372;
  1065. y = 177;
  1066. pts[0].x = 267;
  1067. pts[0].y = 218;
  1068. pts[1].x = 300;
  1069. pts[1].y = 227;
  1070. pts[2].x = 364;
  1071. pts[2].y = 232;
  1072. pts[3].x = 446;
  1073. pts[3].y = 238;
  1074. pts[4].x = 509;
  1075. pts[4].y = 238;
  1076. pts[5].x = 561;
  1077. pts[5].y = 234;
  1078. dadd = points;
  1079. for (i = 0; i < nbPts; i++)
  1080. {
  1081. input[0] = ((pts[i].x & 0xFF000000) >> 24);
  1082. input[1] = ((pts[i].x & 0x00FF0000) >> 16);
  1083. input[2] = ((pts[i].x & 0x0000FF00) >> 8);
  1084. input[3] = ((pts[i].x & 0x000000FF));
  1085. *dadd = input[0];
  1086. dadd++;
  1087. *dadd = input[1];
  1088. dadd++;
  1089. *dadd = input[2];
  1090. dadd++;
  1091. *dadd = input[3];
  1092. dadd++;
  1093. input[0] = ((pts[i].y & 0xFF000000) >> 24);
  1094. input[1] = ((pts[i].y & 0x00FF0000) >> 16);
  1095. input[2] = ((pts[i].y & 0x0000FF00) >> 8);
  1096. input[3] = ((pts[i].y & 0x000000FF));
  1097. *dadd = input[0];
  1098. dadd++;
  1099. *dadd = input[1];
  1100. dadd++;
  1101. *dadd = input[2];
  1102. dadd++;
  1103. *dadd = input[3];
  1104. dadd++;
  1105. }
  1106. retour = calculPlaque(h_image, x, y, nbPts, points); //, 60, 120
  1107. // m_res->allocate_vectors(m_nPtLongeantPlaque);
  1108. return retour;
  1109. }*/
  1110. int CPlaqueBase::calculPlaque(QImage *h_image, int x, int y, int nbPts, const QList<Point>& pts/*, int seuil1, int seuil2*/)
  1111. {
  1112. Point point;
  1113. int npt;
  1114. int retour;
  1115. //unsigned char *dadd;
  1116. retour = 0;
  1117. unsigned char a, b, c, d;
  1118. m_result = h_image;
  1119. // m_result.Create(768, 576, 24 );
  1120. // m_result.CopyFrom2(h_image);
  1121. m_Etape = etapeRien;
  1122. // C'est le premier octet qui est pris : le rouge.
  1123. m_debug1 = (int) GetIntensityResult(100, 125);
  1124. m_debug2 = (int) GetIntensityResult(200, 170);
  1125. m_debug3 = (int) GetIntensityResult(300, 460);
  1126. m_debug4 = (int) m_result->width();
  1127. m_debug5 = (int) 1;
  1128. //retour = 1999;
  1129. // return retour;
  1130. // Création de m_etudie
  1131. if ( m_Etape == etapeRien )
  1132. {
  1133. if ( !m_etudie )
  1134. {
  1135. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  1136. }
  1137. /* if ( m_etudie )
  1138. {
  1139. m_etudie->Create( GetWidth(), GetHeight(), 24 );
  1140. }
  1141. */
  1142. // 1er Point
  1143. m_Etape = etapeSegments;
  1144. m_wimg.Del();
  1145. m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
  1146. m_wimg.Fill(0);
  1147. }
  1148. retour = 0;
  1149. //dadd = points;
  1150. if (m_Etape == etapeSegments)
  1151. {
  1152. npt = 0;
  1153. do
  1154. {
  1155. /*a = *dadd;
  1156. dadd++;
  1157. b = *dadd;
  1158. dadd++;
  1159. c = *dadd;
  1160. dadd++;
  1161. d = *dadd;
  1162. dadd++;
  1163. point.x = d;
  1164. point.x = point.x | (c << 8);
  1165. point.x = point.x | (b << 16);
  1166. point.x = point.x | (a << 24);
  1167. a = *dadd;
  1168. dadd++;
  1169. b = *dadd;
  1170. dadd++;
  1171. c = *dadd;
  1172. dadd++;
  1173. d = *dadd;
  1174. dadd++;
  1175. point.y = d;
  1176. point.y = point.y | (c << 8);
  1177. point.y = point.y | (b << 16);
  1178. point.y = point.y | (a << 24);*/
  1179. point = pts[npt];
  1180. if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
  1181. {
  1182. if ( m_nPtLongeantPlaque
  1183. && ( (CVector (point.x, point.y, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y).Norm () <= 5)
  1184. || ((m_type == typeManual) && (CVector (point.x, point.y, m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y).Norm () <= 5))
  1185. )
  1186. )
  1187. {
  1188. // si la distance entre deux points est inférieure à 5 pixels, on considère que
  1189. // c'est la fin de la paroi
  1190. if (m_type == typeManual)
  1191. {
  1192. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
  1193. m_nPtLongeantPlaque++;
  1194. retour = CalculerPlaqueManuelle();
  1195. break;
  1196. }
  1197. m_Etape = etapeTacheSeuil;
  1198. }
  1199. else
  1200. {
  1201. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
  1202. m_nPtLongeantPlaque++;
  1203. }
  1204. }
  1205. npt++;
  1206. } while (npt < nbPts);
  1207. m_Etape = etapeTacheSeuil; // Ajouter voir interface
  1208. }
  1209. if (m_Etape == etapeTacheSeuil)
  1210. {
  1211. // Pt indiquant la limite inférieure
  1212. m_ptInferieur.x = x;
  1213. m_ptInferieur.y = y;
  1214. // Calculer la région dans laquelle on coloriera
  1215. retour = ParametrerRegionATraiter ();
  1216. if (retour == 40)
  1217. {
  1218. retour = 20;
  1219. if ( TestCouleur() )
  1220. {
  1221. m_type = typeRGB;
  1222. }
  1223. else
  1224. {
  1225. m_type = typeBW;
  1226. retour = 23;
  1227. }
  1228. // Afficher le bitmap LeadResult seulement si la région est OK
  1229. // est PAS en Release, afin de dissimuler, un peu, la méthode de détection
  1230. m_Etape = etapeReglage;
  1231. // s'il y a une phase de réglage (il n'y en a pas pour la plaque couleur)
  1232. if (m_type == typeRGB)
  1233. {
  1234. m_debug1 = 100;
  1235. retour = Mesurer_3(0); // mesure immédiate
  1236. // retour = m_nVecteursTrouves;
  1237. }
  1238. else
  1239. {
  1240. m_debug1 = 200;
  1241. m_iTache = GetIntensityTache (m_ptInferieur, 7);
  1242. // Calculer le seuil inferieur
  1243. Mesurer_3(m_iTache + 10);
  1244. }
  1245. // AnalysePlaque(seuil1, seuil2);
  1246. }
  1247. }
  1248. return retour;
  1249. }
  1250. int CPlaqueBase::OnLButtonUp(QImage *h_image, int x, int y)
  1251. {
  1252. m_result = h_image;
  1253. // m_result.Create(768, 576, 24 );
  1254. // m_result.CopyFrom2(h_image);
  1255. // Création de m_etudie
  1256. if (m_Etape == etapeRien)
  1257. {
  1258. if ( !m_etudie )
  1259. {
  1260. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  1261. }
  1262. /* m_etudie = new ExtendedImage;
  1263. if ( m_etudie )
  1264. {
  1265. m_etudie->Create( GetWidth(), GetHeight(), 24 );
  1266. }
  1267. */
  1268. }
  1269. return OnLButtonUp(x, y);
  1270. }
  1271. int CPlaqueBase::OnLButtonUp(int x, int y)
  1272. {
  1273. Point point;
  1274. point.x = x;
  1275. point.y = y;
  1276. return OnLButtonUp(point);
  1277. }
  1278. int CPlaqueBase::OnLButtonUp(Point& point)
  1279. {
  1280. int retour;
  1281. int x, y;
  1282. x = point.x;
  1283. y = point.y;
  1284. retour = 0;
  1285. if (m_Etape == etapeRien)
  1286. {
  1287. // 1er Point
  1288. m_Etape = etapeSegments;
  1289. m_wimg.Del();
  1290. m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
  1291. m_wimg.Fill(0);
  1292. }
  1293. if (m_Etape == etapeSegments)
  1294. {
  1295. retour = 9;
  1296. if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
  1297. {
  1298. if ( m_nPtLongeantPlaque
  1299. && ( (CVector (point.x, point.y, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y).Norm () <= 5)
  1300. || ((m_type == typeManual) && (CVector (point.x, point.y, m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y).Norm () <= 5))
  1301. )
  1302. )
  1303. {
  1304. // si la distance entre deux points est inférieure à 5 pixels, on considère que
  1305. // c'est la fin de la paroi
  1306. if (m_type == typeManual)
  1307. {
  1308. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
  1309. m_nPtLongeantPlaque++;
  1310. retour = CalculerPlaqueManuelle();
  1311. // return (retour);
  1312. }
  1313. m_Etape = etapeTacheSeuil;
  1314. // retour = 10;
  1315. // return (retour);
  1316. }
  1317. retour = 11;
  1318. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
  1319. m_nPtLongeantPlaque++;
  1320. }
  1321. }
  1322. else if (m_Etape == etapeTacheSeuil)
  1323. {
  1324. // Pt indiquant la limite inférieure
  1325. m_ptInferieur = point;
  1326. // Calculer la région dans laquelle on coloriera
  1327. retour = ParametrerRegionATraiter ();
  1328. if (retour == 40)
  1329. {
  1330. retour = 20;
  1331. if ( TestCouleur() )
  1332. {
  1333. m_type = typeRGB;
  1334. }
  1335. else
  1336. {
  1337. m_type = typeBW;
  1338. retour = 23;
  1339. }
  1340. //? cursor.Clip (m_pView, NULL); // Cesser le clipping
  1341. // Afficher le bitmap LeadResult seulement si la région est OK
  1342. // est PAS en Release, afin de dissimuler, un peu, la méthode de détection
  1343. m_Etape = etapeReglage;
  1344. // s'il y a une phase de réglage (il n'y en a pas pour la plaque couleur)
  1345. if (m_type == typeRGB)
  1346. {
  1347. Mesurer_3(0); // mesure immédiate
  1348. retour = 22;
  1349. }
  1350. else
  1351. {
  1352. m_iTache = GetIntensityTache (m_ptInferieur, 7);
  1353. // Calculer le seuil inferieur
  1354. Mesurer_3(m_iTache + 10);
  1355. retour = 21;
  1356. }
  1357. }
  1358. }
  1359. else if (m_Etape == etapeReglage)
  1360. {
  1361. retour = 30;
  1362. }
  1363. return retour; // Tous les clics ne sont pas faits
  1364. }
  1365. unsigned char CPlaqueBase::GetIntensityTache(Point& ptCentre, int nRayonTache)
  1366. {
  1367. int nIntensiteTache = 0;
  1368. // Quelle est l'intensité monochrome de la tache autour de ce pt ?
  1369. for (int iX = min (GetWidth()-1, max (0, ptCentre.x - nRayonTache));
  1370. iX <= min (GetWidth()-1, ptCentre.x + nRayonTache); iX++)
  1371. {
  1372. for (int iY = min (GetHeight()-1, max (0, ptCentre.y - nRayonTache));
  1373. iY <= min (GetHeight()-1, ptCentre.y + nRayonTache); iY++)
  1374. {
  1375. nIntensiteTache += GetIntensityResult(iX, iY);
  1376. }
  1377. }
  1378. return (nIntensiteTache / ((nRayonTache * 2 + 1) * (nRayonTache * 2 + 1)));
  1379. }
  1380. double CPlaqueBase::Mean()
  1381. {
  1382. return (m_nMesures ? g_pCurrentScale->DistanceX (double (m_nSommeLongueurs) / m_nMesures) : 0.);
  1383. }
  1384. double CPlaqueBase::Max()
  1385. {
  1386. return (g_pCurrentScale->DistanceX ((long)m_nLongueurMax));
  1387. }
  1388. unsigned char CPlaqueBase::Density()
  1389. {
  1390. int res;
  1391. if (m_nPointsDansPlaque != 0)
  1392. {
  1393. res = max(m_iSommeIntensitesPlaque, 0) / m_nPointsDansPlaque;
  1394. }
  1395. else
  1396. {
  1397. res = 0;
  1398. }
  1399. return ((unsigned char) res);
  1400. }
  1401. // Surface != DistanceX (m_nPointsDansPlaque) !!
  1402. double CPlaqueBase::Surface()
  1403. {
  1404. double dblSide = sqrt ((double) m_nPointsDansPlaque);
  1405. return (g_pCurrentScale->Surface (dblSide, dblSide));
  1406. }
  1407. bool CPlaqueBase::TestCouleur()
  1408. {
  1409. bool isCouleur = false;
  1410. Rect rc;
  1411. int x, y;
  1412. rc = m_rgnATraiter.GetRgnBox();
  1413. m_debug2 = rc.left;
  1414. m_debug3 = rc.left;
  1415. m_debug4 = rc.top;
  1416. m_debug5 = rc.bottom;
  1417. for (x = rc.left; ((x < rc.right) && (isCouleur == false)); x++)
  1418. {
  1419. for (y = rc.top; ((y < rc.bottom) && (isCouleur == false)); y++)
  1420. {
  1421. if ( m_rgnATraiter.PtInRegion0( x, y ) )
  1422. {
  1423. isCouleur = IsColor(x, y);
  1424. if (isCouleur == true)
  1425. {
  1426. x = x;
  1427. y = y;
  1428. isCouleur = IsColor(x, y);
  1429. }
  1430. }
  1431. }
  1432. }
  1433. return isCouleur;
  1434. }
  1435. unsigned long CPlaqueBase::GetPixelResult(const int& x, const int& y)
  1436. {
  1437. Point pt;
  1438. pt.x = x;
  1439. pt.y = y;
  1440. return GetPixelResult(pt);
  1441. }
  1442. unsigned long CPlaqueBase::GetPixelResult(const Point& pt)
  1443. {
  1444. unsigned long color;
  1445. color = 0;
  1446. if (m_wimg.GetValue(pt.x, pt.y) == 1)
  1447. {
  1448. color = m_clrVert;
  1449. }
  1450. // m_wimg.SaveImgAsRaw();
  1451. return color;
  1452. /*
  1453. assert( m_result );
  1454. #if defined( WIN32 ) && !defined( PLAQUE_DLL )
  1455. return m_result->GetPixel( pt.x, pt.y );
  1456. #else
  1457. return *m_result->GetPixel( pt.x, pt.y );
  1458. #endif
  1459. */
  1460. }
  1461. unsigned long CPlaqueBase::GetPixelEtudie(const int& x, const int& y)
  1462. {
  1463. Point pt;
  1464. pt.x = x;
  1465. pt.y = y;
  1466. return GetPixelEtudie(pt);
  1467. }
  1468. unsigned long CPlaqueBase::GetPixelEtudie(const Point& pt)
  1469. {
  1470. assert( m_etudie );
  1471. //#if defined( WIN32 ) && !defined( IMT_DLL ) && !defined( PLAQUE_DLL )
  1472. // return m_etudie->GetPixel( pt.x, pt.y );
  1473. //#else
  1474. //return *m_etudie->GetPixel( pt.x, pt.y );
  1475. return m_etudie[ pt.x + GetWidth() * pt.y ];
  1476. //#endif
  1477. }
  1478. void CPlaqueBase::SetPixelResult(int x, int y)
  1479. {
  1480. m_wimg.SetValue(x, y, 1);
  1481. // m_wimg.SaveImgAsRaw();
  1482. }
  1483. void CPlaqueBase::SetPixelEtudie(Point& pt, unsigned long vColor)
  1484. {
  1485. int x, y;
  1486. x = pt.x;
  1487. y = pt.y;
  1488. // m_etudie->SetPixel(vColor, x, y);
  1489. m_etudie[ x + GetWidth() * y ] = vColor;
  1490. }
  1491. void CPlaqueBase::SetPixelEtudie(int x, int y, unsigned long vColor)
  1492. {
  1493. // m_etudie->SetPixel(vColor, x, y);
  1494. m_etudie[ x + GetWidth() * y ] = vColor;
  1495. }
  1496. int CPlaqueBase::GetWidth()
  1497. {
  1498. return m_result->width();
  1499. }
  1500. int CPlaqueBase::GetHeight()
  1501. {
  1502. return m_result->height();
  1503. }
  1504. // Copie de m_result dans m_etudie
  1505. void CPlaqueBase::CopyResultDansEtudie()
  1506. {
  1507. // m_etudie->Copy2(GetWidth(), GetHeight(), m_result);
  1508. if ( !m_etudie )
  1509. {
  1510. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  1511. }
  1512. int w, h;
  1513. int width = GetWidth();
  1514. int height = GetHeight();
  1515. unsigned long* ptr = m_etudie;
  1516. for ( h = 0; h < height; h++ )
  1517. {
  1518. for ( w = 0; w < width; w++ )
  1519. {
  1520. *ptr++ = GetPixelResult( w, h );
  1521. }
  1522. }
  1523. }
  1524. /*void CPlaqueBase::CopieResultSvg()
  1525. {
  1526. int width = m_result->GetWidth();
  1527. int height = m_result->GetHeight();
  1528. m_result2.Create(width, height, 24 );
  1529. m_result2.CopyFrom2(m_result);
  1530. // m_result.SaveImgAsRaw();
  1531. }*/
  1532. /*void CPlaqueBase::AffectLeadResult()
  1533. {
  1534. m_result->CopyFrom2(&m_result2);
  1535. }*/
  1536. void CPlaqueBase::AnalysePlaque(int seuil1, int seuil2)
  1537. {
  1538. int i, x, y;
  1539. // double dng;
  1540. // int gray;
  1541. int ngLumiere, ngAdventitia;
  1542. // Si la lumière est en Doppler couleur
  1543. if (IsColor(m_ptInferieur.x, m_ptInferieur.y))
  1544. {
  1545. ngLumiere = 0;
  1546. }
  1547. else
  1548. {
  1549. ngLumiere = GetIntensityResult(m_ptInferieur.x, m_ptInferieur.y);
  1550. }
  1551. ngAdventitia = 0;
  1552. for (i = 0; i < m_nPtLongeantPlaque; i++)
  1553. {
  1554. ngAdventitia += GetIntensityResult(m_tPtLongeantPlaque[i].x, m_tPtLongeantPlaque[i].y);
  1555. }
  1556. ngAdventitia = 255;
  1557. Rect rectEnglobant;
  1558. rectEnglobant = m_rgnATraiter.GetRgnBox();
  1559. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  1560. {
  1561. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  1562. {
  1563. bool fGreen;
  1564. fGreen = (GetPixelResult(x, y) == m_clrVert);
  1565. if ( m_rgnATraiter.PtInRegion0( x, y ) && (!fGreen))
  1566. {
  1567. m_wimg.SetValue(x, y, 2);
  1568. // On récupére le niveau de gris de l'image originale
  1569. /* gray = GetIntensityResult(x, y);
  1570. dng = ((double) (gray - ngLumiere) * 195.0 ) / (double) ngAdventitia;
  1571. if (dng < 0) dng = 0;
  1572. if (dng > 195.0) dng = 195.0;
  1573. if (dng <= seuil1)
  1574. {
  1575. m_wimg.SetValue(x, y, 2);
  1576. }
  1577. else if ((dng > seuil1) && (dng <= seuil2))
  1578. {
  1579. m_wimg.SetValue(x, y, 3);
  1580. m_nbPixelsB++;
  1581. }
  1582. else if (dng > seuil2)
  1583. {
  1584. m_wimg.SetValue(x, y, 4);
  1585. m_nbPixelsV++;
  1586. }
  1587. */ }
  1588. }
  1589. }
  1590. // CalculScoreRepartition();
  1591. }
  1592. /*
  1593. void CPlaqueBase::CalculScoreRepartition()
  1594. {
  1595. int nbConnexesR, nbConnexesB, nbConnexesV;
  1596. int nbConnections, x, y, i, offset[8];
  1597. // Tableau des Offsets
  1598. // 4 0 5
  1599. // 3 1
  1600. // 7 2 6
  1601. offset[0] = - m_imgPlaque.dimh;
  1602. offset[1] = 1;
  1603. offset[2] = m_imgPlaque.dimh;
  1604. offset[3] = - 1;
  1605. offset[4] = - 1 - m_imgPlaque.dimh;
  1606. offset[5] = 1 - m_imgPlaque.dimh;
  1607. offset[6] = 1 + m_imgPlaque.dimh;
  1608. offset[7] = - 1 + m_imgPlaque.dimh;
  1609. m_scoreRepartitionR = 0;
  1610. m_scoreRepartitionB = 0;
  1611. m_scoreRepartitionV = 0;
  1612. m_scoreRepartition = 0;
  1613. // Scrutation du rectangle englobant de la plaque
  1614. nbConnexesR = 0;
  1615. nbConnexesB = 0;
  1616. nbConnexesV = 0;
  1617. nbConnections = 0;
  1618. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  1619. {
  1620. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  1621. {
  1622. bool fGreen;
  1623. fGreen = (GetPixelResult(x, y) == m_clrVert);
  1624. if ( m_rgnATraiter.PtInRegion0( x, y ) && (!fGreen))
  1625. {
  1626. for (i = 0; i < m_connexite; i++)
  1627. {
  1628. dadd3 = dadd1 + offset[i];
  1629. if (*dadd3 == 1) // L'autre pixel appartient également à la plaque
  1630. {
  1631. dadd4 = dadd2 + offset[i];
  1632. nbConnections++;
  1633. // Si les 2 couleurs des pixels sont dans la même zone
  1634. if ((*dadd2 <= m_SeuilCouleur1) && (*dadd4 <= m_SeuilCouleur1))
  1635. {
  1636. // Les 2 sont dans le seuil du bas
  1637. nbConnexesR++;
  1638. }
  1639. else if ((*dadd2 > m_SeuilCouleur1) && (*dadd4 > m_SeuilCouleur1) && (*dadd2 <= m_SeuilCouleur2) && (*dadd4 <= m_SeuilCouleur2))
  1640. {
  1641. // Les 2 sont dans le seuil du milieu
  1642. nbConnexesB++;
  1643. }
  1644. else if ((*dadd2 > m_SeuilCouleur2) && (*dadd4 > m_SeuilCouleur2))
  1645. {
  1646. // Les 2 sont dans le seuil du haut
  1647. nbConnexesV++;
  1648. }
  1649. }
  1650. }
  1651. }
  1652. }
  1653. }
  1654. // Score = 0 : tous les pixels sont de la même couleur
  1655. // Score = 100% : Aucun pixel connexe
  1656. if (nbConnections != 0)
  1657. {
  1658. m_scoreRepartitionR = 100.0 - (((double) nbConnexesR / (double) nbConnections) * 100.0);
  1659. m_scoreRepartitionB = 100.0 - (((double) nbConnexesB / (double) nbConnections) * 100.0);
  1660. m_scoreRepartitionV = 100.0 - (((double) nbConnexesV / (double) nbConnections) * 100.0);
  1661. }
  1662. // Score répartition globale
  1663. m_scoreRepartition = ((m_scoreRepartitionR + m_scoreRepartitionB + m_scoreRepartitionV) / 3.0);
  1664. }
  1665. */