plaquebase.cpp 50 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991
  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. #define sqr(a) ((a) * (a))
  34. inline int Distance2D (const Point &pt1, const Point &pt2)
  35. {
  36. return int (sqrt((double) sqr(pt1.x - pt2.x) + (double) sqr(pt1.y - pt2.y)));
  37. }
  38. CPlaqueBase::CPlaqueBase()
  39. {
  40. m_etudie = NULL;
  41. RAZ();
  42. m_iTache = 0;
  43. m_clrVert = 0 | (255 << 16) | (0 << 8);
  44. m_clrBleue = 0 | (0 << 16) | (255 << 8);
  45. m_debug1 = 1;
  46. m_debug2 = 2;
  47. m_debug3 = 3;
  48. m_debug4 = 4;
  49. m_debug5 = 5;
  50. }
  51. CPlaqueBase::~CPlaqueBase()
  52. {
  53. delete[] m_etudie;
  54. }
  55. void CPlaqueBase::RAZ()
  56. {
  57. m_Etape = etapeRien;
  58. m_nVecteursTrouves = 0;
  59. m_nPtLongeantPlaque = 0;
  60. m_ptInferieur.x = 0;
  61. m_ptInferieur.y = 0;
  62. m_pointLimite1.x = 0;
  63. m_pointLimite1.y = 0;
  64. m_pointLimite2.x = 0;
  65. m_pointLimite2.y = 0;
  66. m_iMax = 0;
  67. m_IntervallesIntensite[0] = 0;
  68. m_IntervallesIntensite[1] = 0;
  69. m_IntervallesIntensite[2] = 0;
  70. // m_ptList.clear();
  71. }
  72. /*----------------------------------------------------------\
  73. | Mesurer |
  74. |-----------------------------------------------------------|
  75. | DESCRIPTION : |
  76. | On a saisi les segments. Mesurer l'épaisseur de droites |
  77. | perpendiculaires, jusqu'au 1° pt vert |
  78. | précédemment coloré par Threshold (). |
  79. |-----------------------------------------------------------|
  80. | PARAMETRES : |
  81. \----------------------------------------------------------*/
  82. const short NORTHOMAX = 1000;
  83. const short NMAXERREURS = 3; // Erreurs avant de déclarer le segment fini
  84. int CPlaqueBase::Mesurer_3 (int iMax)
  85. {
  86. short iVector;
  87. int retour;
  88. m_nSommeLongueurs = 0;
  89. m_nMesures = 0;
  90. m_nLongueurMax = 0;
  91. m_nVecteursTrouves = 0;
  92. m_nMesuresTotal = 0;
  93. // m_ptList.clear();
  94. // Seuillage par propagation
  95. retour = Threshold(iMax);
  96. // Mesurer les limites de la plaque
  97. for (iVector = 0; iVector < (m_nPtLongeantPlaque-1); iVector++)
  98. {
  99. retour = Mesurer_3_1Segment(m_tPtLongeantPlaque [iVector], m_tPtLongeantPlaque [iVector+1]);
  100. }
  101. // Et sa surface, son intensité
  102. retour = CalculerSurfaceEtIntensitePlaque (false);
  103. return retour;
  104. }
  105. //***** Mesurer 1 des segments définis / utilisateur
  106. int CPlaqueBase::Mesurer_3_1Segment (const Point &pt1, const Point &pt2)
  107. {
  108. CVector vectSegment(pt1.x, pt1.y, pt2.x, pt2.y);
  109. CVector vectOrtho;
  110. Point ptAVerifier;
  111. long iSegment, iLong;
  112. bool fFound; // Du segment à mesurer
  113. int nLongueurSegment;
  114. int retour;
  115. retour = 0;
  116. GraphMeanInit();
  117. Point pt( pt1.x, pt1.y );
  118. // Parcourir le segment et, tous les NINTERVALLE, calculer l'épaisseur
  119. vectOrtho = vectSegment.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  120. // la vérification de l'appartenance du point à la région de traitement ralentit certainement
  121. // mais je ne trace apparemment pas les droites de la même manière que Windows et certains
  122. // points des droites des extrémités n'appartiennent pas à la région
  123. for (iSegment = 0; iSegment < vectSegment.Norm (); iSegment++)
  124. {
  125. vectOrtho.MoveTo(vectSegment [iSegment]);
  126. m_nMesuresTotal ++;
  127. // on effectue une mesure seulement lorsque la plaque touche la paroi
  128. // autrement dit, le premier point du vecteur orthogonal ne doit pas être vert
  129. ptAVerifier.x = vectOrtho[1].x;
  130. ptAVerifier.y = vectOrtho[1].y;
  131. // seules les extrémités des segments devraient poser des problèmes d'appartenance
  132. if ( m_rgnATraiter.PtInRegion(&ptAVerifier)
  133. && PointInBufferResult(ptAVerifier)
  134. && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) != m_clrVert) // [LAU - 13/1/2006]
  135. )
  136. {
  137. fFound = false;
  138. // on cherche la fin de la plaque (<=> premier point vert rencontré)
  139. // on s'arrête dès que le point ne fait plus partie de la région de traitement
  140. for (iLong = 2;(!fFound )&& (iLong < NORTHOMAX) && m_rgnATraiter.PtInRegion (&ptAVerifier); iLong++)
  141. {
  142. ptAVerifier.x = vectOrtho [iLong].x;
  143. ptAVerifier.y = vectOrtho [iLong].y;
  144. if ( PointInBufferResult(ptAVerifier)
  145. && (GetPixelResult(ptAVerifier.x, ptAVerifier.y) == m_clrVert)
  146. )
  147. {
  148. fFound = true;
  149. // On a une longueur
  150. nLongueurSegment = iLong - 1;
  151. m_nSommeLongueurs += nLongueurSegment;
  152. m_nMesures ++;
  153. if ((unsigned int) nLongueurSegment > (unsigned int) m_nLongueurMax)
  154. m_nLongueurMax = nLongueurSegment;
  155. if (nLongueurSegment)
  156. GraphMeanAddMeasure(true, nLongueurSegment);
  157. m_tbPtsTrouvesFin [m_nVecteursTrouves] = vectOrtho [iLong];
  158. // Ajouter le segment à ceux à afficher
  159. /* Point pt;
  160. pt.x = vectOrtho[iLong].x;
  161. pt.y = vectOrtho[iLong].y;
  162. m_ptList.push_back( pt );
  163. */
  164. if ((m_nVecteursTrouves + 1) < NBVECTEURSMAX)
  165. {
  166. m_nVecteursTrouves++;
  167. }
  168. }
  169. }
  170. }
  171. }
  172. return retour;
  173. }
  174. /*----------------------------------------------------------\
  175. | CalculerSensVecteurs |
  176. |-----------------------------------------------------------|
  177. | DESCRIPTION : |
  178. | Calcule de quel côté est le pt minimum par rapport aux |
  179. | segments définis par l'utilisateur -> m_nSensTrigo |
  180. |-----------------------------------------------------------|
  181. | PARAMETRES : |
  182. \----------------------------------------------------------*/
  183. void CPlaqueBase::CalculerSensVecteurs()
  184. {
  185. CVector vecteur1erSegment (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
  186. m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y);
  187. if (vecteur1erSegment.m_fHorizontal == true)
  188. {
  189. // Vecteur horizontal : au dessus ou en dessous ?
  190. if (m_tPtLongeantPlaque [0].y < m_ptInferieur.y)
  191. {
  192. // En dessous
  193. if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
  194. {
  195. m_nSensTrigo = 1;
  196. }
  197. else
  198. {
  199. m_nSensTrigo = 0;
  200. }
  201. }
  202. else
  203. {
  204. // Au dessus
  205. if (m_tPtLongeantPlaque [0].x > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].x)
  206. {
  207. m_nSensTrigo = 0;
  208. }
  209. else
  210. {
  211. m_nSensTrigo = 1;
  212. }
  213. }
  214. }
  215. else
  216. {
  217. // Vecteur vertical : à gauche ou à droite ?
  218. if (m_tPtLongeantPlaque [0].x < m_ptInferieur.x)
  219. {
  220. // à droite
  221. if (m_tPtLongeantPlaque [0].y > m_tPtLongeantPlaque [m_nPtLongeantPlaque-1].y)
  222. {
  223. m_nSensTrigo = 0;
  224. }
  225. else
  226. {
  227. m_nSensTrigo = 1;
  228. }
  229. }
  230. else
  231. {
  232. // à gauche
  233. if (m_tPtLongeantPlaque[0].y > m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y)
  234. {
  235. m_nSensTrigo = 1;
  236. }
  237. else
  238. {
  239. m_nSensTrigo = 0;
  240. }
  241. }
  242. }
  243. }
  244. /*----------------------------------------------------------\
  245. | SetRegion |
  246. |-----------------------------------------------------------|
  247. | DESCRIPTION : |
  248. | Crée une région polygonale, composée des segments |
  249. | indiqués par l'utilisateur, de 2 segments sur les côtés, |
  250. | orthogonaux aux 1° et dernier segments utilisateur, |
  251. | et de taille suffisante pour que le m_ptInferieur |
  252. | soit dedans. |
  253. |-----------------------------------------------------------|
  254. | PARAMETRES : |
  255. \----------------------------------------------------------*/
  256. bool CPlaqueBase::SetRegion
  257. ( const CVector &vFirst,
  258. const CVector &vLast,
  259. int iLength )
  260. {
  261. CVector vOrtho;
  262. Point pt( m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y );
  263. vOrtho = vLast.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  264. m_pointLimite1.x = vOrtho[iLength].x;
  265. m_pointLimite1.x = vOrtho[iLength].x;
  266. m_pointLimite1.y = vOrtho[iLength].y;
  267. m_tPtLongeantPlaque[m_nPtLongeantPlaque] = m_pointLimite1;
  268. pt = Point( m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y );
  269. vOrtho = vFirst.Orthogonal (pt, m_nSensTrigo); // 0 = sens inverse trigo
  270. m_pointLimite2.x = vOrtho[iLength].x;
  271. m_pointLimite2.y = vOrtho[iLength].y;
  272. m_tPtLongeantPlaque[m_nPtLongeantPlaque+1] = m_pointLimite2;
  273. // Créer le polygone
  274. m_rgnATraiter.DeleteObject ();
  275. /*
  276. m_debug1 = m_nPtLongeantPlaque;
  277. m_debug2 = m_pointLimite1.x;
  278. m_debug3 = m_pointLimite1.y;
  279. m_debug4 = m_pointLimite2.x;
  280. m_debug5 = m_pointLimite2.y;
  281. */
  282. return (m_rgnATraiter.CreatePolygonRgn (m_tPtLongeantPlaque, m_nPtLongeantPlaque + 2));
  283. } // fin de SetRegion
  284. int CPlaqueBase::ParametrerRegionATraiter ()
  285. {
  286. int retour;
  287. retour = 0;
  288. assert(m_nPtLongeantPlaque >= 2);
  289. // Vecteur entre le 1° et le dernier pt utilisateur
  290. CVector vGlobal (m_tPtLongeantPlaque [0].x, m_tPtLongeantPlaque [0].y,
  291. m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque [m_nPtLongeantPlaque - 1].y),
  292. // Dernier vecteur tracé (peut être égal à vGlobal)
  293. vFirst (m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y,
  294. m_tPtLongeantPlaque[1].x, m_tPtLongeantPlaque[1].y),
  295. // Dernier vecteur tracé (peut être égal à vFirst)
  296. vLast (m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 2].y,
  297. m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].x, m_tPtLongeantPlaque[m_nPtLongeantPlaque - 1].y);
  298. Point ptProjected;
  299. int nLongueurPlaque, nDistanceAPtInferieur;
  300. bool fResult;
  301. CalculerSensVecteurs ();
  302. // Longueur de la plaque indiquée par l'utilisateur
  303. nLongueurPlaque = int(vGlobal.Norm());
  304. // Limiter la longueur des segments de côté
  305. Point pti( m_ptInferieur.x, m_ptInferieur.y );
  306. ptProjected.x = vGlobal.Projected (pti).x;
  307. ptProjected.y = vGlobal.Projected (pti).y;
  308. nDistanceAPtInferieur = int (CVector (ptProjected.x, ptProjected.y, m_ptInferieur.x,m_ptInferieur.y).Norm () + 5);
  309. if (nDistanceAPtInferieur > nLongueurPlaque)
  310. nLongueurPlaque = nDistanceAPtInferieur;
  311. // pour optimiser, on diminue la taille des droites orthogonales d'encadrement
  312. // pour que la tache soit à la limite
  313. nLongueurPlaque++;
  314. do
  315. {
  316. nLongueurPlaque--;
  317. fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
  318. } while ((fResult == true) && m_rgnATraiter.PtInRegion (&m_ptInferieur) && (nLongueurPlaque > 1));
  319. if ((fResult == true) && (nLongueurPlaque > 1))
  320. {
  321. nLongueurPlaque++;
  322. fResult = SetRegion (vFirst, vLast, nLongueurPlaque);
  323. }
  324. if (fResult == true)
  325. {
  326. retour = 40;
  327. m_debug1 = nLongueurPlaque;
  328. m_debug2 = ptProjected.x;
  329. m_debug3 = ptProjected.y;
  330. m_debug4 = nDistanceAPtInferieur;
  331. m_debug5 = 2222;
  332. }
  333. if ((fResult == false) || (nLongueurPlaque <= 1))
  334. {
  335. retour = 41;
  336. m_Etape = etapeSegments;
  337. m_nPtLongeantPlaque = 0;
  338. }
  339. else if (m_rgnATraiter.PtInRegion(&m_ptInferieur) == false)
  340. {
  341. retour = 42;
  342. m_Etape = etapeTacheSeuil; // Recommencer cette étape
  343. }
  344. return retour;
  345. }
  346. /*----------------------------------------------------------\
  347. | TraiterPoint |
  348. |-----------------------------------------------------------|
  349. | DESCRIPTION : |
  350. | Propagation à partir du pt minimal : colorer en vert les |
  351. | points sous le seuil indiqué |
  352. | |
  353. | modifié pour limiter la profondeur de récursion |
  354. |-----------------------------------------------------------|
  355. | PARAMETRES : |
  356. \----------------------------------------------------------*/
  357. int CPlaqueBase::TraiterPoint (int x, int y)
  358. {
  359. unsigned char bCheck[9];
  360. int i, xx, yy, xMin, yMin, xMax, yMax;
  361. int retour;
  362. bool bool0;
  363. bool bool1;
  364. bool bc0;
  365. retour = 0;
  366. m_debug1++;
  367. // m_wimg.SaveImgAsRaw();
  368. // if (m_debug1 == 40700)
  369. if (((m_debug1 % 2500) == 0) && (m_debug1 != 0))
  370. {
  371. m_debug1 = m_debug1;
  372. }
  373. assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
  374. SetPixelResult(x, y);
  375. xMin = max(0, x - 1);
  376. xMax = min(x + 1, GetWidth() - 1);
  377. yMin = max(0, y - 1);
  378. yMax = min(y + 1, GetHeight() - 1);
  379. i = 0;
  380. for (xx = xMin; xx <= xMax; xx++)
  381. {
  382. for (yy = yMin; yy <= yMax; yy++)
  383. {
  384. assert (PointInBufferResult(xx, yy));
  385. /* bCheck [i] = ((xx != x) || (yy != y))
  386. && ((m_type == typeRGB) ?
  387. IsColor (xx, yy) :
  388. (GetIntensityResult(xx, yy) <= m_iMax)
  389. )
  390. && (GetPixelResult(xx, yy) != m_clrVert) // [LAU - 13/1/2006]
  391. && m_rgnATraiter.PtInRegion0(xx, yy);
  392. */
  393. bool0 = ((xx != x) || (yy != y));
  394. if ((bool0) && (m_type == typeRGB))
  395. {
  396. bc0 = IsColor (xx, yy);
  397. }
  398. else
  399. {
  400. bc0 = (GetIntensityResult(xx, yy) <= m_iMax);
  401. }
  402. bool1 = (bool0) && (bc0) && (GetPixelResult(xx, yy) != m_clrVert) && m_rgnATraiter.PtInRegion0(xx, yy);
  403. bCheck [i] = bool1 ? 1:0;
  404. i++;
  405. }
  406. }
  407. i = 0;
  408. for (xx = xMin; xx <= xMax; xx++)
  409. {
  410. for (yy = yMin; yy <= yMax; yy++)
  411. {
  412. if ((int) bCheck [i++] > 0)
  413. {
  414. TraiterPoint(xx, yy);
  415. }
  416. }
  417. }
  418. return retour;
  419. }
  420. int CPlaqueBase::Threshold( int iMax )
  421. {
  422. int retour;
  423. // AffectLeadResult();
  424. // Décompte de la répartition des points
  425. m_iMax = iMax;
  426. if (!SuiviContour())
  427. {
  428. m_debug1 = 0;
  429. retour = TraiterPoint(m_ptInferieur.x, m_ptInferieur.y);
  430. }
  431. // Fermeture et effacement des petites régions.
  432. DoClosing();
  433. DoBlobColoring();
  434. return retour;
  435. } // fin de Threshold
  436. /*----------------------------------------------------------\
  437. | Surface de la plaque |
  438. |-----------------------------------------------------------|
  439. | DESCRIPTION : |
  440. | Crée une région polygonale, composée des segments |
  441. | indiqués par l'utilisateur, des extrémités trouvées. |
  442. |-----------------------------------------------------------|
  443. | PARAMETRES : |
  444. \----------------------------------------------------------*/
  445. int CPlaqueBase::CalculerSurfaceEtIntensitePlaque (bool bManuelle)
  446. {
  447. int nIntensite;
  448. Rect rectEnglobant;
  449. Point pt;
  450. int retour;
  451. retour = 0;
  452. if (bManuelle)
  453. {
  454. m_nSensTrigo = 0;
  455. assert (m_nVecteursTrouves == 0); // Pour être sûr
  456. }
  457. // Suppression de l'utilisation d'une region pour la mesure:
  458. // la figure est trop complexe et beaucoup de points sont oubliés
  459. // (il suffit de l'afficher dans OnDraw pour s'en rendre compte).
  460. // seule la région de traitement se monte fiable (peu de points, points éloignés)
  461. rectEnglobant = m_rgnATraiter.GetRgnBox();
  462. m_nPointsDansPlaque = 0;
  463. m_iSommeIntensitesPlaque = 0;
  464. memset (m_IntervallesIntensite, 0, sizeof (m_IntervallesIntensite));
  465. GraphMeanInit();
  466. // Calculer la surface & l'intensité & l'Histogramme.
  467. for (pt.y = rectEnglobant.top; pt.y < rectEnglobant.bottom; pt.y++)
  468. {
  469. for (pt.x = rectEnglobant.left; pt.x < rectEnglobant.right; pt.x++)
  470. {
  471. if ((GetPixelResult(pt.x, pt.y) != m_clrVert) && (m_rgnATraiter.PtInRegion(&pt)))
  472. {
  473. nIntensite = GetIntensityResult(pt); // - m_iTache;
  474. m_nPointsDansPlaque++;
  475. GraphMeanAddMeasure(true, nIntensite);
  476. m_iSommeIntensitesPlaque += nIntensite;
  477. if (nIntensite < 120)
  478. m_IntervallesIntensite [0]++;
  479. else if (nIntensite < 200)
  480. m_IntervallesIntensite [1]++;
  481. else
  482. m_IntervallesIntensite [2]++;
  483. }
  484. }
  485. }
  486. if (m_iSommeIntensitesPlaque < 0)
  487. {
  488. retour = 50;
  489. }
  490. if (bManuelle)
  491. {
  492. int i1, i2;
  493. int nPt1 = -1, nPt2 = -1;
  494. int nDistance = 0, nDistanceMax = 0;
  495. int iSegment, iOrtho1, iOrtho2;
  496. // Calculer la longueur de la plaque (les 2 pts les + éloignés)
  497. for (i1 = 0; i1 < m_nPtLongeantPlaque - 1; i1++)
  498. for (i2 = i1 + 1; i2 < m_nPtLongeantPlaque; i2++)
  499. if ((nDistance = Distance2D (m_tPtLongeantPlaque [i1], m_tPtLongeantPlaque [i2]))
  500. > nDistanceMax)
  501. {
  502. nDistanceMax = nDistance;
  503. nPt1 = i1;
  504. nPt2 = i2;
  505. }
  506. if (!bManuelle) GraphMeanInit();
  507. m_nLongueurMax = 0;
  508. m_nSommeLongueurs = 0;
  509. m_nMesures = 0;
  510. // Calculer la largeur
  511. if (nDistanceMax)
  512. {
  513. // Vecteur le long de la plaque
  514. CVector vectLong (m_tPtLongeantPlaque [nPt1].x,m_tPtLongeantPlaque [nPt1].y,
  515. m_tPtLongeantPlaque [nPt2].x, m_tPtLongeantPlaque [nPt2].y);
  516. CVector vectOrtho;
  517. // Pour essai
  518. if (m_rgnATraiter.PtInRegion0(vectLong [5].x, vectLong [5].y) )
  519. {
  520. retour = 52;
  521. }
  522. if (m_rgnATraiter.PtInRegion0(vectLong [0].x, vectLong [0].y))
  523. {
  524. retour = 52;
  525. }
  526. for (iSegment = 0; iSegment < vectLong.Norm () - 1; iSegment ++)
  527. {
  528. vectOrtho = vectLong.Orthogonal (vectLong [iSegment], 0);
  529. for ( iOrtho1 = 0;
  530. iOrtho1 < vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho1].x,vectOrtho [iOrtho1].y));
  531. iOrtho1 ++);
  532. for ( iOrtho2 = 0;
  533. iOrtho2 > -vectLong.Norm () && (m_rgnATraiter.PtInRegion0(vectOrtho [iOrtho2].x,vectOrtho [iOrtho2].y));
  534. iOrtho2 --);
  535. if (iOrtho1 - iOrtho2 > ((long) m_nLongueurMax))
  536. m_nLongueurMax = iOrtho1 - iOrtho2;
  537. m_nSommeLongueurs += iOrtho1 - iOrtho2;
  538. if (!bManuelle)
  539. {
  540. if (iOrtho1 - iOrtho2)
  541. GraphMeanAddMeasure(true, iOrtho1 - iOrtho2);
  542. }
  543. m_nMesures++;
  544. }
  545. }
  546. }
  547. return retour;
  548. }
  549. int CPlaqueBase::calculPlaque2(ExtendedImage *h_image, int nbPts, unsigned char *points)
  550. {
  551. unsigned char *dadd;
  552. unsigned char a, b, c, d;
  553. Point point;
  554. int npt;
  555. int retour;
  556. m_result = h_image;
  557. if ( !m_etudie )
  558. {
  559. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  560. }
  561. m_wimg.Del();
  562. m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
  563. m_wimg.Fill(0);
  564. m_type = typeManual;
  565. retour = 0;
  566. npt = 0;
  567. dadd = points;
  568. do
  569. {
  570. a = *dadd;
  571. dadd++;
  572. b = *dadd;
  573. dadd++;
  574. c = *dadd;
  575. dadd++;
  576. d = *dadd;
  577. dadd++;
  578. point.x = d;
  579. point.x = point.x | (c << 8);
  580. point.x = point.x | (b << 16);
  581. point.x = point.x | (a << 24);
  582. a = *dadd;
  583. dadd++;
  584. b = *dadd;
  585. dadd++;
  586. c = *dadd;
  587. dadd++;
  588. d = *dadd;
  589. dadd++;
  590. point.y = d;
  591. point.y = point.y | (c << 8);
  592. point.y = point.y | (b << 16);
  593. point.y = point.y | (a << 24);
  594. // if (m_nPtLongeantPlaque < NBPTSLONGEANTMAX)
  595. {
  596. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = point;
  597. m_nPtLongeantPlaque++;
  598. }
  599. npt++;
  600. } while (npt < nbPts);
  601. m_tPtLongeantPlaque [m_nPtLongeantPlaque] = m_tPtLongeantPlaque [0];
  602. m_nPtLongeantPlaque++;
  603. retour = CalculerPlaqueManuelle();
  604. return retour;
  605. }
  606. /*----------------------------------------------------------\
  607. | Surface de la plaque |
  608. |-----------------------------------------------------------|
  609. | DESCRIPTION : |
  610. | Crée une région polygonale, composée des segments |
  611. | indiqués par l'utilisateur, des extrémités trouvées. |
  612. |-----------------------------------------------------------|
  613. | PARAMETRES : |
  614. \----------------------------------------------------------*/
  615. int CPlaqueBase::CalculerPlaqueManuelle ()
  616. {
  617. int retour;
  618. // AffectLeadResult();
  619. // Créer le polygone
  620. m_rgnATraiter.DeleteObject();
  621. if (!m_rgnATraiter.CreatePolygonRgn(m_tPtLongeantPlaque, m_nPtLongeantPlaque))
  622. {
  623. retour = 31;
  624. return retour;
  625. }
  626. retour = CalculerSurfaceEtIntensitePlaque(true);
  627. return retour;
  628. }
  629. bool CPlaqueBase::IsBorder(int x, int y)
  630. {
  631. if (!((m_type == typeRGB) ? !IsColor(x, y) :
  632. (GetIntensityResult(x, y) > m_iMax)))
  633. { // On considère qu'il faut être dans la plaque!
  634. return false;
  635. }
  636. // L'aspect static de ces 7 variables est purement dans un but d'économie de mémoire...
  637. static int Xmin, Xmax, xx, Ymin, Ymax, yy, NbPoints;
  638. Xmin = max(0, x-1);
  639. Xmax = min(x+1, GetWidth() - 1);
  640. Ymin = max(0, y-1);
  641. Ymax = min(y+1, GetHeight() - 1);
  642. // On compte le nombre de points en-plaque autour du point étudié
  643. NbPoints = 0;
  644. for(xx = Xmin; xx <= Xmax; xx++)
  645. {
  646. for(yy = Ymin; yy <= Ymax; yy++)
  647. {
  648. if (((xx != x) || (yy != y)) &&
  649. ((m_type == typeRGB) ? !IsColor(xx, yy) :
  650. (GetIntensityResult(xx, yy) > m_iMax)))
  651. {
  652. NbPoints++;
  653. }
  654. }
  655. }
  656. // Ce point est considéré comme faisant partie de la frontière s'il possède
  657. // plus de 3 points en-plaque autour de lui, et s'il n'est pas au milieu de
  658. // la plaque (id est tout point autour de lui en-plaque!)
  659. if ((NbPoints < 3) || (NbPoints == (Xmax-Xmin+1)*(Ymax-Ymin+1)-1))
  660. {
  661. return false;
  662. }
  663. return true;
  664. }
  665. bool CPlaqueBase::SuiviContourLocal(int x, int y, double Xd, double Yd, bool Initialise)
  666. {
  667. static CVector VectBordFin;
  668. static int Width;
  669. static bool* TabPtParcourus = NULL;
  670. // (TabPtParcourus[x+Width*y] == true) s'il le point (x,y) à été parcourus
  671. if (Initialise)
  672. {
  673. Width = GetWidth();
  674. delete [] TabPtParcourus;
  675. TabPtParcourus = new bool[Width * GetHeight()];
  676. memset(TabPtParcourus, 0, Width * GetHeight());
  677. VectBordFin = CVector(m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].x,m_tPtLongeantPlaque[m_nPtLongeantPlaque-1].y,
  678. m_pointLimite1.x,m_pointLimite1.y);
  679. return true;
  680. }
  681. static int xx, yy; // L'aspect static est purement dans un but d'économie de mémoire...
  682. // On marque ce point comme parcourus
  683. TabPtParcourus[x+y*Width] = true;
  684. // On conserve l'ancienne valeur de la couleur pour pouvoir la restaurer
  685. unsigned long OldPixelColor = GetPixelEtudie(x, y);
  686. // On dessine en bleu le point étudié (appartenant à priori au contour)
  687. SetPixelEtudie(x, y, m_clrBleue);
  688. // On a fini avec succes la mesure si le point étudié touche le 2nd bord jaune!
  689. Point pt = VectBordFin.Projected(Point(x,y));
  690. if (Distance2D(Point(pt.x,pt.y) , Point(x,y)) < 2) return true;
  691. int Xbest, Ybest;
  692. Xbest = 0;
  693. Ybest = 0;
  694. // L'aspect static de ces 6 variables est purement dans un but d'économie de mémoire...
  695. static double Vbest;
  696. static bool Valide;
  697. static int M;
  698. static double XdNew;
  699. static double YdNew;
  700. static double PScal;
  701. int dimension = 1;
  702. Valide = false; Vbest = 1;
  703. while (!Valide)
  704. {
  705. Vbest = 0.25 * (4 - dimension);
  706. // On cherche les coordonnées du point ou la "pertinence" est la plus elevé
  707. for(xx = -dimension; xx <= dimension; xx++)
  708. {
  709. for(yy = -dimension; yy <= dimension; yy++)
  710. {
  711. // On regarde la pertinence de ce point environnant...
  712. if ((xx) || (yy))
  713. {
  714. // PScal = (Xd *xx + Yd *yy)/sqrt(xx*xx+yy*yy);
  715. PScal = (Xd *xx + Yd *yy) / sqrt((double) xx * xx + (double) yy * yy); // MAJ2005
  716. if ((PScal > Vbest) &&
  717. (m_rgnATraiter.PtInRegion0(x+xx, y+yy)) &&
  718. (!TabPtParcourus[(x+xx)+(y+yy)*Width]) &&
  719. (IsBorder(x+xx, y+yy)))
  720. {
  721. Vbest = PScal;
  722. Xbest = xx;
  723. Ybest = yy;
  724. }
  725. }
  726. }
  727. }
  728. if (Vbest != 0.25*(4 - dimension))
  729. {
  730. M = max(abs(Xbest), abs(Ybest));
  731. XdNew = Xbest * M + Xd * 3 * dimension;
  732. YdNew = Ybest * M + Yd * 3 * dimension;
  733. PScal = sqrt(XdNew * XdNew + YdNew * YdNew);
  734. if (SuiviContourLocal(x + Xbest / M, y + Ybest / M, XdNew / PScal, YdNew / PScal))
  735. {
  736. Valide = true;
  737. break;
  738. }
  739. else
  740. {
  741. Valide = false; // On restaure cette variable static au cas où...
  742. TabPtParcourus[(x + Xbest) + (y + Ybest) * Width] = true;
  743. }
  744. }
  745. else
  746. {
  747. // On agrandi la fenetre de recherche...
  748. if (dimension < 4) dimension++;
  749. else break;
  750. }
  751. }
  752. if (!Valide)
  753. {
  754. // On remet la couleur initial du point
  755. SetPixelEtudie(x, y, OldPixelColor);
  756. return false;
  757. }
  758. return true;
  759. }
  760. bool CPlaqueBase::SuiviContour()
  761. {
  762. // On cherche le début de la plaque le long du 1er bord jaune
  763. CVector vectSegment(m_pointLimite2.x, m_pointLimite2.y, m_tPtLongeantPlaque[0].x, m_tPtLongeantPlaque[0].y);
  764. int i = 0;
  765. // On prend le premier point entrant dans la plaque!
  766. while(!((m_type == typeRGB) ?
  767. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  768. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
  769. {
  770. i++;
  771. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  772. }
  773. double Xd, Yd, d; // Direction initiale de recherche de contour...
  774. Xd = m_tPtLongeantPlaque[1].x - m_tPtLongeantPlaque[0].x;
  775. Yd = m_tPtLongeantPlaque[1].y - m_tPtLongeantPlaque[0].y;
  776. d = sqrt(Xd * Xd + Yd * Yd);
  777. Xd = Xd/d;
  778. Yd = Yd/d;
  779. int Compteur = 0;
  780. bool MesureValide = false;
  781. while ((!MesureValide) && (Compteur++ < 5)) // On fait 5 essais maximum...
  782. {
  783. CopyResultDansEtudie();
  784. // On espère avoir une frontière de la plaque valide en ce point...
  785. SuiviContourLocal(0, 0, 0, 0, true); // Initialisation de la fonction!
  786. MesureValide = SuiviContourLocal(vectSegment[i].x, vectSegment[i].y, Xd, Yd);
  787. if (!MesureValide)
  788. {
  789. // La première mesure n'est pas valide...
  790. // On cherche le premier point sortant de la plaque précedemment détectée!
  791. while ((m_type == typeRGB) ?
  792. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  793. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax))
  794. {
  795. i++;
  796. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  797. }
  798. // On cherche le premier point entrant dans la plaque!
  799. while(!((m_type == typeRGB) ?
  800. !IsColor(vectSegment[i].x, vectSegment[i].y) :
  801. (GetIntensityResult(vectSegment[i].x, vectSegment[i].y) > m_iMax)))
  802. {
  803. i++;
  804. if (!PointInBufferResult(vectSegment[i].x, vectSegment[i].y)) return false;
  805. }
  806. }
  807. }
  808. if (!MesureValide) return false;
  809. #ifdef _DEBUG
  810. // On affiche le résultat de l'algo de repérage du contour plaque.
  811. // m_pLeadResult->Copy(m_LeadEtudie);
  812. #endif // _DEBUG
  813. // Remplissage de la partie hors-plaque en vert
  814. SuiviContourRemplis(m_ptInferieur.x, m_ptInferieur.y);
  815. return true;
  816. }
  817. void CPlaqueBase::SuiviContourRemplis(int x, int y)
  818. {
  819. assert(PointInBufferResult(x, y) && (m_type != typeUndefined));
  820. assert(GetPixelEtudie(x, y) != m_clrBleue);
  821. assert(GetPixelResult(x, y) != m_clrVert);
  822. int xx, Xmin, Xmax, yy, Ymin, Ymax;
  823. // On dessine en vert le point hors-plaque étudié
  824. SetPixelResult(x, y);
  825. Xmin = max(0, x-2);
  826. Xmax = min(x+2, GetWidth() - 1);
  827. Ymin = max(0, y-2);
  828. Ymax = min(y+2, GetHeight() - 1);
  829. // On compte le nombre de points frontière autour du point étudié
  830. double NbPoints = 0;
  831. for(xx = Xmin; xx <= Xmax; xx++)
  832. {
  833. for(yy = Ymin; yy <= Ymax; yy++)
  834. {
  835. if (((xx != x) || (yy != y)) &&
  836. (GetPixelEtudie(xx, yy) == m_clrBleue))
  837. {
  838. NbPoints++;
  839. }
  840. }
  841. }
  842. // Ce point est à la fin de l'arbre de parcours si il possède 2 points ou plus
  843. // appartenant à la frontières à coté de lui
  844. if (NbPoints > 0) return;
  845. Xmin = max(0, x-1);
  846. Xmax = min(x+1, GetWidth() - 1);
  847. Ymin = max(0, y-1);
  848. Ymax = min(y+1, GetHeight() - 1);
  849. for (xx = Xmin; xx <= Xmax; xx++)
  850. {
  851. for (yy = Ymin; yy <= Ymax; yy++)
  852. {
  853. if (((xx != x) || (yy != y)) &&
  854. (m_rgnATraiter.PtInRegion0(xx, yy)) &&
  855. (GetPixelEtudie(xx, yy) != m_clrBleue) &&
  856. (GetPixelResult(xx, yy) != m_clrVert))
  857. { // Le point (xx, yy) est donc hors-plaque et non traité
  858. SuiviContourRemplis(xx, yy);
  859. }
  860. }
  861. }
  862. }
  863. // [LAU - 2/5/2006] Calcule la somme des longeurs entre les points enregistrés longeant la plaque
  864. double CPlaqueBase::Get_SommeLongueurs()
  865. {
  866. double dist = 0;
  867. if (m_Etape == etapeRien)
  868. {
  869. return (int)dist;
  870. }
  871. for (int i = 0; i < m_nPtLongeantPlaque-1; i++)
  872. {
  873. dist += CVector (m_tPtLongeantPlaque[i].x, m_tPtLongeantPlaque[i].y, m_tPtLongeantPlaque[i+1].x, m_tPtLongeantPlaque[i+1].y).Norm (g_pCurrentScale);
  874. }
  875. return (int) dist;
  876. }
  877. // Algorithme de coloriage de blobs sur l'image d'entrée
  878. // Objectif : enlever les petites régions dans l'image seuillée
  879. bool CPlaqueBase::DoBlobColoring()
  880. {
  881. int x, y, i, indblob, nblob, realblob, ng;
  882. long taille;
  883. img lwimg, lwimg1;
  884. int wdimh, wdimv;
  885. blob m_tblob[MAXBLOB];
  886. Rect rectEnglobant;
  887. rectEnglobant = m_rgnATraiter.GetRgnBox();
  888. wdimh = GetWidth();
  889. wdimv = GetHeight();
  890. lwimg.Create(TYPE_UCHAR, wdimh, wdimv);
  891. lwimg1.Create(TYPE_INT, wdimh, wdimv); // On prend des ints
  892. lwimg.Fill(0);
  893. indblob = 0;
  894. nblob = 0;
  895. // Générer l'image binaire qui va aller à l'algo. du blob coloring
  896. // lwimg
  897. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  898. {
  899. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  900. {
  901. bool fGreen;
  902. fGreen = (GetPixelResult(x, y) == m_clrVert);
  903. if (!fGreen)
  904. {
  905. lwimg.SetValue(x, y, 1);
  906. }
  907. }
  908. }
  909. // Résultat : les blobs sont dans wimg1
  910. nblob = lwimg.BlobColoring(m_tblob, &lwimg1);
  911. // Elimination des petits blobs.
  912. realblob = nblob;
  913. for (i = 1; i <= nblob; i++)
  914. {
  915. taille = lwimg1.GetBlobSize(i);
  916. if ((taille < (wdimh * wdimv) - 1) && (taille <= 50))
  917. {
  918. lwimg1.RemplaceCouleur(i, MAXBLOB+1); // Sur int
  919. }
  920. }
  921. // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
  922. // Mise à jour de lwimg, puis transfert dans l'image d'origine
  923. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  924. {
  925. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  926. {
  927. ng = lwimg1.GetValue(x, y);
  928. if (ng == (MAXBLOB + 1))
  929. {
  930. SetPixelResult(x, y);
  931. }
  932. }
  933. }
  934. if (lwimg.init == 1) lwimg.Del();
  935. if (lwimg1.init == 1) lwimg1.Del();
  936. return true;
  937. }
  938. // Algorithme de fermeture
  939. bool CPlaqueBase::DoClosing()
  940. {
  941. int x, y, ng;
  942. img lwimg, lwimg1;
  943. int wdimh, wdimv;
  944. Rect rectEnglobant;
  945. rectEnglobant = m_rgnATraiter.GetRgnBox();
  946. wdimh = GetWidth();
  947. wdimv = GetHeight();
  948. lwimg.Create(TYPE_USHORT, wdimh, wdimv);
  949. lwimg1.Create(TYPE_USHORT, wdimh, wdimv); // On prend des ints
  950. lwimg.Fill(0);
  951. // Générer l'image binaire qui va aller à l'algo. du blob coloring
  952. // lwimg
  953. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  954. {
  955. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  956. {
  957. if (GetPixelResult(x, y) == m_clrVert)
  958. {
  959. lwimg.SetValue(x, y, 1);
  960. }
  961. }
  962. }
  963. lwimg.BinaryClosing(&lwimg1);
  964. // Dans lwimg1, les pixels à la valeur MAXBLOB+1, sont ceux des régions à supprimer
  965. // Mise à jour de lwimg, puis transfert dans l'image d'origine
  966. for (x = rectEnglobant.left; x < rectEnglobant.right; x++)
  967. {
  968. for (y = rectEnglobant.top; y < rectEnglobant.bottom; y++)
  969. {
  970. ng = lwimg1.GetValue(x, y);
  971. if (ng == 1)
  972. {
  973. SetPixelResult(x, y);
  974. }
  975. }
  976. }
  977. if (lwimg.init == 1) lwimg.Del();
  978. if (lwimg1.init == 1) lwimg1.Del();
  979. return true;
  980. }
  981. bool CPlaqueBase::PointInBufferResult(const int& x, const int& y)
  982. {
  983. Point pt(x, y);
  984. // pt.x = x;
  985. // pt.y = y;
  986. return PointInBufferResult(pt);
  987. }
  988. bool CPlaqueBase::PointInBufferResult(const Point& pt)
  989. {
  990. assert( m_result );
  991. int dx = GetWidth();
  992. int dy = GetHeight();
  993. return ( (pt.x >= 0) && (pt.y >= 0) && (pt.x < dx) && (pt.y < dy) );
  994. }
  995. bool CPlaqueBase::IsColor(int x, int y)
  996. {
  997. unsigned char bRed;
  998. unsigned char bGreen;
  999. unsigned char bBlue;
  1000. int iRed;
  1001. int iGreen;
  1002. int iBlue;
  1003. // AffectLeadResult();
  1004. bRed = m_result->GetPixelRGB( x, y, 0);
  1005. bGreen = m_result->GetPixelRGB( x, y, 1);
  1006. bBlue = m_result->GetPixelRGB( x, y, 2);
  1007. iRed = (int) bRed;
  1008. iGreen = (int) bGreen;
  1009. iBlue = (int) bBlue;
  1010. // un niveau de gris implique bRed = bGreen = bBlue
  1011. // étant donné que l'image a été numérisé on autorise un delta de 10 entre chaque couleur
  1012. // ex : 190 197 185 est gris, 190 201 190 est en couleur
  1013. return ( (abs (iRed - iGreen) > 30)
  1014. || (abs (iRed - iBlue ) > 30)
  1015. || (abs (iGreen - iBlue ) > 30)
  1016. );
  1017. }
  1018. int CPlaqueBase::GetIntensityResult(const int& x, const int& y)
  1019. {
  1020. Point pt;
  1021. pt.x = x;
  1022. pt.y = y;
  1023. return GetIntensityResult(pt);
  1024. }
  1025. int CPlaqueBase::GetIntensityResult(const Point& pt)
  1026. {
  1027. assert( m_result );
  1028. return m_result->GetPixelGray( pt.x, pt.y );
  1029. /*
  1030. value = (char) m_result->GetPixel( pt.x, pt.y );
  1031. col = (unsigned char)(value & 0xff);
  1032. return col;
  1033. */
  1034. /*
  1035. #if defined( WIN32 ) && !defined( IMT_DLL ) && !defined( PLAQUE_DLL )
  1036. return GetRValue( m_result->GetPixel( pt.x, pt.y ) );
  1037. #else
  1038. return *m_result->GetPixel( pt.x, pt.y );
  1039. #endif
  1040. */
  1041. }
  1042. unsigned int CPlaqueBase::GetErrorID(void)
  1043. {
  1044. return m_uErrorID;
  1045. }
  1046. int CPlaqueBase::TestFantome(ExtendedImage *h_image, CPlaqueResult *)
  1047. {
  1048. int i, x, y, nbPts;
  1049. unsigned char *points, *dadd;
  1050. int *input;
  1051. Point pts[12];
  1052. int retour;
  1053. m_result = h_image;
  1054. // m_result.Create(768, 576, 24);
  1055. // m_result.CopyFrom2(h_image);
  1056. CopieResultSvg();
  1057. nbPts = 6;
  1058. retour = 0;
  1059. points = (unsigned char *) malloc( nbPts * sizeof(unsigned char *) );
  1060. input = (int *) malloc( 4 * sizeof(int) );
  1061. x = 372;
  1062. y = 177;
  1063. pts[0].x = 267;
  1064. pts[0].y = 218;
  1065. pts[1].x = 300;
  1066. pts[1].y = 227;
  1067. pts[2].x = 364;
  1068. pts[2].y = 232;
  1069. pts[3].x = 446;
  1070. pts[3].y = 238;
  1071. pts[4].x = 509;
  1072. pts[4].y = 238;
  1073. pts[5].x = 561;
  1074. pts[5].y = 234;
  1075. /* double a, b;
  1076. a = g_pCurrentScale->m_dblHor;
  1077. b = g_pCurrentScale->m_dblVer;
  1078. */
  1079. dadd = points;
  1080. for (i = 0; i < nbPts; i++)
  1081. {
  1082. input[0] = ((pts[i].x & 0xFF000000) >> 24);
  1083. input[1] = ((pts[i].x & 0x00FF0000) >> 16);
  1084. input[2] = ((pts[i].x & 0x0000FF00) >> 8);
  1085. input[3] = ((pts[i].x & 0x000000FF));
  1086. *dadd = input[0];
  1087. dadd++;
  1088. *dadd = input[1];
  1089. dadd++;
  1090. *dadd = input[2];
  1091. dadd++;
  1092. *dadd = input[3];
  1093. dadd++;
  1094. input[0] = ((pts[i].y & 0xFF000000) >> 24);
  1095. input[1] = ((pts[i].y & 0x00FF0000) >> 16);
  1096. input[2] = ((pts[i].y & 0x0000FF00) >> 8);
  1097. input[3] = ((pts[i].y & 0x000000FF));
  1098. *dadd = input[0];
  1099. dadd++;
  1100. *dadd = input[1];
  1101. dadd++;
  1102. *dadd = input[2];
  1103. dadd++;
  1104. *dadd = input[3];
  1105. dadd++;
  1106. }
  1107. retour = calculPlaque(h_image, x, y, nbPts, points, 60, 120);
  1108. // m_res->allocate_vectors(m_nPtLongeantPlaque);
  1109. return retour;
  1110. }
  1111. int CPlaqueBase::calculPlaque(ExtendedImage *h_image, int x, int y, int nbPts, unsigned char *points, int seuil1, int seuil2)
  1112. {
  1113. Point point;
  1114. int npt;
  1115. int retour;
  1116. unsigned char *dadd;
  1117. retour = 0;
  1118. unsigned char a, b, c, d;
  1119. m_result = h_image;
  1120. // m_result.Create(768, 576, 24 );
  1121. // m_result.CopyFrom2(h_image);
  1122. m_Etape = etapeRien;
  1123. // C'est le premier octet qui est pris : le rouge.
  1124. m_debug1 = (int) GetIntensityResult(100, 125);
  1125. m_debug2 = (int) GetIntensityResult(200, 170);
  1126. m_debug3 = (int) GetIntensityResult(300, 460);
  1127. m_debug4 = (int) m_result->GetWidth();
  1128. m_debug5 = (int) 1;
  1129. //retour = 1999;
  1130. // return retour;
  1131. // Création de m_etudie
  1132. if ( m_Etape == etapeRien )
  1133. {
  1134. if ( !m_etudie )
  1135. {
  1136. m_etudie = new unsigned long[ GetWidth() * GetHeight() ];
  1137. }
  1138. /* if ( m_etudie )
  1139. {
  1140. m_etudie->Create( GetWidth(), GetHeight(), 24 );
  1141. }
  1142. */
  1143. // 1er Point
  1144. m_Etape = etapeSegments;
  1145. m_wimg.Del();
  1146. m_wimg.Create(TYPE_UCHAR, GetWidth(), GetHeight());
  1147. m_wimg.Fill(0);
  1148. }
  1149. retour = 0;
  1150. dadd = points;
  1151. if (m_Etape == etapeSegments)
  1152. {
  1153. npt = 0;
  1154. do
  1155. {
  1156. a = *dadd;
  1157. dadd++;
  1158. b = *dadd;
  1159. dadd++;
  1160. c = *dadd;
  1161. dadd++;
  1162. d = *dadd;
  1163. dadd++;
  1164. point.x = d;
  1165. point.x = point.x | (c << 8);
  1166. point.x = point.x | (b << 16);
  1167. point.x = point.x | (a << 24);
  1168. a = *dadd;
  1169. dadd++;
  1170. b = *dadd;
  1171. dadd++;
  1172. c = *dadd;
  1173. dadd++;
  1174. d = *dadd;
  1175. dadd++;
  1176. point.y = d;
  1177. point.y = point.y | (c << 8);
  1178. point.y = point.y | (b << 16);
  1179. point.y = point.y | (a << 24);
  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(ExtendedImage *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->GetWidth();
  1499. }
  1500. int CPlaqueBase::GetHeight()
  1501. {
  1502. return m_result->GetHeight();
  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. */