StenoseBase.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*******************************************************************\
  2. Fichier : Stenose.cpp
  3. Date : 20/04/98
  4. Version : 1.001
  5. Description : fonctions de mesures de sténose
  6. |*******************************************************************|
  7. Bugs:
  8. Notes:
  9. L'ellipse donnée peut être entièrement contenue dans le vaisseau,
  10. c'est pour cela que l'on utilise les régions plutôt que le
  11. rectangle englobant qui peut contenir des points de couleur.
  12. Un rapport entre la surface de l'ellipse et du rectangle est
  13. donc erroné, si des points de couleur sont entre le rectangle
  14. et l'ellipse
  15. |*******************************************************************|
  16. Historique :
  17. 20/04/98 1.001 : L'ellipse n'était pas affichée si aucun point n'était
  18. détecté
  19. 24/07/97 1.000 : Première version
  20. \*******************************************************************/
  21. #include <limits>
  22. #include "StenoseBase.h"
  23. #include "Ressource.h"
  24. //#include "../IMT/MeanEstimate.h"
  25. #include "CStenoseResult.h"
  26. #include "StenoseResult.h"
  27. #include "../Object/regionEllipse.h"
  28. #include "../Object/point.h"
  29. #include "../NR/ToolsMath.h"
  30. #include "../Container/extendedimage.h"
  31. CStenoseBase::CStenoseBase (void)
  32. {
  33. m_pPoints = NULL;
  34. Release ();
  35. }
  36. CStenoseBase::~CStenoseBase()
  37. {
  38. Release ();
  39. }
  40. double CStenoseBase::SurfaceEllipse ()
  41. {
  42. return m_dblEllipse;
  43. }
  44. double CStenoseBase::SurfaceStenose ()
  45. {
  46. return m_dblStenose;
  47. }
  48. double CStenoseBase::Ratio ()
  49. {
  50. return m_dblRatio;
  51. }
  52. bool CStenoseBase::Measure(ExtendedImage *h_image, Rect &rcEllipse)
  53. {
  54. m_image = h_image;
  55. assert(g_pCurrentScale);
  56. long dwEllipse,
  57. dwX,
  58. dwY,
  59. dwEnd,
  60. dwColor;
  61. RegionEllipse rgnEllipse;
  62. bool fColor;
  63. // on libère les ressources allouées pour la précédente mesure
  64. Release();
  65. // définition de la zone de mesure
  66. m_rcDraw = rcEllipse;
  67. m_rcDraw.right++;
  68. m_rcDraw.bottom++;
  69. rgnEllipse.CreateEllipticRgn(m_rcDraw);
  70. dwColor = 0; // nombre de points de couleur dans l'ellipse
  71. dwEllipse = 0; // nombre de points dans l'ellipse
  72. // nombre maximal de points qui pourraient être affichés
  73. m_pPoints = new Point [rcEllipse.Width() * rcEllipse.Height() / 2];
  74. // Balayage horizontal!
  75. for (dwY = rcEllipse.top; ((long) dwY) < rcEllipse.bottom; dwY++)
  76. {
  77. // afin d'accélérer les mesures, on ne travaille que sur les points du segment de droite
  78. // horizontale à l'interieur de l'ellipse
  79. // Point d'abscisse maximal
  80. dwEnd = rcEllipse.right;
  81. while ((!rgnEllipse.PtInRegion0(dwEnd, dwY)) && ((int) dwEnd >= rcEllipse.left)) // un des points appartient nécessairement à l'ellipse
  82. dwEnd--;
  83. // Point d'abscisse minimal
  84. dwX = rcEllipse.left + rcEllipse.right - dwEnd;
  85. // Premier point de couleur ou non?
  86. fColor = IsColor(dwX, dwY);
  87. if (fColor)
  88. {
  89. m_pPoints [m_dwPoints].x = dwX;
  90. m_pPoints [m_dwPoints].y = dwY;
  91. m_dwPoints++; // a été réinitialisé par Release
  92. }
  93. // On parcours le segment de droite...
  94. while (dwX <= dwEnd)
  95. {
  96. dwEllipse++; // Nombre de point intérieur à l'ellipse incrémenté!
  97. assert (PointInBuffer (dwX, dwY));
  98. if (IsColor(dwX, dwY))
  99. {
  100. dwColor++;
  101. if (!fColor)
  102. {
  103. // On passe d'une zone NB à une zone RGB
  104. fColor = true;
  105. m_pPoints [m_dwPoints].x = dwX;
  106. m_pPoints [m_dwPoints].y = dwY;
  107. m_dwPoints++;
  108. }
  109. }
  110. else if (fColor)
  111. {
  112. // On passe d'une zone RGB à une zone NB
  113. fColor = false;
  114. m_pPoints[m_dwPoints].x = dwX;
  115. m_pPoints[m_dwPoints].y = dwY;
  116. m_dwPoints++;
  117. }
  118. dwX++;
  119. }
  120. }
  121. // Fin du balayage horizontal!
  122. // Balayage vertical!
  123. for (dwX = rcEllipse.left; ((long) dwX) < rcEllipse.right; dwX++)
  124. {
  125. // afin d'accélérer les mesures, on ne travaille que sur les points du segment de droite
  126. // verticale à l'interieur de l'ellipse
  127. // Point d'ordonnée maximal
  128. dwEnd = rcEllipse.bottom;
  129. while ((!rgnEllipse.PtInRegion0(dwX, dwEnd)) && ((int) dwEnd >= rcEllipse.top)) // un des points appartient nécessairement à l'ellipse
  130. dwEnd--;
  131. // Point d'ordonnée minimal
  132. dwY = rcEllipse.top + rcEllipse.bottom - dwEnd;
  133. // Premier point de couleur ou non?
  134. fColor = IsColor(dwX, dwY);
  135. if (fColor)
  136. {
  137. m_pPoints[m_dwPoints].x = dwX;
  138. m_pPoints[m_dwPoints].y = dwY;
  139. m_dwPoints++; // a été réinitialisé par Release
  140. }
  141. // On parcours le segment de droite...
  142. while (dwY <= dwEnd)
  143. {
  144. assert(PointInBuffer(dwX, dwY));
  145. if (IsColor(dwX, dwY))
  146. {
  147. if (!fColor)
  148. {
  149. // On passe d'une zone NB à une zone RGB
  150. fColor = true;
  151. m_pPoints[m_dwPoints].x = dwX;
  152. m_pPoints[m_dwPoints].y = dwY;
  153. m_dwPoints++;
  154. }
  155. }
  156. else if (fColor)
  157. {
  158. // On passe d'une zone RGB à une zone NB
  159. fColor = false;
  160. m_pPoints[m_dwPoints].x = dwX;
  161. m_pPoints[m_dwPoints].y = dwY;
  162. m_dwPoints++;
  163. }
  164. dwY++;
  165. }
  166. }
  167. // Fin du balayage vertical!
  168. m_dblRatio = 100 * (1. - double (dwColor) / dwEllipse);
  169. m_dblEllipse = g_pCurrentScale->Surface (rcEllipse.Width(), rcEllipse.Height()) * M_PI / 4;
  170. m_dblStenose = m_dblEllipse * m_dblRatio / 100.0;
  171. m_rcDraw = rcEllipse;
  172. m_rcDraw.bottom--;
  173. m_rcDraw.right--;
  174. return(true); // on retourne toujours un résultat
  175. } // fin de Measure
  176. void CStenoseBase::Release()
  177. {
  178. m_rcDraw.SetRectEmpty ();
  179. if (m_pPoints)
  180. {
  181. delete [] m_pPoints;
  182. m_pPoints = NULL;
  183. }
  184. m_dwPoints = 0; // requis par la routine de mesure
  185. }
  186. bool CStenoseBase::PointInBuffer(const int& x, const int& y)
  187. {
  188. Point pt;
  189. pt.x = x;
  190. pt.y = y;
  191. return PointInBuffer(pt);
  192. }
  193. bool CStenoseBase::PointInBuffer(const Point& pt)
  194. {
  195. assert( m_image );
  196. int dx = m_image->GetWidth();
  197. int dy = m_image->GetHeight();
  198. return ( pt.x >= 0 && pt.y >= 0 && pt.x < dx && pt.y < dy );
  199. }
  200. /*
  201. unsigned long CStenoseBase::GetPixel(const int& x, const int& y)
  202. {
  203. Point pt;
  204. pt.x = x;
  205. pt.y = y;
  206. return GetPixel(pt);
  207. }
  208. unsigned long CStenoseBase::GetPixel(const Point& pt)
  209. {
  210. assert( m_image );
  211. //#if defined( WIN32 ) && !defined( IMT_DLL )
  212. // return m_image->GetPixel( pt.x, pt.y );
  213. //#else
  214. return *m_image->GetPixel( pt.x, pt.y );
  215. //#endif
  216. }
  217. */
  218. bool CStenoseBase::IsColor(int x, int y)
  219. {
  220. unsigned char bRed;
  221. unsigned char bGreen;
  222. unsigned char bBlue;
  223. int iRed;
  224. int iGreen;
  225. int iBlue;
  226. // AffectLeadResult();
  227. bRed = m_image->GetPixelRGB( x, y, 0);
  228. bGreen = m_image->GetPixelRGB( x, y, 1);
  229. bBlue = m_image->GetPixelRGB( x, y, 2);
  230. iRed = (int) bRed;
  231. iGreen = (int) bGreen;
  232. iBlue = (int) bBlue;
  233. // un niveau de gris implique bRed = bGreen = bBlue
  234. // étant donné que l'image a été numérisé on autorise un delta de 10 entre chaque couleur
  235. // ex : 190 197 185 est gris, 190 201 190 est en couleur
  236. return ( (abs (iRed - iGreen) > 30)
  237. || (abs (iRed - iBlue ) > 30)
  238. || (abs (iGreen - iBlue ) > 30)
  239. );
  240. }
  241. void CStenoseBase::PutPixEllipse(float xc,float yc,float x,float y)
  242. {
  243. WritePixel( (int) (xc + x), (int) (yc + y));
  244. WritePixel( (int) (xc - x), (int) (yc - y));
  245. WritePixel( (int) (xc + x), (int) (yc - y));
  246. WritePixel( (int) (xc - x), (int) (yc + y));
  247. }
  248. void CStenoseBase::WritePixel(int x, int y)
  249. {
  250. x = 0;
  251. y = 0;
  252. }
  253. // Algorithme MidPoint de dessin d'une Ellipse
  254. void CStenoseBase::myDrawEllipse()
  255. {
  256. float x = 0, y = 0;
  257. double p1, p2, t1, t2;
  258. int k;
  259. float rx, ry, xc, yc;
  260. rx = (float) (m_rcDraw.right - m_rcDraw.left) / 2;
  261. ry = (float) (m_rcDraw.bottom - m_rcDraw.top) / 2;
  262. xc = m_rcDraw.left + rx;
  263. yc = m_rcDraw.top + ry;
  264. y = ry;
  265. p1 = ry * ry - rx * rx * ry + 0.25 * rx * rx;
  266. PutPixEllipse(xc, yc, x, y);
  267. for (k = 0; (2 * ry * ry * x) <= (2 * rx * rx * y); k++)
  268. {
  269. t1 = 2 * ry * ry * x + 2 * ry * ry;
  270. t2 = 2 * rx * rx * y - 2 * rx * rx;
  271. if (p1 < 0)
  272. {
  273. p1 = p1 + t1 + ry * ry;
  274. }
  275. else
  276. {
  277. p1 = p1 + t1 - t2 + ry * ry;
  278. y--;
  279. }
  280. x++;
  281. PutPixEllipse(xc, yc, x, y);
  282. }
  283. p2 = ry * ry * ( x + 0.5 ) * ( x + 0.5 ) + rx * rx * (y - 1) * (y - 1) - rx * rx * ry * ry;
  284. PutPixEllipse(xc, yc, x, y);
  285. for (k = 0 ; y >= 0 ; k++)
  286. {
  287. t1 = 2 * ry * ry * x + 2 * ry * ry;
  288. t2 = 2 * rx * rx * y - 2 * rx * rx;
  289. if (p2 > 0)
  290. {
  291. p2 = p2 - t2 + rx * rx;
  292. }
  293. else
  294. {
  295. p2 = p2 + t1 - t2 + rx * rx;
  296. x++;
  297. }
  298. y--;
  299. PutPixEllipse(xc, yc, x, y);
  300. }
  301. }