OTSParticle.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  1. #include "stdafx.h"
  2. #include "OTSParticle.h"
  3. #include "Element.h"
  4. namespace OTSDATA {
  5. // COTSParticle
  6. // constructor
  7. COTSParticle::COTSParticle() // constructor
  8. {
  9. Init();
  10. //headerParticle = NULL;
  11. }
  12. COTSParticle::COTSParticle(const COTSParticle& a_oSource) // copy constructor
  13. {
  14. // can't copy itself
  15. if (&a_oSource == this)
  16. {
  17. return;
  18. }
  19. // copy data over
  20. Duplicate(a_oSource);
  21. }
  22. COTSParticle::COTSParticle(COTSParticle* a_poSource) // copy constructor
  23. {
  24. // can't copy itself
  25. if (a_poSource == this)
  26. {
  27. return;
  28. }
  29. // copy data over
  30. Duplicate(*a_poSource);
  31. }
  32. COTSParticle& COTSParticle::operator=(const COTSParticle& a_oSource) // =operator
  33. {
  34. // cleanup
  35. Cleanup();
  36. // copy the class data over
  37. Duplicate(a_oSource);
  38. // return class
  39. return *this;
  40. }
  41. BOOL COTSParticle::operator==(const COTSParticle& a_oSource) // ==operator
  42. {
  43. // return FASLE, if the two segments list are in different size
  44. return ( m_nTagId == a_oSource.m_nTagId &&
  45. m_nSearchId == a_oSource.m_nSearchId &&
  46. m_nAnalysisId == a_oSource.m_nAnalysisId &&
  47. m_nFieldId == a_oSource.m_nFieldId &&
  48. m_dArea == a_oSource.m_dArea &&
  49. m_cAveGray == a_oSource.m_cAveGray &&
  50. m_nTypeId == a_oSource.m_nTypeId &&
  51. m_poiXRayPos == a_oSource.m_poiXRayPos &&
  52. *(m_pFeature.get()) == *(a_oSource.m_pFeature.get()));
  53. }
  54. COTSParticle::~COTSParticle() // destructor
  55. {
  56. Cleanup();
  57. }
  58. void COTSParticle::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode)
  59. {
  60. xmls::xInt xTagId;
  61. xmls::xInt xnSearchId;
  62. xmls::xInt xnAnalysisId;
  63. xmls::xInt xnFieldId;
  64. xmls::xDouble xdArea;
  65. xmls::xRect xrectParticle;
  66. xmls::xInt xcAveGray;
  67. xmls::xInt xType;
  68. xmls::xPoint xpoiXRayPos;
  69. xmls::Slo slo;
  70. slo.Register("TagId", &xTagId);
  71. slo.Register("SearchId", &xnSearchId);
  72. slo.Register("AnalysisId", &xnAnalysisId);
  73. slo.Register("FieldId", &xnFieldId);
  74. slo.Register("Area", &xdArea);
  75. slo.Register("rectParticle", &xrectParticle);
  76. slo.Register("AveGray", &xcAveGray);
  77. slo.Register("Type", &xType);
  78. slo.Register("poiXRayPos", &xpoiXRayPos);
  79. slo.Register("Feature", m_pFeature.get());
  80. if (isStoring)
  81. {
  82. xTagId = m_nTagId;
  83. xnSearchId = m_nSearchId;
  84. xnAnalysisId = m_nAnalysisId;
  85. xnFieldId = m_nFieldId;
  86. xdArea = m_dArea;
  87. xrectParticle = m_rectParticle;
  88. xcAveGray = m_cAveGray;
  89. xType = m_nTypeId;
  90. xpoiXRayPos = m_poiXRayPos;
  91. slo.Serialize(true, classDoc, rootNode);
  92. }
  93. else
  94. {
  95. slo.Serialize(false, classDoc, rootNode);
  96. m_nTagId = xTagId.value();
  97. m_nSearchId = xnSearchId.value();
  98. m_nAnalysisId = xnAnalysisId.value();
  99. m_nFieldId = xnFieldId.value();
  100. m_dArea = xdArea.value();
  101. m_rectParticle = xrectParticle.value();
  102. m_cAveGray = xcAveGray.value();
  103. m_nTypeId = xType.value();
  104. m_poiXRayPos = xpoiXRayPos.value();
  105. }
  106. }
  107. double COTSParticle::GetImgPropertyValueByName(CString propertyName)
  108. {
  109. //double pvalue;
  110. if (propertyName == "Dmax") return this->GetDMax();
  111. if (propertyName == "Dmin") return this->GetDMin();
  112. if (propertyName == "Area") return this->GetActualArea();
  113. if (propertyName == "Dferet") return this->GetFeretDiameter();
  114. if (propertyName == "With") return this->GetWidth();
  115. if (propertyName == "Height") return this->GetHeight();
  116. if (propertyName == "Perimeter") return this->GetPerimeter();
  117. if (propertyName == "Dperp") return this->GetDPerp();
  118. if (propertyName == "Dinscr") return this->GetDInscr();
  119. if (propertyName == "Dmean") return this->GetDMean();
  120. if (propertyName == "Orientation") return this->GetOrientation();
  121. if (propertyName == "Delong") return this->GetDElong();
  122. if (propertyName == "AspectElong") return this->GetAspectElong();
  123. if (propertyName == "Dequalcircle") return this->GetEqualCircleDiameter();
  124. if (propertyName == "Aspect") return this->GetAspectRatio();
  125. if (propertyName == "Vedio") return this->GetVideo();
  126. if (propertyName == "X") return this->GetXRayPos().x;
  127. if (propertyName == "Y") return this->GetXRayPos().y;
  128. //return pvalue;
  129. }
  130. BOOL COTSParticle::CalCoverRect()
  131. {
  132. ASSERT(m_pFeature);
  133. if (!m_pFeature)
  134. {
  135. return FALSE;
  136. }
  137. COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList();
  138. // height is most height - lowest + 1
  139. // width is the widest - thinnest + 1
  140. int nSize = (int)a_listSegment.size();
  141. // no segment, no need to compute
  142. if (nSize <= 0)
  143. {
  144. return FALSE;
  145. }
  146. // get the most highest, lowest, widest, thinness
  147. int nHmin = a_listSegment[0]->GetHeight();
  148. int nHmax = a_listSegment[0]->GetHeight();
  149. int nWmin = a_listSegment[0]->GetStart();
  150. int nWmax = a_listSegment[0]->GetStart() + a_listSegment[0]->GetLength() - 1;
  151. // loop segment list
  152. for (auto pSegement : a_listSegment)
  153. {
  154. int nHt = pSegement->GetHeight();
  155. if (nHt < nHmin)
  156. {
  157. nHmin = nHt;
  158. }
  159. if (nHt > nHmax)
  160. {
  161. nHmax = nHt;
  162. }
  163. int nSt = pSegement->GetStart();
  164. int nEd = pSegement->GetStart() + pSegement->GetLength() - 1;
  165. if (nSt < nWmin)
  166. {
  167. nWmin = nSt;
  168. }
  169. if (nEd > nWmax)
  170. {
  171. nWmax = nEd;
  172. }
  173. }
  174. if (nHmin > nHmax || nWmin > nWmax)
  175. {
  176. return FALSE;
  177. }
  178. // get the rect
  179. m_rectParticle.top = nHmin;
  180. m_rectParticle.left = nWmin;
  181. m_rectParticle.bottom = nHmax;
  182. m_rectParticle.right = nWmax;
  183. return TRUE;
  184. }
  185. BOOL COTSParticle::CalPixelArea()
  186. {
  187. ASSERT(m_pFeature);
  188. if (!m_pFeature)
  189. {
  190. return FALSE;
  191. }
  192. COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList();
  193. // Area is all the segment's length add.
  194. int nSize = (int)a_listSegment.size();
  195. m_dPixelArea = 0;
  196. // no segment, no need to compute
  197. if (nSize <= 0)
  198. {
  199. return FALSE;
  200. }
  201. // loop segment list
  202. for (auto pSegement : a_listSegment)
  203. {
  204. m_dPixelArea += (double)pSegement->GetLength();
  205. }
  206. return TRUE;
  207. }
  208. BOOL COTSParticle::CalXRayPos()
  209. {
  210. ASSERT(m_pFeature);
  211. if (!m_pFeature)
  212. {
  213. return FALSE;
  214. }
  215. COTSSegmentsList a_listSegment = m_pFeature->GetSegmentsList();
  216. // all the pixels add
  217. int nSize = (int)a_listSegment.size();
  218. // no segment, no need to compute
  219. if (nSize <= 0)
  220. {
  221. return FALSE;
  222. }
  223. // get the 1/3 high part, the longest
  224. if(m_rectParticle.IsRectNull())
  225. {
  226. if (!CalCoverRect())
  227. return FALSE;
  228. }
  229. COTSSegmentsList listSegmentLength;
  230. listSegmentLength.clear();
  231. int nHMax = a_listSegment[0]->GetHeight();
  232. int nHMin = a_listSegment[0]->GetHeight();
  233. for (auto pSegment : a_listSegment)
  234. {
  235. int nH = pSegment->GetHeight();
  236. if (nH < nHMin)
  237. {
  238. nHMin = nH;
  239. }
  240. if (nH > nHMax)
  241. {
  242. nHMax = nH;
  243. }
  244. }
  245. int nHeight = m_rectParticle.Height();
  246. int nHStart = (int)(nHeight / 3 + nHMin + 0.5);
  247. int nHEnd = (int)(2 * nHeight / 3 + nHMax + 0.5);
  248. for (auto pSegment : a_listSegment)
  249. {
  250. int nH = pSegment->GetHeight();
  251. if (nH >= nHStart && nH <= nHEnd)
  252. {
  253. COTSSegmentPtr pSegmentNew = COTSSegmentPtr(new COTSSegment(*pSegment.get()));
  254. listSegmentLength.push_back(pSegmentNew);
  255. }
  256. }
  257. // get the longest length in the middle 1/3 part
  258. if ((int)listSegmentLength.size() < 0)
  259. {
  260. return FALSE;
  261. }
  262. int nLMax = listSegmentLength[0]->GetLength();
  263. for (auto pSegment : listSegmentLength)
  264. {
  265. int nL = pSegment->GetLength();
  266. if (nL > nLMax)
  267. {
  268. nLMax = nL;
  269. }
  270. }
  271. COTSSegmentsList listSegmentMaxLength;
  272. listSegmentMaxLength.clear();
  273. // find the segment has the longest length
  274. for (auto pSegment : listSegmentLength)
  275. {
  276. if (pSegment->GetLength() == nLMax)
  277. {
  278. COTSSegmentPtr pSegmentNew = COTSSegmentPtr(new COTSSegment(*pSegment.get()));
  279. listSegmentMaxLength.push_back(pSegmentNew);
  280. }
  281. }
  282. // get the middle longest length
  283. if ((int)listSegmentMaxLength.size() < 0)
  284. {
  285. return FALSE;
  286. }
  287. COTSSegmentPtr pSegCur = listSegmentMaxLength[0];
  288. int nSegStart = pSegCur->GetStart();
  289. int nSegHeight = pSegCur->GetHeight();
  290. int nSegLength = pSegCur->GetLength();
  291. CPoint ptSegCenter;
  292. ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5);
  293. ptSegCenter.y = nSegHeight;
  294. CPoint ptPartCenter = m_rectParticle.CenterPoint();
  295. double nHToMMin = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y));
  296. for (auto pSegment : listSegmentMaxLength)
  297. {
  298. nSegStart = pSegment->GetStart();
  299. nSegHeight = pSegment->GetHeight();
  300. nSegLength = pSegment->GetLength();
  301. ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5);
  302. ptSegCenter.y = nSegHeight;
  303. double nHToM = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y));
  304. if (nHToM < nHToMMin)
  305. {
  306. nHToMMin = nHToM;
  307. }
  308. }
  309. // get the middle longest segment
  310. for (auto pSegment : listSegmentMaxLength)
  311. {
  312. nSegStart = pSegment->GetStart();
  313. nSegHeight = pSegment->GetHeight();
  314. nSegLength = pSegment->GetLength();
  315. ptSegCenter.x = (int)(nSegStart + nSegLength / 2 + 0.5);
  316. ptSegCenter.y = nSegHeight;
  317. double nHToM = sqrt((ptSegCenter.x - ptPartCenter.x)*(ptSegCenter.x - ptPartCenter.x) + (ptSegCenter.y - ptPartCenter.y)*(ptSegCenter.y - ptPartCenter.y));
  318. if (nHToM == nHToMMin)
  319. {
  320. m_poiXRayPos = ptPartCenter;
  321. break;
  322. }
  323. }
  324. return TRUE;
  325. }
  326. void COTSParticle::SetFeature(COTSFeaturePtr a_pFeature)
  327. {
  328. ASSERT(a_pFeature);
  329. if (!a_pFeature)
  330. {
  331. return;
  332. }
  333. //m_pFeature = COTSFeaturePtr(new COTSFeature(*a_pFeature.get()));
  334. m_pFeature = a_pFeature;
  335. }
  336. BOOL COTSParticle::IsConnected(COTSParticle* a_p, int fldwidth, int fldheight, int direction)
  337. {
  338. //decide if two on boundary particles are connected.
  339. typedef enum class SORTING_DIRECTION
  340. {
  341. LEFT = 1,
  342. DOWN = 2,
  343. RIGHT = 3,
  344. UP = 4
  345. }SORTING_DIRECTION;
  346. SORTING_DIRECTION di = (SORTING_DIRECTION)direction;
  347. for (auto s : m_pFeature->GetSegmentsList())
  348. {
  349. for (auto a_seg : a_p->GetFeature()->GetSegmentsList())
  350. {
  351. if (di == SORTING_DIRECTION::LEFT || di == SORTING_DIRECTION::RIGHT)
  352. {
  353. if (s->GetHeight() == a_seg->GetHeight())
  354. {
  355. if ((s->GetStart() + s->GetLength()) == fldwidth && a_seg->GetStart() == 0)
  356. {
  357. return true;//left connected to neighbor's right.
  358. }
  359. if ((a_seg->GetStart() + a_seg->GetLength()) == fldwidth && s->GetStart() == 0)
  360. {
  361. return true;//
  362. }
  363. }
  364. }
  365. if (di == SORTING_DIRECTION::UP || di == SORTING_DIRECTION::DOWN)
  366. {
  367. if (s->GetHeight() == 0 && a_seg->GetHeight() == fldheight - 1)//the lowest height of the segment is the height of the field minus 1.
  368. {
  369. if (s->GetStart() >= a_seg->GetStart() && s->GetStart() <= a_seg->GetStart() + a_seg->GetLength())
  370. {
  371. return true;
  372. }
  373. if (a_seg->GetStart() >= s->GetStart() && a_seg->GetStart() <= s->GetStart() + s->GetLength())
  374. {
  375. return true;
  376. }
  377. }
  378. if (a_seg->GetHeight() == 0 && s->GetHeight() == fldheight - 1)
  379. {
  380. if (s->GetStart() >= a_seg->GetStart() && s->GetStart() <= a_seg->GetStart() + a_seg->GetLength())
  381. {
  382. return true;
  383. }
  384. if (a_seg->GetStart() >= s->GetStart() && a_seg->GetStart() <= s->GetStart() + s->GetLength())
  385. {
  386. return true;
  387. }
  388. }
  389. }
  390. }
  391. }
  392. return false;
  393. }
  394. // cleanup
  395. void COTSParticle::Cleanup()
  396. {
  397. }
  398. // initialization
  399. void COTSParticle::Init()
  400. {
  401. // initialization
  402. // id and tag id
  403. m_nTagId = -1;
  404. m_nSearchId = -1;
  405. m_nAnalysisId = -1;
  406. m_nFieldId = -1;
  407. // type
  408. m_nTypeId = (int)OTS_PARTICLE_TYPE::NOT_IDENTIFIED;
  409. // area
  410. m_dArea = 0;
  411. // gray
  412. m_cAveGray = 0;
  413. // feature
  414. m_pFeature = COTSFeaturePtr(new COTSFeature());
  415. m_dFeretDiameter=0;
  416. //最小外接矩形的宽度
  417. m_Width=0;
  418. //最小外接矩形的长度
  419. m_Height=0;
  420. // STD chemical type
  421. m_Perimeter=0;
  422. m_DMax=0;
  423. m_DMin=0;
  424. m_Dp=0;
  425. m_Di=0;
  426. m_Dm=0;
  427. m_De=0;
  428. m_Orientation=0;
  429. GB_CHEMICAL_TYPE m_nChemical= GB_CHEMICAL_TYPE::INVALID;
  430. m_pXRayInfo = nullptr;
  431. }
  432. // duplication
  433. void COTSParticle::Duplicate(const COTSParticle& a_oSource)
  434. {
  435. // initialization
  436. Init();
  437. // copy data over
  438. // id and tag id
  439. m_nTagId = a_oSource.m_nTagId;
  440. m_nSearchId = a_oSource.m_nSearchId;
  441. m_nAnalysisId = a_oSource.m_nAnalysisId;
  442. m_nFieldId = a_oSource.m_nFieldId;
  443. // type
  444. m_nTypeId = a_oSource.m_nTypeId;
  445. // area
  446. m_dArea = a_oSource.m_dArea;
  447. // rectangle
  448. m_rectParticle = a_oSource.m_rectParticle;
  449. // gray
  450. m_cAveGray = a_oSource.m_cAveGray;
  451. // x-ray position
  452. m_poiXRayPos = a_oSource.m_poiXRayPos;
  453. m_Width = a_oSource.m_Width;
  454. m_Height = a_oSource.m_Height;
  455. m_TypeName = a_oSource.m_TypeName;
  456. m_TypeColor = a_oSource.m_TypeColor;
  457. // feature
  458. m_pFeature = COTSFeaturePtr(new COTSFeature(*a_oSource.m_pFeature.get()));
  459. }
  460. }