plaquebase.cpp 50 KB

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