EIMBase.cpp 80 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610
  1. /*******************************************************************\
  2. Fichier : EIMBase.cpp
  3. Date : 29/04/98
  4. Version : 1.024
  5. Auteur : P-J Touboul
  6. Description : Fonctions de d�tection et mesures de parois
  7. |*******************************************************************|
  8. Bugs:
  9. Il serait plus propre dans la fonction EIM, d'appliquer le masque
  10. sur le vecteur (proc�dure Mask mise en commentaire).
  11. Notes:
  12. |*******************************************************************|
  13. Historique :
  14. 29/04/98 1.024 : Modification du sens de la mesure en fonction de la position relative
  15. des points du segment utilisateur
  16. M�morisation de la distance de la mesure
  17. 02/04/98 1.022 : Utilisation d'une valeur minimale permettant de consid�rer qu'il
  18. y a une variation de densit� (STEP)
  19. Bug quand il y a avait UN SEUL lissage effectu�
  20. 11/03/98 1.020 : Nouvel algorithme possible pour la mesure de diam�tre (sym�trie)
  21. 31/01/98 1.010 : Mesures 'sub-pixels' permettant de gagner jusqu'� un pixel
  22. en pr�cision (1/2 pixel avant + 1/2 pixel apr�s). Les points
  23. au milieu des pentes ont donc defs coordonn�es d�cimales
  24. Correction d'un probl�me sur la d�tection de plateaux
  25. 22/01/98 1.001 : Correction sur le calcul des points m�dians
  26. Ajout de la position des points m�dians
  27. 17/03/97 1.000 : Premi�re version
  28. \*******************************************************************/
  29. /*----------------------------------------------------------\
  30. Includes
  31. \----------------------------------------------------------*/
  32. #include "EIMBase.h"
  33. #include "MeanEstimate.h"
  34. #include "CEIMResult.h"
  35. #include "EIMResult.h"
  36. #include "Ressource.h"
  37. #include "point.h"
  38. #include "ToolsMath.h"
  39. //#include "../Container/ExtendedImage.h"
  40. #include <limits>
  41. #include <string.h>
  42. #include <QImage>
  43. //#define TEST_FOR_FANTOME
  44. /*----------------------------------------------------------\
  45. Defines
  46. \----------------------------------------------------------*/
  47. #define STEP 0
  48. /*----------------------------------------------------------\
  49. Variables locales
  50. \----------------------------------------------------------*/
  51. //static char Version[] = "$VER: " __FILE__ " 1.024 (" __DATE__ ")";
  52. /*----------------------------------------------------------\
  53. | Delta |
  54. \----------------------------------------------------------*/
  55. char CEIMBase::Delta (unsigned char b1, unsigned char b2)
  56. {
  57. int i;
  58. // En utilisant STEP, on consid�re par exemple que 15/16/17 repr�sentent
  59. // la m�me valeur et que ce n'est donc pas une croissance
  60. i = b1 - b2;
  61. if (i > STEP) return ( 1);
  62. else if (i < -STEP) return (-1);
  63. else return ( 0);
  64. } // end of Delta
  65. /*----------------------------------------------------------\
  66. | CEIM::CEIM |
  67. |-----------------------------------------------------------|
  68. | DESCRIPTION : |
  69. | Constructeur de la classe |
  70. |-----------------------------------------------------------|
  71. | PARAMETRES : |
  72. | scale : �chelle � utiliser pour les mesures |
  73. \----------------------------------------------------------*/
  74. CEIMBase::CEIMBase (void)
  75. {
  76. //debugOutput = NULL;
  77. m_pMeasures = NULL;
  78. m_bDelta1 = 30; // variation minimale pour la premi�re pente
  79. m_bDelta2 = 10; // variation minimale entre le sommet des deux pentes // A voir Release
  80. m_bSeuil1 = 140;
  81. m_algoDiameter = algoProfile; // algorithme par d�faut
  82. m_arVariance.clear();
  83. m_arVarianceAA.clear();
  84. m_arVarianceII.clear();
  85. m_arVarianceINT.clear();
  86. Release(); // apr�s m_pMeasures = NULL;
  87. m_coeff_a = -1.0;
  88. m_coeff_b = -1.0;
  89. m_coeff_c = -1.0;
  90. m_bDisplay = false;
  91. m_parallelismeDiametre = false; // Exp�rimental
  92. m_image = NULL;
  93. m_versionTomtecAout08 = true;
  94. } // fin de CEIM
  95. CEIMBase::~CEIMBase(void)
  96. {
  97. Release();
  98. } // fin de ~CEIM
  99. void CEIMBase::SetEimAssisted(bool valide)
  100. {
  101. m_Assist = valide;
  102. }
  103. bool CEIMBase::GetEimAssisted()
  104. {
  105. return m_Assist;
  106. }
  107. // Calcul automatique de l'EIM
  108. // Ancienne version : n'est plus utilis�e
  109. int CEIMBase::CalculEimAutomatique(int mode, bool bActionDiametre, Point *ptClick0, Point *ptClick1, Point *ptLastClick, unsigned char *bClicks, QImage *img,bool *fBackToNone)
  110. {
  111. m_image = img;
  112. return CalculEimAutomatique( mode, bActionDiametre, ptClick0, ptClick1, ptLastClick, bClicks, fBackToNone );
  113. }
  114. int CEIMBase::CalculEimAutomatique(int mode, bool bActionDiametre, Point *ptClick0, Point *ptClick1, Point *ptLastClick, unsigned char *bClicks, bool *fBackToNone)
  115. {
  116. int retour = 0;
  117. if (m_Assist)
  118. {
  119. if (mode == 0)
  120. {
  121. Measure(*ptClick0, *ptLastClick, bActionDiametre);
  122. }
  123. double dDirection = Direction();
  124. if (dDirection == 0)
  125. {
  126. //CMessage::Warn(MyLoadString(IDS_EIM_FAILED));
  127. *fBackToNone = false;
  128. return 0;
  129. }
  130. else
  131. {
  132. Point CorrectPoint = *ptLastClick;
  133. CorrectPoint.y = ptClick0->y + ((long) (dDirection*(CorrectPoint.x - ptClick0->x)));
  134. *ptClick1 = CorrectPoint;
  135. *bClicks = 1;
  136. retour = 1; // Pour lancer un Invalidate
  137. if (mode == 1)
  138. {
  139. Measure(*ptClick0, CorrectPoint, bActionDiametre);
  140. }
  141. *ptLastClick = CorrectPoint;
  142. }
  143. }
  144. return retour;
  145. }
  146. bool CEIMBase::PointInBuffer(const Point& pt)
  147. {
  148. assert( m_image );
  149. int dx = m_image->width();
  150. int dy = m_image->height();
  151. return ( pt.x >= 0 && pt.y >= 0 && pt.x < dx && pt.y < dy );
  152. }
  153. unsigned char CEIMBase::GetIntensity(const Point& pt)
  154. {
  155. assert( m_image );
  156. return qGray(m_image->pixel( pt.x, pt.y ));
  157. }
  158. /*----------------------------------------------------------\
  159. | Release |
  160. |-----------------------------------------------------------|
  161. | DESCRIPTION : |
  162. | Lib�re les ressources allou�es pour une mesure |
  163. \----------------------------------------------------------*/
  164. void CEIMBase::Release (void)
  165. {
  166. m_dblEIMMin =
  167. m_dblEIMMean =
  168. m_dblEIMMax =
  169. m_dblINTMin =
  170. m_dblINTMean =
  171. m_dblINTMax =
  172. m_dblDiaAAMin =
  173. m_dblDiaAAMean =
  174. m_dblDiaAAMax =
  175. m_dblDiaIIMin =
  176. m_dblDiaIIMean =
  177. m_dblDiaIIMax =
  178. m_dblQI =
  179. m_dblQIMean =
  180. m_dblIA =
  181. m_dblEIMdMean =
  182. m_dblINTdMean =
  183. m_dblMEDdMean =
  184. m_dblIAd =
  185. m_dblVariance =
  186. m_dblDistance = 0.0;
  187. m_dwPoints = // nombre de points sur lesquels une mesure a �t� effectu�e
  188. m_dwValidPoints = // nombre de points sur lesquels le profil a �t� reconnu
  189. m_uErrorID = 0; // ID de la cha�ne d�crivant l'erreur
  190. if (m_pMeasures)
  191. {
  192. delete [] m_pMeasures;
  193. m_pMeasures = NULL;
  194. }
  195. m_StartPoint.x = -1;
  196. m_StartPoint.y = -1;
  197. m_EndPoint.x = -1;
  198. m_EndPoint.x = -1;
  199. memset( m_bBuffer, 0, THICKNESS );
  200. memset( m_cOffsets, 0, THICKNESS );
  201. } // fin de Release
  202. /*----------------------------------------------------------\
  203. | Measure |
  204. |-----------------------------------------------------------|
  205. | DESCRIPTION : |
  206. | Mesure d'une �paisseur de paroi ou d'un diam�tre |
  207. |-----------------------------------------------------------|
  208. | PARAMETRES : |
  209. | gfx : image en niveau de gris d'o� lire les |
  210. | donn�es |
  211. | pGraphMean : graphe dans lequel ajout� les mesures si |
  212. | non nul |
  213. | pt1 : premier point du segment d�terminant la |
  214. | ligne de la paroi |
  215. | pt2 : deuxi�me point du segment |
  216. | fDiameter : mesure d'un diam�re ou d'une paroi |
  217. |-----------------------------------------------------------|
  218. | RETOURNE : |
  219. | VRAI si au moins une mesure a �t� effectu�e |
  220. \----------------------------------------------------------*/
  221. bool CEIMBase::Measure(
  222. QImage *h_image,
  223. const Point &point1,
  224. const Point &point2,
  225. bool fDiameter,
  226. CEIMResult *m_res)
  227. {
  228. m_image = h_image;
  229. return Measure( point1, point2, fDiameter, m_res );
  230. }
  231. bool CEIMBase::Measure (
  232. const Point &point1,
  233. const Point &point2,
  234. bool fDiameter,
  235. CEIMResult *m_res
  236. )
  237. {
  238. Point point3, point4;
  239. // En fonction de la position du premier point, on d�termine le c�t� d'analyse
  240. m_fDiameter = fDiameter;
  241. Release ();
  242. if (point1.x > point2.x)
  243. {
  244. m_bNearWall = true;
  245. m_vUser = CVector(point2, point1);
  246. if (!fDiameter)
  247. {
  248. m_StartPoint = point2;
  249. m_EndPoint = point1;
  250. }
  251. }
  252. else
  253. {
  254. m_bNearWall = false;
  255. m_vUser = CVector(point1, point2); // pour imposer le calcul de gauche � droite pour
  256. // le diam�tre et la distensibilit� m�me si le trac�
  257. // se fait de droite � gauche.
  258. if (!fDiameter)
  259. {
  260. m_StartPoint = point1;
  261. m_EndPoint = point2;
  262. }
  263. }
  264. m_minx_curve = std::numeric_limits< int >::max();
  265. m_max_curve = 0;
  266. /*
  267. if ((m_Assist) && (!fDiameter))
  268. {
  269. // CJ 2007 : Allongement auto de la distance � 10 mm
  270. dpoint pta, ptb, s1, s2, ptc;
  271. const long x1 = 0;
  272. pta.x = point1.x;
  273. pta.y = point1.y;
  274. ptb.x = point2.x;
  275. ptb.y = point2.y;
  276. if (point1.x < point2.x)
  277. {
  278. if (InterCercleDroite(pta, 10.0 / g_pCurrentScale->DistanceX(1L), pta, ptb, &s1, &s2))
  279. {
  280. ptc = leplusproche(ptb, s1, s2);
  281. point3.x = (int) pta.x;
  282. point3.y = (int) pta.y;
  283. point4.x = (int) ptc.x;
  284. point4.y = (int) ptc.y;
  285. }
  286. #ifndef NEW_EIM
  287. m_vUser = CVector (point3, point4);
  288. #else
  289. if (point3.x <= point4.x)
  290. {
  291. m_vUser = CVector (point3, point4);
  292. m_StartPoint = point3;
  293. m_EndPoint = point4;
  294. }
  295. else
  296. {
  297. m_vUser = CVector (point4, point3);
  298. m_StartPoint = point4;
  299. m_EndPoint = point3;
  300. }
  301. if (point4.x > point3.x)
  302. {
  303. m_max_curve = point4.x;
  304. }
  305. else
  306. {
  307. m_max_curve = point3.x;
  308. }
  309. if (point3.x < point4.x)
  310. {
  311. m_minx_curve = point3.x;
  312. }
  313. else
  314. {
  315. m_minx_curve = point4.x;
  316. }
  317. #endif
  318. }
  319. }
  320. */
  321. if (m_vUser.Nul ())
  322. {
  323. m_uErrorID = IDS_EIM_INVALID;
  324. return (false);
  325. }
  326. else
  327. {
  328. // CWaitCursor wait;
  329. m_dwPoints = m_vUser.Length () + 1;
  330. m_pMeasures = new CEIMInfo [m_dwPoints];
  331. memset (m_pMeasures, 0, sizeof (CEIMInfo) * m_dwPoints);
  332. // pour un algo plut�t bas� sur la proximit� de la droite par
  333. // rapport � la paroi potentielle la plus proche voir fichier EIM/AvecSeuil.cpp
  334. // comme le point de d�part de vecteur � toujours une abscisse inf�rieure au point d'arriv�e
  335. // la direction � donner � Orthogonal est 0. Voir algo de Orthogonal pour comprendre
  336. if (!m_bNearWall)
  337. {
  338. m_indexParoi = 0;
  339. m_Max_Alignement = 8;
  340. }
  341. else
  342. {
  343. m_indexParoi = 1;
  344. m_Max_Alignement = 20;
  345. }
  346. if (fDiameter)
  347. {
  348. Diameter();
  349. }
  350. else
  351. {
  352. #ifdef NEW_EIM
  353. if (!m_Assist)
  354. #else
  355. // if ((m_Assist) && (!fDiameter))
  356. {
  357. }
  358. // else
  359. #endif
  360. {
  361. m_vUser = CVector (point1, point2);
  362. }
  363. Paroi();
  364. }
  365. }
  366. Update (m_res);
  367. return (Valid ());
  368. } // fin de Measure
  369. /*----------------------------------------------------------\
  370. | ParallelismeEIM |
  371. |-----------------------------------------------------------|
  372. | DESCRIPTION : |
  373. | Fonction de calcul du parall�lisme du trait utilisateur |
  374. | Par rapport � la paroi
  375. | Pour le calcul de l'EIM |
  376. \----------------------------------------------------------*/
  377. void CEIMBase::ParallelismeEIM()
  378. {
  379. long dwPos, dwMin;
  380. long dwPos2;
  381. CEIMInfo *pInfo = &m_pMeasures[0];
  382. dpoint tpoints[MAX_POINTS_EIM_AUTO];
  383. int tContinueGauche[MAX_POINTS_EIM_AUTO];
  384. int tContinueDroite[MAX_POINTS_EIM_AUTO];
  385. int tContinue[MAX_POINTS_EIM_AUTO];
  386. int tContinue2[MAX_POINTS_EIM_AUTO];
  387. dpoint pta, ptb, ptc, ptd, pte, ptf, s1, s2;
  388. double dist_etalon, dist_etalon2, dist;
  389. int cptValid, cptNonValid;
  390. dpoint tabPointsValides[128];
  391. dpoint pts;
  392. bool bDebut = false;
  393. for (int i = 0; i < MAX_POINTS_EIM_AUTO; i++)
  394. {
  395. tContinueGauche[i] = 0;
  396. tContinueDroite[i] = 0;
  397. tContinue[i] = 0;
  398. tContinue2[i] = 0;
  399. }
  400. // 2�me passe : On enl�ve les outliers : En allant de gauche � droite
  401. dwMin = long (-1);
  402. pInfo = &m_pMeasures[0];
  403. cptValid = 0;
  404. cptNonValid = 0;
  405. // double dist2, dist3;
  406. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  407. {
  408. if (pInfo->m_fValid == true)
  409. {
  410. pts.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  411. pts.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  412. if ((pts.x != 0) && (pts.y != 0))
  413. {
  414. // V�rification de l'alignement
  415. if (cptValid >= m_Max_Alignement)
  416. {
  417. // Estimation droite � partir de tabPointsValides
  418. double ka, kb;
  419. RegressionLineaire(m_Max_Alignement, tabPointsValides, &ka, &kb);
  420. // Calcul de la distance orthogonale entre la droite et pts
  421. dpoint ptk, ptl, ptr;
  422. ptk.x = pts.x;
  423. ptk.y = ka * pts.x + kb;
  424. ptl.x = pts.x + 10;
  425. ptl.y = ka * ptl.x + kb;
  426. dist = distanceOrthPtDroite(pts, ptk, ptl, &ptr);
  427. if (dist < 3) // Si la distance est < � n pixels
  428. {
  429. cptNonValid = 0; // On remet le compteur � 0
  430. // Ce point est OK, on le garde
  431. // Remise � jour du tableau des points
  432. for (int i = 0; i < m_Max_Alignement-1; i++)
  433. {
  434. tabPointsValides[i].x = tabPointsValides[i+1].x;
  435. tabPointsValides[i].y = tabPointsValides[i+1].y;
  436. }
  437. tabPointsValides[m_Max_Alignement-1].x = pts.x;
  438. tabPointsValides[m_Max_Alignement-1].y = pts.y;
  439. tContinueGauche[dwPos] = 1;
  440. }
  441. else
  442. {
  443. cptNonValid++; // Nb de points non valides � la suite
  444. }
  445. // Si un nombre de points non valides suffisant a �t� d�tect� � la suite
  446. if (cptNonValid >= m_Max_Alignement - 1)
  447. {
  448. // On remet � 0 le tableau des valeurs
  449. for (int i = 0; i < m_Max_Alignement-1; i++)
  450. {
  451. tabPointsValides[i].x = 0;
  452. tabPointsValides[i].y = 0;
  453. }
  454. cptValid = 0; // On redemande un remplissage
  455. cptNonValid = 0;
  456. }
  457. }
  458. else
  459. {
  460. tabPointsValides[0].x = pInfo->m_Paroi[m_indexParoi].m_slope[2].m_ptDraw.x;
  461. tabPointsValides[0].y = pInfo->m_Paroi[m_indexParoi].m_slope[2].m_ptDraw.y;
  462. cptValid++;
  463. }
  464. }
  465. }
  466. pInfo++;
  467. }
  468. // Puis de droite � gauche
  469. pInfo = &m_pMeasures[m_dwPoints-1];
  470. cptValid = 0;
  471. cptNonValid = 0;
  472. bDebut = false;
  473. for (dwPos = m_dwPoints-1; dwPos > 0; dwPos--)
  474. {
  475. if (pInfo->m_fValid == true)
  476. {
  477. pts.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  478. pts.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  479. if ((pts.x != 0) && (pts.y != 0))
  480. {
  481. // V�rification de l'alignement
  482. if (cptValid >= m_Max_Alignement)
  483. {
  484. // Estimation droite � partir de tabPointsValides
  485. double ka, kb;
  486. RegressionLineaire(m_Max_Alignement, tabPointsValides, &ka, &kb);
  487. // Calcul de la distance orthogonale entre la droite et pts
  488. dpoint ptk, ptl, ptr;
  489. ptk.x = pts.x;
  490. ptk.y = ka * pts.x + kb;
  491. ptl.x = pts.x + 10;
  492. ptl.y = ka * ptl.x + kb;
  493. dist = distanceOrthPtDroite(pts, ptk, ptl, &ptr);
  494. if (dist < 3) // Si la distance est < � x pixels
  495. {
  496. cptNonValid = 0; // On remet le compteur � 0
  497. // Ce point est OK, on le garde
  498. // Remise � jour du tableau des points
  499. for (int i = 0; i < m_Max_Alignement-1; i++)
  500. {
  501. tabPointsValides[i].x = tabPointsValides[i+1].x;
  502. tabPointsValides[i].y = tabPointsValides[i+1].y;
  503. }
  504. tabPointsValides[m_Max_Alignement-1].x = pts.x;
  505. tabPointsValides[m_Max_Alignement-1].y = pts.y;
  506. tContinueDroite[dwPos] = 1;
  507. }
  508. else
  509. {
  510. cptNonValid++; // Nb de points non valides � la suite
  511. }
  512. // Si un nombre de points non valides suffisant a �t� d�tect� � la suite
  513. if (cptNonValid >= m_Max_Alignement - 1)
  514. {
  515. // On remet � 0 le tableau des valeurs
  516. for (int i = 0; i < m_Max_Alignement-1; i++)
  517. {
  518. tabPointsValides[i].x = 0;
  519. tabPointsValides[i].y = 0;
  520. }
  521. cptNonValid = 0;
  522. cptValid = 0; // On redemande un remplissage
  523. }
  524. }
  525. else
  526. {
  527. tabPointsValides[cptValid].x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  528. tabPointsValides[cptValid].y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  529. cptValid++;
  530. }
  531. }
  532. }
  533. pInfo--;
  534. }
  535. pInfo = &m_pMeasures[0];
  536. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  537. {
  538. if (pInfo->m_fValid == true)
  539. {
  540. if ((tContinueGauche[dwPos] == 1) || (tContinueDroite[dwPos] == 1))
  541. {
  542. tContinue[dwPos] = 1;
  543. }
  544. }
  545. tContinue2[dwPos] = tContinue[dwPos];
  546. pInfo++;
  547. }
  548. bool bNonContinue = false;
  549. int cptNonContinue = 0;
  550. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  551. {
  552. if (tContinue2[dwPos] == 1)
  553. {
  554. cptNonContinue = 0;
  555. }
  556. else if (tContinue2[dwPos] == 0)
  557. {
  558. cptNonContinue++;
  559. bNonContinue = true;
  560. }
  561. // 1- On faits rejoindre les segments si l'�cart est faible (sur front montant)
  562. if ((tContinue2[dwPos] == 1) && bNonContinue)
  563. {
  564. bNonContinue = false;
  565. if (cptNonContinue < 3*m_Max_Alignement)
  566. {
  567. // Dans ce cas on peut rejoindre les 2 segments
  568. for (dwPos2 = dwPos - 3*m_Max_Alignement; dwPos2 < dwPos; dwPos2++)
  569. {
  570. if (dwPos2 >= 0)
  571. {
  572. tContinue2[dwPos2] = 1;
  573. }
  574. }
  575. }
  576. }
  577. }
  578. int indexSegments = 0;
  579. bNonContinue = true;
  580. int maxSegment = 0;
  581. int longueurSegment = 0;
  582. int indexMaxSegment = 1;
  583. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  584. {
  585. if (tContinue2[dwPos] == 0)
  586. {
  587. bNonContinue = true;
  588. }
  589. if ((tContinue2[dwPos] == 1) && bNonContinue)
  590. {
  591. indexSegments++;
  592. bNonContinue = false;
  593. longueurSegment = 0;
  594. }
  595. // 2 - On num�rote chacun des segments
  596. if (tContinue2[dwPos] == 1)
  597. {
  598. tContinue2[dwPos] = indexSegments;
  599. longueurSegment++;
  600. if (longueurSegment > maxSegment)
  601. {
  602. maxSegment = longueurSegment;
  603. indexMaxSegment = indexSegments;
  604. }
  605. }
  606. }
  607. // 3 - Si plus de 1 segment on regarde celui qui est le plus grand
  608. if (indexSegments > 1)
  609. {
  610. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  611. {
  612. if (tContinue2[dwPos] != indexMaxSegment)
  613. {
  614. // 4- On efface les traits continus des segments qui ne sont pas le plus long
  615. tContinue[dwPos] = 0;
  616. }
  617. }
  618. }
  619. dwMin = long (-1);
  620. pInfo = &m_pMeasures[0];
  621. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  622. {
  623. pInfo->m_fValid = (tContinue[dwPos] == 1);
  624. pInfo++;
  625. }
  626. dwMin = long (-1);
  627. pInfo = &m_pMeasures[0];
  628. dist_etalon = 0;
  629. dist_etalon2 = 0;
  630. m_nbpoints_curve = 0;
  631. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  632. {
  633. if (pInfo->m_fValid == true)
  634. {
  635. // Au premier point on m�morise la valeur de la distance qui va servir d'�talon pour les autres points
  636. pta.x = m_vUser[dwPos].x;
  637. pta.y = m_vUser[dwPos].y;
  638. ptb.x = pInfo->m_Paroi[0].m_slope[2].m_ptMiddle.x;
  639. ptb.y = pInfo->m_Paroi[0].m_slope[2].m_ptMiddle.y;
  640. pte.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  641. pte.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  642. ptf.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  643. ptf.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  644. if (m_nbpoints_curve == 0)
  645. {
  646. dist_etalon = distance(pta, ptb);
  647. dist_etalon2 = distance(pta, pte);
  648. tpoints[0].x = m_vUser[dwPos].x;
  649. tpoints[0].y = m_vUser[dwPos].y;
  650. m_nbpoints_curve++;
  651. }
  652. else
  653. {
  654. bool outOfImage;
  655. outOfImage = false;
  656. // Intersection entre le cercle centr� sur ptb de rayon dist_etalon, et la droite pta, ptb
  657. if (InterCercleDroite(ptb, dist_etalon, pta, ptb, &s1, &s2))
  658. {
  659. // Renvoie le point le plus proche de pta
  660. // Qui va �tre le nouveau point
  661. ptc = leplusproche(pta, s1, s2);
  662. dist = distance(ptc, pta);
  663. // Contre les bugs aux extr�mit�s des images
  664. if (dist <= (2 * dist_etalon))
  665. //if ((ptc.x <= m_rectCadre.GetRight()) && (ptc.x >= m_rectCadre.GetLeft()))
  666. {
  667. tpoints[m_nbpoints_curve].x = ptc.x;
  668. tpoints[m_nbpoints_curve].y = ptc.y;
  669. }
  670. else
  671. {
  672. outOfImage = true;
  673. }
  674. }
  675. else
  676. {
  677. tpoints[m_nbpoints_curve].x = m_vUser[dwPos].x;
  678. tpoints[m_nbpoints_curve].y = m_vUser[dwPos].y;
  679. }
  680. if (!outOfImage)
  681. {
  682. m_nbpoints_curve++;
  683. }
  684. }
  685. }
  686. pInfo++;
  687. }
  688. moindres_carres_parabole(m_nbpoints_curve, tpoints, &m_coeff_a, &m_coeff_b, &m_coeff_c);
  689. CVector vPerp;
  690. Point point1, point2, point3;
  691. // On recalcul l'EIM, en utilisant cette fois les perpendiculaires � la courbe obtenue
  692. dwMin = long (-1);
  693. int i;
  694. i = 0;
  695. pInfo = &m_pMeasures[0];
  696. bool bDistDeb;
  697. bDistDeb = false;
  698. double ka, kb;
  699. bDebut = false;
  700. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  701. {
  702. if (pInfo->m_fValid == true)
  703. {
  704. pta.x = tpoints[i].x;
  705. pta.y = tpoints[i].y;
  706. // La tangente (d�riv�e) de y = ax2 + b x + c est y = 2ax + b
  707. // Le coefficient directeur de la perpendiculaire � la tangente est -1/b
  708. // Pour la perpendiculaire qui passe par pta.x, pta.y, y = ka x + kb
  709. if (m_coeff_b != 0)
  710. {
  711. ka = (double) -1.0 / (2 * m_coeff_a);
  712. }
  713. else
  714. {
  715. ka = 0.0;
  716. }
  717. kb = pta.y - ka * pta.x;
  718. ptb.y = tpoints[i].y + 2 * dist_etalon;
  719. if (ka != 0)
  720. {
  721. ptb.x = (ptb.y - kb) / ka;
  722. }
  723. else
  724. {
  725. ptb.x = tpoints[i].x;
  726. }
  727. // Intersection entre le cercle centr� sur pta de rayon dist_etalon, et la droite pta, ptb
  728. bool bInter = InterCercleDroite(pta, 2 * dist_etalon2, pta, ptb, &s1, &s2);
  729. if (bInter)
  730. {
  731. if (m_bNearWall)
  732. {
  733. if (s1.y <= s2.y)
  734. {
  735. ptc.x = s1.x;
  736. ptc.y = s1.y;
  737. ptd.x = s2.x;
  738. ptd.y = s2.y;
  739. }
  740. else
  741. {
  742. ptc.x = s2.x;
  743. ptc.y = s2.y;
  744. ptd.x = s1.x;
  745. ptd.y = s1.y;
  746. }
  747. }
  748. else
  749. {
  750. if (s1.y > s2.y)
  751. {
  752. ptc.x = s1.x;
  753. ptc.y = s1.y;
  754. ptd.x = s2.x;
  755. ptd.y = s2.y;
  756. }
  757. else
  758. {
  759. ptc.x = s2.x;
  760. ptc.y = s2.y;
  761. ptd.x = s1.x;
  762. ptd.y = s1.y;
  763. }
  764. }
  765. }
  766. else
  767. {
  768. ptc.x = ptb.x;
  769. ptc.y = ptb.y;
  770. ptd.x = ptb.x;
  771. ptd.y = ptb.y;
  772. }
  773. point1.x = (int) pta.x;
  774. point1.y = (int) pta.y;
  775. point2.x = (int) ptc.x;
  776. point2.y = (int) ptc.y;
  777. point3.x = (int) ptd.x;
  778. point3.y = (int) ptd.y;
  779. m_pt1perp[i].x = point1.x;
  780. m_pt1perp[i].y = point1.y;
  781. m_pt2perp[i].x = point2.x;
  782. m_pt2perp[i].y = point2.y;
  783. i++;
  784. }
  785. pInfo++;
  786. }
  787. /* Enlev�
  788. // Calculs aux extr�mit�s
  789. // Au d�but
  790. dpoint pt0, pt1;
  791. pt0.x = debx;
  792. // y = ax2 + b x + c
  793. pt0.y = (m_coeff_a * pt0.x * pt0.x) + (m_coeff_b * pt0.x) + m_coeff_c;
  794. // La tangente (d�riv�e) de y = ax2 + b x + c est y = 2ax + b
  795. // Le coefficient directeur de la perpendiculaire � la tangente est -1/b
  796. double ka, kb;
  797. // Pour la perpendiculaire qui passe par pta.x, pta.y, y = ka x + kb
  798. if (m_coeff_b != 0)
  799. {
  800. ka = (double) -1.0 / (2 * m_coeff_a);
  801. }
  802. else
  803. {
  804. ka = 0.0;
  805. }
  806. kb = pt0.y - ka * pt0.x;
  807. double kb2 = m_coeff_b;
  808. pt1.y = pt0.y + 2 * dist_etalon;
  809. if (ka != 0)
  810. {
  811. pt1.x = (pt1.y - kb) / ka;
  812. }
  813. else
  814. {
  815. pt1.x = pt0.x;
  816. }
  817. // Intersection entre le cercle centr� sur pt0 de rayon dist_etalon, et la droite xd,yd, ptcel
  818. if (InterCercleDroite(pt0, dist_Debut, pt0, pt1, &s1, &s2))
  819. {
  820. dist2 = distance(s1, ptdeb);
  821. dist3 = distance(s2, ptdeb);
  822. if (dist2 < dist3)
  823. {
  824. m_ptDebut.x = (int) s1.x;
  825. m_ptDebut.y = (int) s1.y;
  826. }
  827. else
  828. {
  829. m_ptDebut.x = (int) s2.x;
  830. m_ptDebut.y = (int) s2.y;
  831. }
  832. }
  833. // A la fin
  834. pt0.x = finx;
  835. // y = ax2 + b x + c
  836. pt0.y = (m_coeff_a * pt0.x * pt0.x) + (m_coeff_b * pt0.x) + m_coeff_c;
  837. // La tangente (d�riv�e) de y = ax2 + b x + c est y = 2ax + b
  838. // Le coefficient directeur de la perpendiculaire � la tangente est -1/b
  839. // Pour la perpendiculaire qui passe par pta.x, pta.y, y = ka x + kb
  840. if (m_coeff_b != 0)
  841. {
  842. ka = (double) -1.0 / (2 * m_coeff_a);
  843. }
  844. else
  845. {
  846. ka = 0.0;
  847. }
  848. kb = pt0.y - ka * pt0.x;
  849. kb2 = m_coeff_b;
  850. pt1.y = pt0.y + 2 * dist_etalon;
  851. if (ka != 0)
  852. {
  853. pt1.x = (pt1.y - kb) / ka;
  854. }
  855. else
  856. {
  857. pt1.x = pt0.x;
  858. }
  859. // Intersection entre le cercle centr� sur pt0 de rayon dist_etalon, et la droite xd,yd, ptcel
  860. if (InterCercleDroite(pt0, dist_Fin, pt0, pt1, &s1, &s2))
  861. {
  862. dist2 = distance(s1, ptfin);
  863. dist3 = distance(s2, ptfin);
  864. if (dist2 < dist3)
  865. {
  866. m_ptFin.x = (int) s1.x;
  867. m_ptFin.y = (int) s1.y;
  868. }
  869. else
  870. {
  871. m_ptFin.x = (int) s2.x;
  872. m_ptFin.y = (int) s2.y;
  873. }
  874. }
  875. */
  876. }
  877. /*----------------------------------------------------------\
  878. | Paroi |
  879. |-----------------------------------------------------------|
  880. | DESCRIPTION : |
  881. | Calcul de l'�paisseur d'une paroi dans une zone donn�e |
  882. \----------------------------------------------------------*/
  883. void CEIMBase::Paroi()
  884. {
  885. long dwPos, dwMin, dwFirst;
  886. int debx, finx;
  887. CEIMInfo *pInfo = &m_pMeasures[0];
  888. #ifdef NEW_EIM
  889. double dist_Debut, dist_Fin;
  890. dpoint pts;
  891. #endif
  892. bool bDebut = false;
  893. dpoint ptdeb, ptfin;
  894. ptdeb.x = ptfin.x = 0;
  895. ptdeb.y = ptfin.y = 0;
  896. m_nbpoints_curve = 0;
  897. m_coeff_a = -1.0;
  898. m_coeff_b = -1.0;
  899. m_coeff_c = -1.0;
  900. assert(!m_fDiameter && m_pMeasures && GfxImageValid());
  901. dwMin = long (-1);
  902. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  903. {
  904. // Ligne perpendiculaire � la paroi sur laquelle effectuer la mesure
  905. pInfo->m_Paroi[0].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 0);
  906. if (AddVector(pInfo->m_Paroi[0]))
  907. {
  908. ComputeEIM(pInfo);
  909. // recherche des premi�res position valides, afin de r�duire l'�tendue de l'histogramme
  910. dwFirst = pInfo->m_Paroi[0].m_slope[0].m_dwPos[0];
  911. if (dwFirst < dwMin)
  912. {
  913. dwMin = dwFirst;
  914. }
  915. if (bDebut == false)
  916. {
  917. bDebut = true;
  918. debx = m_vUser[dwPos].x;
  919. #ifndef NEW_EIM
  920. ptdeb.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  921. ptdeb.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  922. #endif
  923. }
  924. #ifndef NEW_EIM
  925. ptfin.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  926. ptfin.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  927. #endif
  928. finx = m_vUser[dwPos].x;
  929. }
  930. else
  931. {
  932. pInfo->m_fValid = false;
  933. }
  934. pInfo->m_diagnostic = m_diag;
  935. pInfo++;
  936. }
  937. #ifdef NEW_EIM
  938. // Modif CJ2007
  939. if (m_Assist)
  940. {
  941. ParallelismeEIM();
  942. CVector vPerp;
  943. // On recalcul l'EIM, en utilisant cette fois les perpendiculaires � la courbe obtenue
  944. dwMin = long (-1);
  945. int i;
  946. i = 0;
  947. pInfo = &m_pMeasures[0];
  948. bool bDistDeb;
  949. bDistDeb = false;
  950. bDebut = false;
  951. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  952. {
  953. if (pInfo->m_fValid == true)
  954. {
  955. if ((m_pt1perp[i].y >= 0) && (m_pt2perp[i].y >= 0) && (m_pt1perp[i].x >= 0) && (m_pt2perp[i].x >= 0)
  956. && (m_pt1perp[i].y < 576) && (m_pt2perp[i].y < 576) && (m_pt1perp[i].x < 768) && (m_pt2perp[i].x < 768))
  957. {
  958. pInfo->m_Paroi[0].m_vMeasure = CVector(m_pt1perp[i], m_pt2perp[i]);
  959. if (AddVector(pInfo->m_Paroi[0]))
  960. {
  961. ComputeEIM(pInfo);
  962. // Recherche des premi�res position valides, afin de r�duire l'�tendue de l'histogramme
  963. dwFirst = pInfo->m_Paroi[0].m_slope[0].m_dwPos[0];
  964. if (dwFirst < dwMin)
  965. {
  966. dwMin = dwFirst;
  967. }
  968. if (bDebut == false)
  969. {
  970. bDebut = true;
  971. ptdeb.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  972. ptdeb.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  973. }
  974. ptfin.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  975. ptfin.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  976. dpoint ptt, ptr;
  977. ptt.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  978. ptt.y = (m_coeff_a * ptt.x * ptt.x) + (m_coeff_b * ptt.x) + m_coeff_c;
  979. ptr.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  980. ptr.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  981. if (!bDistDeb)
  982. {
  983. bDistDeb = true;
  984. dist_Debut = distance(ptt, ptr);
  985. }
  986. dist_Fin = distance(ptt, ptr);
  987. }
  988. else
  989. {
  990. pInfo->m_fValid = false;
  991. }
  992. pts.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  993. }
  994. i++;
  995. }
  996. pInfo++;
  997. }
  998. }
  999. #endif
  1000. if (ptdeb.x < ptfin.x)
  1001. {
  1002. m_ptDebut.x = (long) ptdeb.x;
  1003. m_ptFin.x = (long) ptfin.x;
  1004. }
  1005. else
  1006. {
  1007. m_ptDebut.x = (long) ptfin.x;
  1008. m_ptFin.x = (long) ptdeb.x;
  1009. }
  1010. // Ajustement des vecteurs de mesures et des positions
  1011. pInfo = &m_pMeasures[0];
  1012. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  1013. {
  1014. pInfo->m_Paroi[0].m_slope[0].m_dwPos[0] -= dwMin;
  1015. pInfo->m_Paroi[0].m_slope[0].m_dwPos[1] -= dwMin;
  1016. pInfo->m_Paroi[0].m_slope[0].m_dwMiddle -= dwMin;
  1017. pInfo->m_Paroi[0].m_slope[1].m_dwPos[0] -= dwMin;
  1018. pInfo->m_Paroi[0].m_slope[1].m_dwPos[1] -= dwMin;
  1019. pInfo->m_Paroi[0].m_slope[1].m_dwMiddle -= dwMin;
  1020. pInfo->m_Paroi[0].m_slope[2].m_dwPos[0] -= dwMin;
  1021. pInfo->m_Paroi[0].m_slope[2].m_dwPos[1] -= dwMin;
  1022. pInfo->m_Paroi[0].m_slope[2].m_dwMiddle -= dwMin;
  1023. pInfo->m_Paroi[0].m_vMeasure = CVector(pInfo->m_Paroi[0].m_vMeasure[dwMin], pInfo->m_Paroi[0].m_vMeasure.EndPoint());
  1024. pInfo++;
  1025. }
  1026. } // end of Paroi
  1027. /*-----------------------------------------------------------\
  1028. | ParallelismeDistensibilite |
  1029. |-----------------------------------------------------------|
  1030. | DESCRIPTION : |
  1031. | Fonction de calcul du parall�lisme du trait utilisateur |
  1032. | Par rapport � la paroi |
  1033. | Pour le calcul du diam�tre pour la distensibilit� |
  1034. \----------------------------------------------------------*/
  1035. void CEIMBase::ParallelismeDistensibilite()
  1036. {
  1037. int nbOk;
  1038. long dwPos;
  1039. dpoint pta, ptb, ptc, s1, s2;
  1040. double distMoy, sommeDist;
  1041. dpoint tpoints[MAX_POINTS_EIM_AUTO];
  1042. double ka, kb;
  1043. Point vp1, vp2;
  1044. bool bInter;
  1045. CEIMInfo *pInfo;
  1046. ka = 0;
  1047. kb = 0;
  1048. // 1)- On va estimer la distance du milieu de la veine sur les points valides
  1049. nbOk = 0;
  1050. distMoy = 0;
  1051. sommeDist = 0;
  1052. pInfo = &m_pMeasures [0];
  1053. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  1054. {
  1055. pInfo->m_Paroi[0].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 0);
  1056. // pour l'histogramme, le deuxi�me vecteur est requis m�me si la mesure a �chou�
  1057. pInfo->m_Paroi[1].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 1);
  1058. if (AddVector(pInfo->m_Paroi [0])
  1059. && ((m_algoDiameter == algoProfile) ?
  1060. AddVector(pInfo->m_Paroi [1]) : // recherche d'un profil sur la paroi sup�rieure
  1061. FindOpposite(pInfo->m_Paroi[0], pInfo->m_Paroi[1]) // recherche sur la paroi sup�rieure du sym�trique de la paroi inf�rieure
  1062. )
  1063. )
  1064. {
  1065. ComputeEIM(pInfo);
  1066. distMoy = (pInfo->m_dblDia / 2.0);
  1067. sommeDist += distMoy;
  1068. nbOk++;
  1069. }
  1070. pInfo++;
  1071. }
  1072. if (nbOk > 0)
  1073. {
  1074. distMoy = sommeDist / nbOk;
  1075. // 2)- On va d�terminer les points au centre
  1076. pInfo = &m_pMeasures [0];
  1077. m_nbpoints_curve = 0;
  1078. nbOk = 0;
  1079. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  1080. {
  1081. pInfo->m_Paroi[0].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 0);
  1082. // On regarde que la paroi du bas pour le parall�lisme
  1083. if (AddVector(pInfo->m_Paroi [0]))
  1084. {
  1085. ComputeEIM(pInfo);
  1086. // Au premier point on m�morise la valeur de la distance qui va servir d'�talon pour les autres points
  1087. pta.x = m_vUser[dwPos].x;
  1088. pta.y = m_vUser[dwPos].y;
  1089. ptb.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  1090. ptb.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  1091. // Intersection cercle centr� sur ptb
  1092. bInter = InterCercleDroite(ptb, distMoy, pta, ptb, &s1, &s2);
  1093. // On prend celui qui est le plus pr�s de pta
  1094. ptc = leplusproche(pta, s1, s2);
  1095. // On stocke le point trouv� pour faire l'approximation
  1096. tpoints[nbOk].x = ptc.x;
  1097. tpoints[nbOk].y = ptc.y;
  1098. nbOk++;
  1099. }
  1100. pInfo++;
  1101. }
  1102. if (nbOk > 4) // Plusieurs points sinon �rron�s
  1103. {
  1104. // Alors on approxime les points par une droite
  1105. RegressionLineaire(nbOk, tpoints, &ka, &kb);
  1106. // On met � jour m_vUser en fonction de la droite approxim�e : il va �tre utilis� par la suite
  1107. vp1.x = m_vUser[0].x;
  1108. vp1.y = (int) ((double) ka * vp1.x + kb);
  1109. vp2.x = m_vUser[dwPos].x;
  1110. vp2.y = (int) ((double) ka * vp2.x + kb);
  1111. // On d�termine les nouvelles valeurs de m_vUser
  1112. // Et c'est celui l� qui va �tre utilis� dans la fonction de base
  1113. m_vUser = CVector (vp1, vp2);
  1114. m_StartPoint.x = vp1.x;
  1115. m_StartPoint.y = vp1.y;
  1116. m_EndPoint.x = vp2.x;
  1117. m_EndPoint.y = vp2.y;
  1118. }
  1119. else
  1120. {
  1121. m_StartPoint.x = m_vUser[0].x;
  1122. m_StartPoint.y = m_vUser[0].y;
  1123. m_EndPoint.x = m_vUser[1].x;
  1124. m_EndPoint.y = m_vUser[1].y;
  1125. }
  1126. // Les calculs de base vont se faire avec le nouvel m_vUser calcul�
  1127. }
  1128. }
  1129. /*----------------------------------------------------------\
  1130. | Diameter |
  1131. |-----------------------------------------------------------|
  1132. | DESCRIPTION : |
  1133. | Mesure du diam�tre d'un vaisseau |
  1134. |-----------------------------------------------------------|
  1135. | PARAMETRES : |
  1136. | pScale : �chelle � utiliser pour les mesures |
  1137. | gfx : image en niveau de gris d'o� lire les donn�es |
  1138. | pt1 : premier point du segment d�terminant la ligne |
  1139. | de la paroi. |
  1140. | pt2 : deuxi�me point du segment |
  1141. \----------------------------------------------------------*/
  1142. void CEIMBase::Diameter()
  1143. {
  1144. CEIMInfo *pInfo;
  1145. long dwMin [2], dwPos, dwFirst;
  1146. assert (m_fDiameter && m_pMeasures && GfxImageValid());
  1147. if (m_parallelismeDiametre)
  1148. {
  1149. ParallelismeDistensibilite();
  1150. }
  1151. dwMin[0] = long(-1);
  1152. dwMin[1] = long(-1);
  1153. bool bDistDeb, bDebut;
  1154. bDistDeb = false;
  1155. bDebut = false;
  1156. pInfo = &m_pMeasures[0];
  1157. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  1158. {
  1159. pInfo->m_Paroi[0].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 0);
  1160. // Pour l'histogramme, le deuxi�me vecteur est requis m�me si la mesure a �chou�
  1161. pInfo->m_Paroi[1].m_vMeasure = m_vUser.Orthogonal(m_vUser[dwPos], 1);
  1162. if ( AddVector(pInfo->m_Paroi [0])
  1163. && ( (m_algoDiameter == algoProfile) ?
  1164. AddVector(pInfo->m_Paroi [1]) : // recherche d'un profil sur la paroi sup�rieure
  1165. FindOpposite (pInfo->m_Paroi[0], pInfo->m_Paroi[1]) // recherche sur la paroi sup�rieure du sym�trique de la paroi inf�rieure
  1166. )
  1167. )
  1168. {
  1169. ComputeEIM (pInfo);
  1170. // recherche des premi�res position valides, afin de r�duire l'�tendue de l'histogramme
  1171. for (int j = 0; j < 2; j++)
  1172. {
  1173. dwFirst = pInfo->m_Paroi[j].m_slope[0].m_dwPos[0];
  1174. if (dwFirst < dwMin [j])
  1175. dwMin[j] = dwFirst;
  1176. }
  1177. }
  1178. else
  1179. {
  1180. // recalcul syst�matique, car cette fonction est appel� lors de la modification des seuils
  1181. pInfo->m_fValid = false;
  1182. }
  1183. pInfo++;
  1184. }
  1185. // ajustement des vecteurs de mesures et des positions
  1186. pInfo = &m_pMeasures [0];
  1187. for (dwPos = 0; dwPos < m_dwPoints; dwPos++)
  1188. {
  1189. for (int i = 0; i < 2; i++)
  1190. {
  1191. pInfo->m_Paroi[i].m_slope[0].m_dwPos[0] -= dwMin[i];
  1192. pInfo->m_Paroi[i].m_slope[0].m_dwPos[1] -= dwMin[i];
  1193. pInfo->m_Paroi[i].m_slope[0].m_dwMiddle -= dwMin[i];
  1194. pInfo->m_Paroi[i].m_slope[1].m_dwPos[0] -= dwMin[i];
  1195. pInfo->m_Paroi[i].m_slope[1].m_dwPos[1] -= dwMin[i];
  1196. pInfo->m_Paroi[i].m_slope[1].m_dwMiddle -= dwMin[i];
  1197. pInfo->m_Paroi[i].m_vMeasure = CVector (pInfo->m_Paroi[i].m_vMeasure[dwMin[i]], pInfo->m_Paroi[i].m_vMeasure.EndPoint());
  1198. }
  1199. pInfo++;
  1200. }
  1201. } // end of Diameter
  1202. /*----------------------------------------------------------\
  1203. | CEIM::AddVector |
  1204. |-----------------------------------------------------------|
  1205. | DESCRIPTION : |
  1206. | Calcul de l'�paisseur d'une paroi dans une zone donn�e |
  1207. |-----------------------------------------------------------|
  1208. | PARAMETRES : |
  1209. | paroi : CEIMInfo � remplir avec les mesures |
  1210. \----------------------------------------------------------*/
  1211. bool CEIMBase::AddVector(sParoi &paroi)
  1212. {
  1213. long dwPoint, dwLast = THICKNESS - 1; // le dernier point sur lequel effectuer une mesure (au pire)
  1214. // on s'assure que le vecteur ne d�passe pas la zone d'affichage
  1215. // paroi.m_vMeasure.Mask (*m_pGfx); dwLast = min( dwMax, m_vMeasure.Length())
  1216. assert (PointInBuffer (paroi.m_vMeasure [0]));
  1217. // afin de traiter la variation d'intensit� en m�me temps, on r�cup�re le premier
  1218. // point ind�pendamment des autres
  1219. // ASSERT ((paroi.m_vMeasure [0].x != 301) && (paroi.m_vMeasure [0].x != 336));
  1220. m_bBuffer [0] = GetIntensity (paroi.m_vMeasure [0]);
  1221. for (dwPoint = 1; dwPoint <= dwLast; dwPoint++)
  1222. {
  1223. const Point &pt = paroi.m_vMeasure [dwPoint];
  1224. if (PointInBuffer (pt))
  1225. {
  1226. // remplissage de la m�moire tampon
  1227. m_bBuffer [dwPoint] = GetIntensity (pt);
  1228. // calcul de la variation de densit�
  1229. m_cOffsets [dwPoint] = Delta (m_bBuffer [dwPoint], m_bBuffer [dwPoint - 1]);
  1230. }
  1231. else // peu �l�gant, mais efficace
  1232. {
  1233. dwLast = dwPoint - 1; // interrompra �galement la prochaine boucle (de d�tection de profil)
  1234. }
  1235. }
  1236. // On mesure l'E.I.M. sur la ligne extraite
  1237. if (m_versionTomtecAout08)
  1238. {
  1239. // Pour pouvoir afficher les points milieux m�me s'ils sont pas valides
  1240. int res = MeasureLineBuffer (paroi, m_bBuffer, m_cOffsets, dwPoint);
  1241. {
  1242. SetMiddlePoint (paroi.m_slope [0], paroi.m_vMeasure);
  1243. SetMiddlePoint (paroi.m_slope [1], paroi.m_vMeasure);
  1244. // On mesure l'IMT sur la ligne extraite
  1245. SetMiddlePoint (paroi.m_slope [2], paroi.m_vMeasure, true);
  1246. if (res)
  1247. {
  1248. return (true);
  1249. }
  1250. }
  1251. }
  1252. else
  1253. {
  1254. if (MeasureLineBuffer (paroi, m_bBuffer, m_cOffsets, dwPoint) > 0)
  1255. {
  1256. SetMiddlePoint (paroi.m_slope [0], paroi.m_vMeasure);
  1257. SetMiddlePoint (paroi.m_slope [1], paroi.m_vMeasure);
  1258. // On mesure l'IMT sur la ligne extraite
  1259. SetMiddlePoint (paroi.m_slope [2], paroi.m_vMeasure, true);
  1260. return (true);
  1261. }
  1262. }
  1263. return (false);
  1264. } // end of AddVector
  1265. /*----------------------------------------------------------\
  1266. | FindOpposite |
  1267. |-----------------------------------------------------------|
  1268. | DESCRIPTION : |
  1269. | Recherche le point adventice sym�trique|
  1270. |-----------------------------------------------------------|
  1271. | PARAMETRES : |
  1272. | paroi : CEIMInfo � remplir avec les mesures |
  1273. \----------------------------------------------------------*/
  1274. bool CEIMBase::FindOpposite(sParoi &paroi1, sParoi &paroi0)
  1275. {
  1276. long dwSeek = paroi0.m_slope[0].m_dwIntensity,
  1277. dwMax = GetIntensity(paroi1.m_vMeasure[paroi0.m_slope[1].m_dwPos[1]]),
  1278. dwPoint;
  1279. bool fFound, fInGfx;
  1280. // afin de traiter la variation d'intensit� en m�me temps, on r�cup�re le premier
  1281. // point ind�pendamment des autres
  1282. dwPoint = 0;
  1283. fFound = false;
  1284. fInGfx = true;
  1285. do
  1286. {
  1287. const Point &pt = paroi1.m_vMeasure [dwPoint];
  1288. fInGfx = PointInBuffer (pt);
  1289. if (fInGfx)
  1290. {
  1291. unsigned char bLevel = GetIntensity (pt);
  1292. m_bBuffer [dwPoint] = bLevel;
  1293. if (bLevel < dwSeek)
  1294. dwPoint++;
  1295. else if (bLevel > dwMax)
  1296. // la valeur trouv�e d�passe la valeur du sommet de la pente de la paroi
  1297. // du bas, on consid�re que c'est une erreur
  1298. fInGfx = false;
  1299. else
  1300. {
  1301. long dwPos = dwPoint;
  1302. // il est tr�s peu probable que l'on arrive juste sur le milieu de la pente.
  1303. // on cherche donc les extr�mes.
  1304. // recherche du bas de la pente
  1305. while (dwPoint && (m_bBuffer [dwPoint - 1] <= m_bBuffer [dwPoint]))
  1306. dwPoint--;
  1307. paroi1.m_slope [1].m_dwPos [0] = dwPoint;
  1308. // recherche du sommet de la pente
  1309. dwPoint = dwPos + 1;
  1310. paroi1.m_slope [1].m_dwPos [1] = 0; // normalement d�j� fait
  1311. while (!paroi1.m_slope [1].m_dwPos [1])
  1312. {
  1313. const Point &pt = paroi1.m_vMeasure [dwPoint];
  1314. if (!PointInBuffer (pt))
  1315. paroi1.m_slope [1].m_dwPos [1] = dwPoint - 1;
  1316. else
  1317. {
  1318. m_bBuffer [dwPoint] = GetIntensity (pt);
  1319. if (m_bBuffer [dwPoint] > m_bBuffer [dwPoint - 1])
  1320. dwPoint++;
  1321. else
  1322. paroi1.m_slope [1].m_dwPos [1] = dwPoint - 1;
  1323. }
  1324. }
  1325. // la 1� pente est ignor�e par cette m�thode, seule la 2� pente est analys�e
  1326. SetMiddlePoint (paroi1.m_slope [1], paroi1.m_vMeasure);
  1327. fFound = true;
  1328. }
  1329. }
  1330. } while (fInGfx && !fFound);
  1331. return (fFound);
  1332. } // end of FindOpposite
  1333. /*----------------------------------------------------------\
  1334. | SetMiddlePoints |
  1335. |-----------------------------------------------------------|
  1336. | DESCRIPTION : |
  1337. | D�termine la position des deux points encadrants le |
  1338. | milieu d'une des deux pentes. |
  1339. | Les deux points retourn�s peuvent �tre confondus. |
  1340. |-----------------------------------------------------------|
  1341. | PARAMETRES : |
  1342. | slope : pente sur laquelle effectuer les mesures |
  1343. | vMeasure : vecteur sur lequel cette pente a �t� d�tect�e |
  1344. \----------------------------------------------------------*/
  1345. void CEIMBase::SetMiddlePoint(
  1346. sSlope &slope,
  1347. CVector &vMeasure,
  1348. bool reverseSlope)
  1349. {
  1350. int iMean;
  1351. long dwPos;
  1352. // on utilise le double du milieu, car 80+21/2=50, pas 50.5 puisque c'est un entier
  1353. //assert (AfxIsValidAddress (&slope, sizeof (slope)));
  1354. // [JAK - 06/09/02] l'assert surgit un peu trop souvent lors de mesure de la distensibilit�
  1355. // if ( reverseSlope )
  1356. // ASSERT (m_bBuffer[slope.m_dwPos[0]] > m_bBuffer [slope.m_dwPos[1]]);//ICI
  1357. // else
  1358. // ASSERT (m_bBuffer[slope.m_dwPos[0]] < m_bBuffer [slope.m_dwPos[1]]);
  1359. dwPos = slope.m_dwPos[0];
  1360. iMean = m_bBuffer [dwPos] + m_bBuffer [slope.m_dwPos [1]];
  1361. if (reverseSlope)
  1362. while (m_bBuffer [dwPos] * 2 > iMean) dwPos++;
  1363. else
  1364. while (m_bBuffer [dwPos] * 2 < iMean) dwPos++;
  1365. // La mesure d'EIM est maintenant faite ici, car les intensit�s des points sont
  1366. // n�cessaires pour estimer la position exacte du milieu (en INTENSITE)
  1367. if (m_bBuffer [dwPos] * 2 == iMean)
  1368. {
  1369. // en cas d'�galit�, les deux points sont confondus
  1370. slope.m_ptDraw =
  1371. slope.m_ptMiddle = vMeasure [dwPos];
  1372. slope.m_dblMiddle = 0.0;
  1373. }
  1374. else
  1375. {
  1376. dwPos--;
  1377. slope.m_ptMiddle = vMeasure [dwPos];
  1378. if ( reverseSlope )
  1379. {
  1380. if (iMean - 2 * m_bBuffer [dwPos + 1] < 2 * m_bBuffer [dwPos] - iMean)
  1381. slope.m_ptDraw = slope.m_ptMiddle;
  1382. else
  1383. slope.m_ptDraw = vMeasure [dwPos + 1];
  1384. // [JAK - 3/8/2002] ASSERT (m_bBuffer [dwPos + 1] < m_bBuffer [dwPos]);
  1385. }
  1386. else
  1387. {
  1388. if (2 * m_bBuffer [dwPos + 1] - iMean > iMean - 2 * m_bBuffer [dwPos])
  1389. slope.m_ptDraw = slope.m_ptMiddle;
  1390. else
  1391. slope.m_ptDraw = vMeasure [dwPos + 1];
  1392. //assert (m_bBuffer [dwPos + 1] > m_bBuffer [dwPos]);
  1393. }//
  1394. assert (abs (slope.m_ptMiddle.x - vMeasure [dwPos + 1].x) <= 1);
  1395. assert (abs (slope.m_ptMiddle.y - vMeasure [dwPos + 1].y) <= 1);
  1396. slope.m_dblMiddle =
  1397. ( double (iMean - m_bBuffer [dwPos] * 2)
  1398. * CVector (slope.m_ptMiddle, vMeasure [dwPos + 1]).Norm ()
  1399. / (m_bBuffer [dwPos + 1] - m_bBuffer [dwPos]) // bug potentiel : division par zero [JAK - 15/10/2002]
  1400. / 2
  1401. );
  1402. }
  1403. // permet un affichage beaucoup plus rapide de l'histogramme
  1404. slope.m_dwMiddle = dwPos;
  1405. slope.m_dwIntensity = iMean / 2;
  1406. } // fin de SetMiddlePoints
  1407. /*----------------------------------------------------------\
  1408. | CEIM::MeasureLineBuffer |
  1409. |-----------------------------------------------------------|
  1410. | DESCRIPTION : |
  1411. | Mesure de l'E.I.M. � partir d'un buffer d'intensit� et |
  1412. | de variation |
  1413. |-----------------------------------------------------------|
  1414. | PARAMETRES : |
  1415. | paroi : Info � d�finir sur la mesure d'EIM |
  1416. | pbIntensity : pointeur sur les intensit�s |
  1417. | pcOffsets : pointeur sur les variations d'intensit� |
  1418. | dwPoints : nombre de points � �tudier |
  1419. |-----------------------------------------------------------|
  1420. | RETOUR : |
  1421. | un bool�en indiquant si le profil a �t� reconnu |
  1422. \----------------------------------------------------------*/
  1423. int CEIMBase::MeasureLineBuffer
  1424. (
  1425. sParoi &paroi,
  1426. unsigned char* pbBuffer,
  1427. char *pcOffsets,
  1428. long dwPoints
  1429. )
  1430. {
  1431. m_diag = 0; // Permet de voir o� l'algorithme s'est arr�t� (afin de l'am�liorer)
  1432. // Valeur n�gative
  1433. if (dwPoints < 3)
  1434. {
  1435. return (0);
  1436. }
  1437. else
  1438. {
  1439. long dwStart, dwPos, dwFirst, dwLast, dwLastChanged;
  1440. bool fChanged;
  1441. /////////////////////////////////
  1442. // lissage de la courbe de densit�
  1443. /////////////////////////////////
  1444. // il ne faut pas corriger les ext�rieurs sinon, � cause du report,
  1445. // tous les points seront corrig�s
  1446. // sur 300 points le lissage dure moins d'une milliseconde
  1447. dwFirst = 2;
  1448. dwLastChanged = dwLast = dwPoints - 2;
  1449. do
  1450. {
  1451. char c, c1, c2, c3;
  1452. fChanged = false;
  1453. // on ne prend pas en compte les variations nulles, autrement dit
  1454. // un 1,1,0,-1,1 ->1,1,0,1(ou 0),1.
  1455. // ainsi les variations de 1 pixel sont ignor�es
  1456. // on conserve donc en m�moire le dernier point significatif (au d�but 0...)
  1457. c1 = pcOffsets [dwFirst - 1];
  1458. for (dwPos = dwFirst; dwPos < dwLast; dwPos++)
  1459. {
  1460. c = pcOffsets [dwPos - 1];
  1461. if (c) // non nul
  1462. c1 = c; // nouvelle variation
  1463. c2 = pcOffsets [dwPos ];
  1464. c3 = pcOffsets [dwPos + 1];
  1465. // on met � jour le pt central � jour si les deux extr�mes varient dans le m�me sens
  1466. // et que le point central varie dans le sens inverse.
  1467. if ((c1 == c3) && (c2 != c1))
  1468. {
  1469. pbBuffer [dwPos ] = (unsigned char )((pbBuffer [dwPos - 1] + pbBuffer [dwPos + 1]) / 2);
  1470. // on est oblig� de recalculer les variations
  1471. pcOffsets [dwPos ] = Delta (m_bBuffer [dwPos ], m_bBuffer [dwPos - 1]);
  1472. pcOffsets [dwPos + 1] = Delta (m_bBuffer [dwPos + 1], m_bBuffer [dwPos ]);
  1473. // ce test n'est pas la pour le FUN !! si l'�cart entre deux intensit� est 1
  1474. // le milieu sera le point de plus faible intensit�, ce qui ne changera rien
  1475. if ((pcOffsets [dwPos] != c2) || (pcOffsets [dwPos + 1] != c3))
  1476. {
  1477. if (!fChanged)
  1478. {
  1479. fChanged = true;
  1480. dwFirst = dwPos;
  1481. }
  1482. // d�s que fChanged est VRAI il faut initialiser dwLastChanged (petit oubli !!)
  1483. dwLastChanged = dwPos; // si on change dwLast, on quitte la boucle!!
  1484. }
  1485. }
  1486. }
  1487. dwLast = dwLastChanged;
  1488. } while (fChanged);
  1489. ////////////////////////////////////
  1490. // recherche du profil de densit� //
  1491. ////////////////////////////////////
  1492. // pour un algo avec gestion de seuils voir fichier EIM/AvecSeuil.cpp
  1493. // a) recherche d'une croissance (3 pixels de suite au moins : 2 variations de m�me sens)
  1494. // � partir du pixel donn�, pour un maximum de points donn�
  1495. // le premier est le plus complexe � trouver.
  1496. #ifdef TEST_FOR_FANTOME
  1497. dwStart = 2;
  1498. #endif
  1499. if ( LookForFirstPoint (dwStart, dwPoints, dwPos, m_bBuffer) )
  1500. {
  1501. m_diag = -1;
  1502. paroi.m_slope [0].m_dwPos [0] = dwPos; // sera modifi� si le delta est insuffisant
  1503. // b) recherche d'une d�croissance (3 pixels de suite au moins : 2 variations de m�me sens)
  1504. bool variation = LookForVariation (dwStart, pcOffsets, dwPoints, enumDown, dwPos);
  1505. #ifdef TEST_FOR_FANTOME
  1506. if ( !variation )
  1507. {
  1508. if ( LookForFirstPoint (dwStart, dwPoints, dwPos, m_bBuffer) )
  1509. {
  1510. variation = LookForVariation (dwStart, pcOffsets, dwPoints, enumDown, dwPos);
  1511. }
  1512. }
  1513. #endif
  1514. if ( variation )
  1515. {
  1516. m_diag = -2;
  1517. paroi.m_slope [0].m_dwPos [1] = dwPos;
  1518. paroi.m_slope [2].m_dwPos [0] = dwPos; // Pour INT
  1519. // "g�n�ration" de plateaux. Suppression des petites irr�gularit�s sur des plateaux,
  1520. // afin de d�tecter ais�ment les zones de saturation
  1521. // ce n'est n�cessaire qu'� ce niveau
  1522. for (dwFirst = dwPos; dwFirst < dwPoints - 3; dwFirst++)
  1523. {
  1524. unsigned char b = pbBuffer [dwFirst];
  1525. // il faut �galement mettre � jour pcOffsets, sinon on engendre une incoh�rence
  1526. if ( (b == pbBuffer [dwFirst + 2])
  1527. && (abs (b - pbBuffer [dwFirst + 1]) < 5))
  1528. {
  1529. pbBuffer [dwFirst + 1] = b;
  1530. pcOffsets [dwFirst + 1] = 0;
  1531. }
  1532. else if ( (b == pbBuffer [dwFirst + 3])
  1533. && (abs (b - pbBuffer [dwFirst + 1]) < 5)
  1534. && (abs (b - pbBuffer [dwFirst + 2]) < 5))
  1535. {
  1536. pbBuffer [dwFirst + 1] = b;
  1537. pbBuffer [dwFirst + 2] = b;
  1538. pcOffsets [dwFirst + 1] = 0;
  1539. pcOffsets [dwFirst + 2] = 0;
  1540. }
  1541. }
  1542. // c) recherche d'une croissance (3 pixels de suite au moins : 2 variations de m�me sens)
  1543. if (LookForVariation (dwStart, pcOffsets, dwPoints, enumUp, dwPos))
  1544. {
  1545. m_diag = -3;
  1546. if (pbBuffer [paroi.m_slope [0].m_dwPos [1]] <= m_bDelta2 + pbBuffer [dwStart - 1])
  1547. {
  1548. m_diag = -4;
  1549. // Test Ajout test 1 180808
  1550. if ((m_versionTomtecAout08 && ((2 * pbBuffer [dwStart - 1])> m_bSeuil1)) || (!m_versionTomtecAout08))
  1551. {
  1552. // if ((2 * pbBuffer [dwStart - 1])> (2 * pbBuffer [paroi.m_slope [0].m_dwPos [1]]))
  1553. {
  1554. paroi.m_slope[1].m_dwPos[0] = dwPos;
  1555. paroi.m_slope[1].m_dwPos[1] = dwStart - 1;
  1556. paroi.m_slope[2].m_dwPos[1] = dwPos;
  1557. }
  1558. return (1);
  1559. }
  1560. }
  1561. if (m_versionTomtecAout08)
  1562. {
  1563. dwStart += 3;
  1564. // On fait 2 fois de suite la recherche d'une croissance 180808
  1565. // La premi�re croissance peut �tre une erreur
  1566. // d) recherche d'une seconde croissance (3 pixels de suite au moins : 2 variations de m�me sens)
  1567. if (LookForVariation (dwStart, pcOffsets, dwPoints, enumUp, dwPos))
  1568. {
  1569. m_diag = -5;
  1570. if (pbBuffer [paroi.m_slope [0].m_dwPos [1]] <= m_bDelta2 + pbBuffer [dwStart - 1])
  1571. {
  1572. m_diag = -6;
  1573. // Test Ajout test 1 180808
  1574. if ((2 * pbBuffer [dwStart - 1])> m_bSeuil1)
  1575. {
  1576. // if ((2 * pbBuffer [dwStart - 1])> (2 * pbBuffer [paroi.m_slope [0].m_dwPos [1]]))
  1577. {
  1578. paroi.m_slope[1].m_dwPos[0] = dwPos;
  1579. paroi.m_slope[1].m_dwPos[1] = dwStart - 1;
  1580. paroi.m_slope[2].m_dwPos[1] = dwPos;
  1581. }
  1582. return (1);
  1583. }
  1584. }
  1585. }
  1586. }
  1587. /*
  1588. // d) recherche d'une d�croissance (3 pixels de suite au moins : 2 variations de m�me sens)
  1589. // il faut que le maximal de la deuxi�me pente soit plus haut que le maximal de la premi�re
  1590. // (c'est un crit�re tr�s efficace pour �liminer de mauvaise mesures, en g�n�ral lorsque la
  1591. // "1�" paroi qui a �t� d�tect�e n'est pas la bonne)
  1592. if (LookForVariation (dwStart, pcOffsets, dwPoints, enumDown, dwPos))
  1593. {
  1594. // on cherche le d�but du plateau si on est dessus, le dernier point doit �tre la fin
  1595. // d'une croissance STRICTE
  1596. dwFirst = dwPos; // on veut conna�tre la taille du plateau
  1597. while (pbBuffer [dwPos] == pbBuffer [dwPos - 1])
  1598. dwPos--;
  1599. if ( (pbBuffer [paroi.m_dwPos [1]] + m_bDelta2 < pbBuffer [dwPos])
  1600. || ((dwFirst - dwPos >= 2) && (pbBuffer [dwPos] >= 240))
  1601. )
  1602. {
  1603. paroi.m_dwPos[3] = dwPos;
  1604. return (1);
  1605. }
  1606. }
  1607. */
  1608. }
  1609. }
  1610. }
  1611. }
  1612. return (0);
  1613. } // end of Measure
  1614. /*----------------------------------------------------------\
  1615. | LookForFirstPoint |
  1616. |-----------------------------------------------------------|
  1617. | DESCRIPTION : |
  1618. | Recherche du premier point caract�ristique de la paroi |
  1619. | Il m�rite � lui seul une fonction... |
  1620. |-----------------------------------------------------------|
  1621. | PARAMETRES : |
  1622. | dwStart : premier point � examine |
  1623. | dwMax : dernier point examinable |
  1624. | dwPos : o� stocker la position trouv�e |
  1625. | pbBuffer : ligne d'intensit� |
  1626. |-----------------------------------------------------------|
  1627. | RETOURNE : |
  1628. | un bool�en indiquant si la variation recherch�e a �t� |
  1629. | trouv�e |
  1630. \----------------------------------------------------------*/
  1631. bool CEIMBase::LookForFirstPoint
  1632. ( long &dwStart,
  1633. long dwMax,
  1634. long &dwPos,
  1635. unsigned char* pbBuffer
  1636. )
  1637. {
  1638. // r�gles de d�tection de la premi�re pente:
  1639. // 1. trois points doivent se se suivre avec une intensit� croissante
  1640. // 2. le dernier des points, doit avoir une intensit� �gal � m_bDelta1 + la moyenne des pr�c�dents
  1641. // 3. au moins trois points cons�cutifs doivent ensuite avoir une intensit� inf�rieur au premier sommet
  1642. //
  1643. // l'intensit� du premier point sert de rep�re
  1644. unsigned char bFirst = pbBuffer [1]; // intensit� du premier point
  1645. unsigned char* pb;
  1646. #ifndef TEST_FOR_FANTOME
  1647. dwStart = 2; // on commence � 2 pour avoir acc�s � -1 et -2
  1648. #endif
  1649. pb = &pbBuffer [dwStart];
  1650. while ( (dwStart < dwMax) &&
  1651. ( ( ( pb [ 0] - bFirst ) < m_bDelta1) // tant que le point courant n'est pas assez lumineux, on continue
  1652. || ( pb [-2] >= pb [-1] ) ) )
  1653. {
  1654. pb++, dwStart++;
  1655. }
  1656. if (dwStart >= dwMax)
  1657. {
  1658. return (false);
  1659. }
  1660. else
  1661. {
  1662. dwPos = dwStart - 1;
  1663. // on incr�mente dwStart jusqu'� une d�croissance STRICTE double
  1664. // une simple d�croissance est une irr�gularit� � ignorer
  1665. while ((dwStart < dwMax) && ((pb [1] >= pb [0]) || (pb [2] >= pb [0])))
  1666. {
  1667. pb++, dwStart++;
  1668. }
  1669. dwStart++; // il faut que l'on pointe sur le d�but de la d�croissance
  1670. if (dwStart >= dwMax)
  1671. {
  1672. return (false);
  1673. }
  1674. else
  1675. {
  1676. pb = &pbBuffer [dwPos];
  1677. // on cherche le premier point � m_bDelta1 du sommet
  1678. // on est certain de trouver un point (au pire dwStart)
  1679. // bFirst = BYTE (pbBuffer [dwStart - 1] - m_bDelta1); // dwStart pointe juste apr�s le sommet
  1680. // while (bFirst < pb [0]) // comparaison STRICTE
  1681. // pb--, dwPos--;
  1682. // on continue tant qu'il y a une d�croissance STRICTE (on autorise UNE irr�gularit� m�me apr�s lissage)
  1683. // sinon si que du noir, on arrive au d�but du segment!!
  1684. // le test sur m_bDelta1 emp�che fr�quemment la d�tection r�elle du d�but de la pente
  1685. while (dwPos && ((pb[0] > pb[-1]) || ((dwPos > 1) && (pb[0] > pb[-2]))))
  1686. {
  1687. pb--, dwPos--;
  1688. }
  1689. return (true);
  1690. }
  1691. }
  1692. } // fin de LookForFirstPoint
  1693. /*----------------------------------------------------------\
  1694. | CEIM::LookForVariation |
  1695. |-----------------------------------------------------------|
  1696. | DESCRIPTION : |
  1697. | Recherche dans le buffer une variation de densit� dans le|
  1698. | sens donn�, et d�place le pointeur tant que cette |
  1699. | variation est maintenue |
  1700. |-----------------------------------------------------------|
  1701. | PARAMETRES : |
  1702. | dwStart : premier point � examine |
  1703. | pcOffsets : tableau de variation de densit�s |
  1704. | dwMax : dernier point examinable |
  1705. | dir : sens de variation recherch� |
  1706. | dwPos : o� stocker la position trouv�e |
  1707. |-----------------------------------------------------------|
  1708. | RETOURNE : |
  1709. | un bool�en indiquant si la variation recherch�e a �t� |
  1710. | trouv�e |
  1711. \----------------------------------------------------------*/
  1712. bool CEIMBase::LookForVariation (long &dwStart, char *pcOffsets, long dwMax, enumDirection dir, long &dwPos)
  1713. {
  1714. char c1, c2;
  1715. assert (dwStart); // le tableau de variation d�bute � 1
  1716. while (dwStart < dwMax)
  1717. {
  1718. c1 = pcOffsets [dwStart];
  1719. c2 = pcOffsets [dwStart + 1];
  1720. if (c1 && (c1 == c2)) // il faut une variation (c1 != 0) <=> (c2 != 0)
  1721. {
  1722. if (dir == enumUp)
  1723. {
  1724. if (c1 < 0)
  1725. {
  1726. return (false); // Sens inverse de celui recherch�
  1727. }
  1728. else
  1729. {
  1730. dwPos = dwStart - 1;
  1731. dwStart++;
  1732. do
  1733. {
  1734. dwStart++;
  1735. // } while ((dwStart < dwMax) && (pcOffsets [dwStart] >= 0));
  1736. } while ((dwStart < dwMax) && (pcOffsets [dwStart] > 0));
  1737. return (true);
  1738. }
  1739. }
  1740. else
  1741. {
  1742. if (c1 > 0)
  1743. {
  1744. return (false); // croissance, au lieu de d�croissance
  1745. }
  1746. else
  1747. {
  1748. dwPos = dwStart - 1;
  1749. dwStart++;
  1750. do
  1751. {
  1752. dwStart++;
  1753. } while ((dwStart < dwMax) && (pcOffsets [dwStart] <= 0));
  1754. return (true);
  1755. }
  1756. }
  1757. }
  1758. dwStart++;
  1759. }
  1760. return (false);
  1761. } // fin de LookForVariation
  1762. /*----------------------------------------------------------\
  1763. | Update |
  1764. |-----------------------------------------------------------|
  1765. | DESCRIPTION : |
  1766. | Mesures des parois reconnues et statistiques |
  1767. |-----------------------------------------------------------|
  1768. | RETOURNE : |
  1769. | VRAI si au moins un profil a �t� reconnu |
  1770. \----------------------------------------------------------*/
  1771. bool CEIMBase::Update (CEIMResult *m_res)
  1772. {
  1773. // ATTENTION, il se peut qu'aucun profil n'ait �t� d�tect�
  1774. // [JAK - 24/6/2002] no histogram window
  1775. //initialisation
  1776. GraphMeanInit();
  1777. m_arVariance.clear();
  1778. m_arVarianceAA.clear();
  1779. m_arVarianceII.clear();
  1780. m_arVarianceINT.clear();
  1781. m_dwValidPoints = 0;
  1782. m_dblDistance = 0.0;
  1783. m_dblEIMMin =
  1784. m_dblEIMMean =
  1785. m_dblEIMMax =
  1786. m_dblINTMin =
  1787. m_dblINTMean =
  1788. m_dblINTMax =
  1789. m_dblEIMdMean =
  1790. m_dblINTdMean =
  1791. m_dblMEDdMean =
  1792. m_dblIAd =
  1793. m_dblDiaAAMin =
  1794. m_dblDiaAAMean =
  1795. m_dblDiaAAMax =
  1796. m_dblDiaIIMin =
  1797. m_dblDiaIIMean =
  1798. m_dblDiaIIMax = 0.0;
  1799. if (m_pMeasures == NULL)
  1800. return (false);
  1801. else
  1802. {
  1803. CEIMInfo *pInfo = &m_pMeasures [0];
  1804. long dw;
  1805. double dblMeanEIM, // valeur moyenne de l'EIM lors de la 1� phase
  1806. dblMeanINT,
  1807. dblMeanEIMd,
  1808. dblMeanINTd,
  1809. dblMeanMEDd,
  1810. dblGapEIM,
  1811. dblMeanQI,
  1812. dblMeanDia, // valeur moyenne du diam�tre lors de la 1� phase
  1813. dblGapDia,
  1814. dblMeanDist, // distance moyenne du 1� milieu au trait utilisateur
  1815. dblStdDist,
  1816. dblGapDist,
  1817. dblII; // diam�tre intima/intima
  1818. // dblGapQI;
  1819. // la premi�re �tape consiste:
  1820. // - � calculer la valeur de l'EIM � partir des points d�tect�s
  1821. // - � calculer la moyenne des mesures afin d'�liminer ensuite
  1822. // celles qui s'�cartent trop de cette valeur moyenne.
  1823. dblGapEIM = 0;
  1824. dblGapDist = 0;
  1825. dblGapDia = 0;
  1826. dblII = 0;
  1827. dblMeanEIM = 0;
  1828. dblMeanINT = 0;
  1829. dblMeanEIMd = 0;
  1830. dblMeanINTd = 0;
  1831. dblMeanMEDd = 0;
  1832. dblMeanDia = 0;
  1833. dblMeanDist = 0;
  1834. dblStdDist = 0.0;
  1835. dblMeanQI = 0.0;
  1836. for (dw = 0; dw < m_dwPoints; dw++)
  1837. {
  1838. if (pInfo->m_fValid) // le profil a �t� rep�r�
  1839. {
  1840. dblMeanEIM += pInfo->m_dblEIM;
  1841. dblMeanINT += pInfo->m_dblINT;//PJT
  1842. dblMeanEIMd += pInfo->m_dblEIMd;
  1843. dblMeanINTd += pInfo->m_dblINTd;
  1844. dblMeanMEDd += pInfo->m_dblMEDd;
  1845. dblMeanDia += pInfo->m_dblDia;
  1846. dblMeanDist += pInfo->m_dblDist;
  1847. dblStdDist += pInfo->m_dblDist * pInfo->m_dblDist;
  1848. dblMeanQI += pInfo->m_dblQI;
  1849. m_dwValidPoints++; // requis pour obtenir la moyenne
  1850. }
  1851. pInfo++;
  1852. }
  1853. if (m_dwValidPoints == 0)
  1854. {
  1855. m_uErrorID = IDS_EIM_FAILED;//BUG ICI //[JAK - 09/09/02]
  1856. return (false); // aucune mesure valide
  1857. }
  1858. else
  1859. {
  1860. try// [JAK - 5/7/2002]
  1861. {
  1862. // calcul des moyennes
  1863. dblMeanEIM /= m_dwValidPoints;
  1864. dblMeanDia /= m_dwValidPoints;
  1865. dblMeanDist /= m_dwValidPoints;
  1866. dblStdDist /= m_dwValidPoints;
  1867. dblMeanINT /= m_dwValidPoints;//PJT
  1868. dblMeanEIMd /= m_dwValidPoints;
  1869. dblMeanINTd /= m_dwValidPoints;
  1870. dblMeanMEDd /= m_dwValidPoints;
  1871. dblMeanQI /= m_dwValidPoints;
  1872. // l'�cart autoris� est �gal � 25% de la moyenne 23/02/99 Touboul
  1873. // l'�cart autoris� est �gal � 50% de la moyenne 06/05/99 Touboul
  1874. // l'�cart autoris� est �gal � 35% de la moyenne 19/07/99 Touboul
  1875. // l'�cart autoris� est �gal � 10% de la moyenne 19/07/05 Touboul
  1876. if (m_versionTomtecAout08)
  1877. {
  1878. dblGapEIM = dblMeanEIM *.25;//.35 20/10/05 PJT // 0.2 180808
  1879. dblGapDia = dblMeanDia *.02;//.04 20/10/05 PJT
  1880. dblGapDist = dblMeanDist *.15;//.25 20/10/05 PJT // 0.2 180808
  1881. }
  1882. else
  1883. {
  1884. dblGapEIM = dblMeanEIM *.20;
  1885. dblGapDia = dblMeanDia *.02;
  1886. dblGapDist = dblMeanDist *.20;
  1887. }
  1888. // dblGapDist = sqrt(dblStdDist - dblMeanDist * dblMeanDist);// 20/12/06 FP
  1889. pInfo = &m_pMeasures[0];
  1890. // exclusion de tous les points hors normes
  1891. for (dw = 0; dw < m_dwPoints; dw++)
  1892. {
  1893. if ( pInfo->m_fValid
  1894. // on exclut tous les point qui s'�cartent trop de la moyenne
  1895. && ( (fabs (pInfo->m_dblEIM - dblMeanEIM ) > dblGapEIM) // EIM incoh�rent
  1896. || (fabs (pInfo->m_dblDist - dblMeanDist) > dblGapDist) // ou distance � l'axe incoh�rente
  1897. || (m_fDiameter && (fabs (pInfo->m_dblDia - dblMeanDia) > dblGapDia)) // ou diam�tre incoh�rent
  1898. || (fabs (pInfo->m_dblQI)> 0.3) // IQ < 50% Touboul
  1899. )
  1900. )
  1901. {
  1902. pInfo->m_fThrownOut = true; // par d�faut � FALSE gr�ce au memset (on laisse valide pour affichage palette)
  1903. pInfo->m_fValid = false;
  1904. m_dwValidPoints--;
  1905. }
  1906. pInfo++;
  1907. }
  1908. // il se peut que TOUS les points soient � + de 20% de la moyenne
  1909. // (par exemple deux lignes tr�s �loign�es)
  1910. if (m_dwValidPoints == 0)
  1911. {
  1912. m_uErrorID = IDS_EIM_FAILED;
  1913. return (false); // aucune mesure valide
  1914. }
  1915. else
  1916. {
  1917. if (m_fDiameter) // Calcul de la moyenne des diam�tres trouv�s
  1918. {
  1919. std::vector<double> arrayAA, arrayII;//il s'agit en faite d'une duplication de m_arVarianceAA et m_arVarianceII
  1920. double dblMeanAA = 0.0;
  1921. double dblMeanII = 0.0;
  1922. double dblVarianceAA = 0.0;
  1923. double dblVarianceII = 0.0;
  1924. // recherche du premier profil valide
  1925. pInfo = &m_pMeasures [0];
  1926. for (dw = 0; !pInfo->m_fValid; dw++)
  1927. {
  1928. pInfo++;
  1929. }
  1930. // on est certain qu'un pInfo valide va �tre trouv�
  1931. //----- resultat d'un calcul de diametre [JAK - 13/1/2003]
  1932. m_dblDiaAAMin = m_dblDiaAAMean = m_dblDiaAAMax = pInfo->m_dblDia;
  1933. m_dblDiaIIMin = m_dblDiaIIMean = m_dblDiaIIMax = pInfo->m_dblDia - 2 * pInfo->m_dblEIM;
  1934. arrayII.push_back(g_pCurrentScale->Distance(m_dblDiaIIMean));
  1935. arrayAA.push_back(g_pCurrentScale->Distance(m_dblDiaAAMean));
  1936. GraphMeanAddMeasure(true, pInfo->m_dblDia);
  1937. m_arVarianceAA.push_back (g_pCurrentScale->Distance (pInfo->m_dblDia));
  1938. m_arVarianceII.push_back (g_pCurrentScale->Distance (pInfo->m_dblDia- 2 * pInfo->m_dblEIM));
  1939. dblMeanAA = g_pCurrentScale->Distance (pInfo->m_dblDia);
  1940. dblMeanII = g_pCurrentScale->Distance (pInfo->m_dblDia - 2 * pInfo->m_dblEIM);
  1941. dw++,pInfo++;
  1942. while (dw < m_dwPoints)
  1943. {
  1944. if (pInfo->m_fValid)
  1945. {
  1946. m_dblDiaAAMean += pInfo->m_dblDia;
  1947. if (pInfo->m_dblDia < m_dblDiaAAMin) m_dblDiaAAMin = pInfo->m_dblDia;
  1948. if (pInfo->m_dblDia > m_dblDiaAAMax) m_dblDiaAAMax = pInfo->m_dblDia;
  1949. dblII = pInfo->m_dblDia - 2 * pInfo->m_dblEIM;
  1950. m_dblDiaIIMean += dblII;
  1951. if (dblII < m_dblDiaIIMin) m_dblDiaIIMin = dblII;
  1952. if (dblII > m_dblDiaIIMax) m_dblDiaIIMax = dblII;
  1953. // [JAK - 24/6/2002] no histogram window
  1954. GraphMeanAddMeasure (true, pInfo->m_dblDia);
  1955. arrayAA.push_back(g_pCurrentScale->Distance(pInfo->m_dblDia));
  1956. arrayII.push_back(g_pCurrentScale->Distance(dblII));
  1957. m_arVarianceAA.push_back (g_pCurrentScale->Distance (pInfo->m_dblDia));
  1958. m_arVarianceII.push_back (g_pCurrentScale->Distance (dblII));
  1959. dblMeanAA += g_pCurrentScale->Distance (pInfo->m_dblDia);
  1960. dblMeanII += g_pCurrentScale->Distance (dblII);
  1961. }
  1962. dw++;
  1963. pInfo++;
  1964. }
  1965. /* if (m_vUser.Length () < QI_MIN)
  1966. {
  1967. CString msg; msg.Format(MyLoadString(IDS_EIM_QI_0), QI_MIN);
  1968. CMessage::Info (msg);
  1969. m_dblQI = 0.;
  1970. }
  1971. else*/
  1972. m_dblQI = double (m_dwValidPoints) / m_dwPoints;
  1973. // calcul de la variance
  1974. dblMeanAA /= (double)m_arVarianceAA.size ();
  1975. dblMeanII /= (double)m_arVarianceII.size ();
  1976. dblVarianceAA = 0.0;
  1977. dblVarianceII = 0.0;
  1978. for (unsigned int i = 0; i < m_arVarianceAA.size (); i++)
  1979. {
  1980. dblVarianceAA += (m_arVarianceAA [i] - dblMeanAA) * (m_arVarianceAA [i] - dblMeanAA);
  1981. dblVarianceII += (m_arVarianceII [i] - dblMeanII) * (m_arVarianceII [i] - dblMeanII);
  1982. }
  1983. dblVarianceAA /= (double)m_arVarianceAA.size ();
  1984. dblVarianceII /= (double)m_arVarianceII.size ();
  1985. m_dblDistance = m_vUser.Norm (g_pCurrentScale);
  1986. m_dblDiaAAMean /= (double)m_dwValidPoints;
  1987. m_dblDiaIIMean /= (double)m_dwValidPoints;
  1988. m_dblDiaAAMin = g_pCurrentScale->Distance (m_dblDiaAAMin);
  1989. m_dblDiaAAMean = g_pCurrentScale->Distance (m_dblDiaAAMean);
  1990. m_dblDiaAAMax = g_pCurrentScale->Distance (m_dblDiaAAMax);
  1991. m_dblDiaIIMin = g_pCurrentScale->Distance (m_dblDiaIIMin);
  1992. m_dblDiaIIMean = g_pCurrentScale->Distance (m_dblDiaIIMean);
  1993. m_dblDiaIIMax = g_pCurrentScale->Distance (m_dblDiaIIMax);
  1994. assert(arrayAA.size() == (size_t)m_dwValidPoints);
  1995. assert(arrayII.size() == (size_t)m_dwValidPoints);
  1996. // double diam = CMeanEstimate::GetMeanEstimate(&arrayAA);
  1997. // m_dblDiaAAMean = (CMeanEstimate::IsANumber(diam)? diam : -1);
  1998. m_dblDiaAAMean = CMeanEstimate::GetMeanEstimate(&arrayAA);
  1999. m_dblDiaIIMean = CMeanEstimate::GetMeanEstimate(&arrayII);
  2000. m_dblVarianceAA = dblVarianceAA;
  2001. m_dblVarianceII = dblVarianceII;
  2002. PrintDiameter();
  2003. if (!CMeanEstimate::IsANumber(m_dblDiaAAMean))
  2004. { //if is is infinite because of the estimate
  2005. return false;
  2006. }
  2007. }
  2008. else // de l'EIM
  2009. {
  2010. double dblMean = 0.0, dblMeanINT = 0.0;
  2011. // double dblMeanEIMd = 0.0, dblMeanINTd = 0.0, dblMeanMEDd = 0.0;
  2012. double dblVariance = 0.0, dblVarianceINT = 0.0;
  2013. imt::Point invalidPoint, tmpPt;
  2014. invalidPoint.x = -1;
  2015. invalidPoint.y = -1;
  2016. if ( m_res )
  2017. {
  2018. m_res->result->numberOfPoints = m_dwPoints;
  2019. m_res->allocate_vectors( m_dwPoints );
  2020. }
  2021. // recherche du premier profil valide
  2022. pInfo = &m_pMeasures [0];
  2023. for (dw = 0; !pInfo->m_fValid; dw++)
  2024. {
  2025. if ( m_res )
  2026. {
  2027. m_res->result->vect_adventitia[dw] = invalidPoint;
  2028. m_res->result->vect_media[dw] = invalidPoint;
  2029. m_res->result->vect_intima[dw] = invalidPoint;
  2030. }
  2031. pInfo++;
  2032. }
  2033. // on est certain qu'un pInfo valide va �tre trouv�
  2034. m_dblEIMMin = m_dblEIMMean = m_dblEIMMax = pInfo->m_dblEIM;
  2035. m_dblINTMin = m_dblINTMean = m_dblINTMax = pInfo->m_dblINT;
  2036. m_dblEIMdMean = pInfo->m_dblEIMd;
  2037. m_dblINTdMean = pInfo->m_dblINTd;
  2038. m_dblMEDdMean = pInfo->m_dblMEDd;
  2039. // [JAK - 24/6/2002] no histogram window
  2040. GraphMeanAddMeasure (true, pInfo->m_dblEIM);
  2041. m_arVariance.push_back (g_pCurrentScale->Distance (pInfo->m_dblEIM));
  2042. m_arVarianceINT.push_back (g_pCurrentScale->Distance (pInfo->m_dblINT));
  2043. dblMean = g_pCurrentScale->Distance (pInfo->m_dblEIM);
  2044. dblMeanINT = g_pCurrentScale->Distance (pInfo->m_dblINT);
  2045. if ( m_res )
  2046. {
  2047. tmpPt.x = pInfo->m_Paroi[0].m_slope[1].m_ptDraw.x;
  2048. tmpPt.y = pInfo->m_Paroi[0].m_slope[1].m_ptDraw.y;
  2049. m_res->result->vect_adventitia[dw] = tmpPt;
  2050. tmpPt.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  2051. tmpPt.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  2052. m_res->result->vect_media[dw] = tmpPt;
  2053. tmpPt.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  2054. tmpPt.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  2055. m_res->result->vect_intima[dw] = tmpPt;
  2056. }
  2057. dw++,pInfo++;
  2058. while (dw < m_dwPoints)
  2059. {
  2060. if (pInfo->m_fValid)
  2061. {
  2062. m_dblEIMMean += pInfo->m_dblEIM;
  2063. if (pInfo->m_dblEIM < m_dblEIMMin) m_dblEIMMin = pInfo->m_dblEIM;
  2064. if (pInfo->m_dblEIM > m_dblEIMMax) m_dblEIMMax = pInfo->m_dblEIM;
  2065. m_dblINTMean += pInfo->m_dblINT;
  2066. if (pInfo->m_dblINT < m_dblINTMin) m_dblINTMin = pInfo->m_dblINT;
  2067. if (pInfo->m_dblINT > m_dblINTMax) m_dblINTMax = pInfo->m_dblINT;
  2068. m_dblEIMdMean += pInfo->m_dblEIMd;
  2069. m_dblINTdMean += pInfo->m_dblINTd;
  2070. m_dblMEDdMean += pInfo->m_dblMEDd;
  2071. // [JAK - 24/6/2002] no histogram window
  2072. GraphMeanAddMeasure (true, pInfo->m_dblEIM);
  2073. m_arVariance.push_back (g_pCurrentScale->Distance (pInfo->m_dblEIM));
  2074. m_arVarianceINT.push_back (g_pCurrentScale->Distance (pInfo->m_dblINT));
  2075. dblMean += g_pCurrentScale->Distance (pInfo->m_dblEIM);
  2076. dblMeanINT += g_pCurrentScale->Distance (pInfo->m_dblINT);
  2077. if ( m_res )
  2078. {
  2079. tmpPt.x = pInfo->m_Paroi[0].m_slope[1].m_ptDraw.x;
  2080. tmpPt.y = pInfo->m_Paroi[0].m_slope[1].m_ptDraw.y;
  2081. m_res->result->vect_adventitia[dw] = tmpPt;
  2082. tmpPt.x = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.x;
  2083. tmpPt.y = pInfo->m_Paroi[0].m_slope[2].m_ptDraw.y;
  2084. m_res->result->vect_media[dw] = tmpPt;
  2085. tmpPt.x = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x;
  2086. tmpPt.y = pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y;
  2087. m_res->result->vect_intima[dw] = tmpPt;
  2088. }
  2089. }
  2090. else
  2091. {
  2092. if ( m_res )
  2093. {
  2094. m_res->result->vect_adventitia[dw] = invalidPoint;
  2095. m_res->result->vect_media[dw] = invalidPoint;
  2096. m_res->result->vect_intima[dw] = invalidPoint;
  2097. }
  2098. }
  2099. dw++;
  2100. pInfo++;
  2101. }
  2102. if (m_vUser.Length () < QI_MIN)
  2103. {
  2104. PrintErrorQIMin();
  2105. m_dblQI = 0.;
  2106. }
  2107. else
  2108. {
  2109. m_dblQI = double (m_dwValidPoints) / m_dwPoints;
  2110. }
  2111. // calcul de la variance
  2112. dblMean /= (double)m_arVariance.size ();
  2113. dblVariance = 0.0;
  2114. dblMeanINT /= (double)m_arVarianceINT.size ();
  2115. dblVarianceINT = 0.0;
  2116. unsigned int i;
  2117. for (i = 0; i < m_arVariance.size (); i++)
  2118. dblVariance += (m_arVariance [i] - dblMean) * (m_arVariance [i] - dblMean);
  2119. dblVariance /= (double)m_arVariance.size ();
  2120. for (i = 0; i < m_arVarianceINT.size (); i++)
  2121. dblVarianceINT += (m_arVarianceINT [i] - dblMeanINT) *
  2122. (m_arVarianceINT [i] - dblMeanINT);
  2123. dblVarianceINT /= (double)m_arVarianceINT.size ();
  2124. m_dblDistance = m_vUser.Norm (g_pCurrentScale);
  2125. // calcul des valeurs moyennes et mise � l'�chelle des normes
  2126. m_dblEIMMean /= (double)m_dwValidPoints;
  2127. m_dblEIMMin = g_pCurrentScale->Distance (m_dblEIMMin);
  2128. m_dblEIMMean = g_pCurrentScale->Distance (m_dblEIMMean);
  2129. m_dblEIMMax = g_pCurrentScale->Distance (m_dblEIMMax);
  2130. m_dblINTMean /= (double)m_dwValidPoints;
  2131. m_dblINTMin = g_pCurrentScale->Distance (m_dblINTMin);
  2132. m_dblINTMean = g_pCurrentScale->Distance (m_dblINTMean);
  2133. m_dblINTMax = g_pCurrentScale->Distance (m_dblINTMax);
  2134. m_dblIA = m_dblINTMean / m_dblEIMMean;
  2135. m_dblEIMdMean /= (double)m_dwValidPoints;
  2136. m_dblINTdMean /= (double)m_dwValidPoints;
  2137. m_dblMEDdMean /= (double)m_dwValidPoints;
  2138. m_dblIAd = m_dblINTdMean / m_dblEIMdMean;
  2139. //#ifdef VERSION_SHOW_VARIANCE // [JAK - 17/6/2002]
  2140. m_dblVariance = dblVariance;
  2141. //#endif
  2142. // [JAK - 4/7/2002] IDS_EIM_RESULT4 = \tE .I.M.\nI.Q.: \t%.2f\nMaximale : \t%.3f mm\nMoyenne : \t%.3f mm\nEcart Type : \t%.3f mm\nMesures Valides :\td%
  2143. PrintResult();
  2144. if ( m_res )
  2145. {
  2146. m_res->result->imt_max = m_dblEIMMax;
  2147. m_res->result->imt_mean = m_dblEIMMean;
  2148. m_res->result->imt_standardDeviation = sqrt (dblVariance);
  2149. m_res->result->intima_mean = m_dblINTMean;
  2150. m_res->result->media_mean = m_dblEIMMean - m_dblINTMean;
  2151. m_res->result->qualityIndex = m_dblQI;
  2152. }
  2153. }
  2154. return (true);
  2155. }
  2156. }catch(...){ // [JAK - 5/7/2002]
  2157. assert(0);
  2158. // not very clean to catch any exception, but it is at least efficient
  2159. //TODO change the "catch(...)" for something more precise like "catch(Float Divide by Zero)"
  2160. m_uErrorID = IDS_EIM_FAILED;
  2161. return (false); // aucune mesure valide
  2162. }
  2163. }
  2164. }
  2165. } // end of Update
  2166. /*----------------------------------------------------------\
  2167. | ComputeEIM |
  2168. |-----------------------------------------------------------|
  2169. | DESCRIPTION : |
  2170. | calcule l'�paisseur EIM et la distance au vecteur trac� |
  2171. | par l'utilisateur � l'aide points d�tect�s |
  2172. |-----------------------------------------------------------|
  2173. | PARAMETRES : |
  2174. | pInfo : une info sur un segment de paroi |
  2175. \----------------------------------------------------------*/
  2176. void CEIMBase::ComputeEIM (CEIMInfo *pInfo)
  2177. {
  2178. pInfo->m_fValid = true;
  2179. // en approximation, m_ptMiddle [0] suffit largement pour la distance, qui n'intervient
  2180. // dans la mesure que pour �carter les points trop �loign�s de la moyenne
  2181. pInfo->m_dblDist = CVector (pInfo->m_Paroi [0].m_slope [0].m_ptMiddle, pInfo->m_Paroi [0].m_vMeasure [0]).Norm ();
  2182. pInfo->m_dblEIM = CVector (pInfo->m_Paroi [0].m_slope [0].m_ptMiddle, pInfo->m_Paroi [0].m_slope [1].m_ptMiddle).Norm ()
  2183. - pInfo->m_Paroi [0].m_slope [0].m_dblMiddle
  2184. + pInfo->m_Paroi [0].m_slope [1].m_dblMiddle;
  2185. pInfo->m_dblINT = CVector (pInfo->m_Paroi [0].m_slope [0].m_ptMiddle, pInfo->m_Paroi [0].m_slope [2].m_ptMiddle).Norm ()
  2186. - pInfo->m_Paroi [0].m_slope [0].m_dblMiddle
  2187. + pInfo->m_Paroi [0].m_slope [2].m_dblMiddle;
  2188. // dans le cas de la paroi, on additionne les deux �carts, car la paroi du bas est mesur�
  2189. // dans le sens oppos� � la paroi du haut
  2190. if (m_fDiameter)
  2191. {
  2192. pInfo->m_dblDia = CVector (pInfo->m_Paroi [0].m_slope [1].m_ptMiddle, pInfo->m_Paroi [1].m_slope [1].m_ptMiddle).Norm ()
  2193. + pInfo->m_Paroi [0].m_slope [1].m_dblMiddle
  2194. + pInfo->m_Paroi [1].m_slope [1].m_dblMiddle;
  2195. }
  2196. else // Calcul des moyennes des intensites entre les differents points
  2197. {
  2198. pInfo->m_dblEIMd = pInfo->m_dblINTd = pInfo->m_dblMEDd = 0.0;
  2199. long dw, nb=0, nbTot=0;
  2200. for ( dw=pInfo->m_Paroi[0].m_slope[0].m_dwMiddle; dw<pInfo->m_Paroi[0].m_slope[2].m_dwMiddle; dw++ )
  2201. {
  2202. nb++;
  2203. nbTot++;
  2204. pInfo->m_dblEIMd += m_bBuffer[dw];
  2205. pInfo->m_dblINTd += m_bBuffer[dw];
  2206. }
  2207. if (nb != 0 ) // Contre la division par 0
  2208. {
  2209. pInfo->m_dblINTd /= (double) nb;
  2210. }
  2211. else
  2212. {
  2213. pInfo->m_dblINTd = 0;
  2214. }
  2215. nb = 0;
  2216. for ( dw=pInfo->m_Paroi[0].m_slope[2].m_dwMiddle; dw<pInfo->m_Paroi[0].m_slope[1].m_dwMiddle; dw++ )
  2217. {
  2218. nb++;
  2219. nbTot++;
  2220. pInfo->m_dblEIMd += m_bBuffer[dw];
  2221. pInfo->m_dblMEDd += m_bBuffer[dw];
  2222. }
  2223. if (nb != 0) // Contre la division par 0
  2224. {
  2225. pInfo->m_dblMEDd /= (double) nb;
  2226. }
  2227. else
  2228. {
  2229. pInfo->m_dblMEDd = 0;
  2230. }
  2231. if (nbTot != 0) // Contre la division par 0
  2232. {
  2233. pInfo->m_dblEIMd /= (double) nbTot;
  2234. }
  2235. else
  2236. {
  2237. pInfo->m_dblEIMd = 0;
  2238. }
  2239. }
  2240. } // fin de ComputeEIM
  2241. /*----------------------------------------------------------\
  2242. | Direction |
  2243. |-----------------------------------------------------------|
  2244. | DESCRIPTION : |
  2245. | Retourne la direction de la droite approxim�e constitu�e |
  2246. | d'apr�s l'ensemble des points mesur�s! |
  2247. \----------------------------------------------------------*/
  2248. double CEIMBase::Direction()
  2249. {
  2250. double r = 0;
  2251. double x = 0, y = 0;
  2252. Point LastPoint( 0, 0 );
  2253. double Valide = 0;
  2254. double sx, sx2, sy, sy2;
  2255. int nbPoints;
  2256. double xmin, xmax, ymin, ymax;
  2257. double moyx, moyy, stdx, stdy;
  2258. if (m_pMeasures)
  2259. {
  2260. sx = sx2 = sy = sy2 = 0.0;
  2261. nbPoints = 0;
  2262. // Calcul de la somme des x et des y et de la somme des x2 et des y2
  2263. CEIMInfo *pInfo = &m_pMeasures[0];
  2264. for (long dw = 0; dw < m_dwPoints; dw++)
  2265. {
  2266. if (pInfo->m_fValid)
  2267. {
  2268. if (dw)
  2269. {
  2270. x = (pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x - LastPoint.x);
  2271. y = (pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y - LastPoint.y);
  2272. if (x)
  2273. {
  2274. sx += x;
  2275. sx2 += (x * x);
  2276. sy += y;
  2277. sy2 += (y * y);
  2278. nbPoints++;
  2279. }
  2280. }
  2281. LastPoint = pInfo->m_Paroi[0].m_slope[0].m_ptDraw;
  2282. }
  2283. pInfo++;
  2284. }
  2285. // Calcul des moyennes et des �carts types
  2286. if (nbPoints != 0)
  2287. {
  2288. moyx = sx / (double) nbPoints;
  2289. moyy = sy / (double) nbPoints;
  2290. stdx = sqrt( (sx2 / (double) nbPoints) - sx * sx);
  2291. stdy = sqrt( (sy2 / (double) nbPoints) - sy * sy);
  2292. xmin = moyx - 2 * stdx;
  2293. xmax = moyx + 2 * stdx;
  2294. ymin = moyy - 2 * stdy;
  2295. ymax = moyy + 2 * stdy;
  2296. }
  2297. pInfo = &m_pMeasures[0];
  2298. for (long dw = 0; dw < m_dwPoints; dw++)
  2299. {
  2300. if (pInfo->m_fValid)
  2301. {
  2302. if (dw)
  2303. {
  2304. x = (pInfo->m_Paroi[0].m_slope[0].m_ptDraw.x - LastPoint.x);
  2305. y = (pInfo->m_Paroi[0].m_slope[0].m_ptDraw.y - LastPoint.y);
  2306. if (x)
  2307. {
  2308. // if ((x >= xmin) && (x <= xmax) && (y >= ymin) && (y <= ymax))
  2309. {
  2310. r += y / x;
  2311. Valide++;
  2312. }
  2313. }
  2314. }
  2315. LastPoint = pInfo->m_Paroi[0].m_slope [0].m_ptDraw;
  2316. }
  2317. pInfo++;
  2318. }
  2319. }
  2320. if (Valide < 20) return 0; // Nombre de points valides insuffisants
  2321. Point PtDirect(100, (int) (100.0 * r / Valide));
  2322. PtDirect.Offset(m_vUser.StartPoint());
  2323. if ( (m_vUser.Angle(PtDirect) > 20) && (m_vUser.Angle(PtDirect) < 160) ) return 0;
  2324. return (r / Valide);
  2325. }
  2326. unsigned int CEIMBase::GetErrorID(void)
  2327. {
  2328. return m_uErrorID;
  2329. }