GBFieldData.cpp 29 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150
  1. #pragma once
  2. #include "stdafx.h"
  3. #include "GBFieldData.h"
  4. #include "CGBLevel.h"
  5. #include <map>
  6. namespace OTSGBCalculate
  7. {
  8. using namespace std;
  9. using namespace OTSDATA;
  10. #pragma region PrivateCode
  11. COTSParticlePtr CGBFieldData::FindAdjacentParticle(COTSParticlePtr p, COTSParticleList plist)
  12. {
  13. auto adjacentPart = find_if(plist.begin(), plist.end(), [p](COTSParticlePtr pBParticle)
  14. {
  15. CRect rectParticle = p->GetParticleRect();
  16. CPoint ptParticleCenter = rectParticle.CenterPoint();
  17. int Bottom = rectParticle.BottomRight().y;
  18. int Top = rectParticle.TopLeft().y;
  19. CRect rectBCurParticle = pBParticle->GetParticleRect();
  20. CPoint ptBParticleCenter = rectBCurParticle.CenterPoint();
  21. int BottomB = rectBCurParticle.BottomRight().y;
  22. int TopB = rectBCurParticle.TopLeft().y;
  23. double dd = 0, ds = 0;
  24. ds = abs(ptParticleCenter.x - ptBParticleCenter.x);
  25. if (ds < 10)//recognize these two particle in the same level
  26. {
  27. if (Bottom > TopB)//current particle is on the above
  28. {
  29. dd = Bottom - TopB;
  30. if (dd < 40)//recognize these two particle in the same vertical string.
  31. {
  32. return true;
  33. }
  34. }
  35. else if (BottomB > Top) //current particle is on the below
  36. {
  37. dd = BottomB - Top;
  38. if (dd < 40)
  39. {
  40. return true;
  41. }
  42. }
  43. }
  44. return false;
  45. });
  46. if (adjacentPart == plist.end())
  47. {
  48. return nullptr;
  49. }
  50. else
  51. {
  52. return *adjacentPart;
  53. }
  54. }
  55. #pragma endregion
  56. CGBFieldData::CGBFieldData() // constructor
  57. {
  58. Init();
  59. }
  60. CGBFieldData::CGBFieldData(const CGBFieldData& a_oSource) // copy constructor
  61. {
  62. // can't copy itself
  63. if (&a_oSource == this)
  64. {
  65. return;
  66. }
  67. // copy data over
  68. Duplicate(a_oSource);
  69. }
  70. CGBFieldData::CGBFieldData(CGBFieldData* a_poSource) // copy constructor
  71. {
  72. // input check
  73. ASSERT(a_poSource);
  74. if (!a_poSource)
  75. {
  76. return;
  77. }
  78. // can't copy itself
  79. if (a_poSource == this)
  80. {
  81. return;
  82. }
  83. // copy data over
  84. Duplicate(*a_poSource);
  85. }
  86. CGBFieldData& CGBFieldData::operator=(const CGBFieldData& a_oSource) // =operator
  87. {
  88. // cleanup
  89. Cleanup();
  90. // copy the class data over
  91. Duplicate(a_oSource);
  92. // return class
  93. return *this;
  94. }
  95. BOOL CGBFieldData::operator==(const CGBFieldData& a_oSource) // =operator
  96. {
  97. // return test result
  98. return((m_nFrameId == a_oSource.m_nFrameId) &&
  99. (*m_pALevel.get() == *a_oSource.m_pALevel.get()) &&
  100. (*m_pBLevel.get() == *a_oSource.m_pBLevel.get()) &&
  101. (*m_pCLevel.get() == *a_oSource.m_pCLevel.get()) &&
  102. (*m_pDLevel.get() == *a_oSource.m_pDLevel.get()) &&
  103. (*m_pDSLevel.get() == *a_oSource.m_pDSLevel.get()));
  104. }
  105. CGBFieldData::~CGBFieldData() // detractor
  106. {
  107. Cleanup();
  108. }
  109. // serialization
  110. void CGBFieldData::Serialize(bool isStoring, tinyxml2::XMLDocument *classDoc, tinyxml2::XMLElement *rootNode)
  111. {
  112. xmls::xInt xFrameId;
  113. xmls::Slo slo;
  114. slo.Register("FrameId", &xFrameId);
  115. slo.Register("ALevel", m_pALevel.get());
  116. slo.Register("BLevel", m_pBLevel.get());
  117. slo.Register("CLevel", m_pCLevel.get());
  118. slo.Register("DLevel", m_pDLevel.get());
  119. slo.Register("DSLevel", m_pDSLevel.get());
  120. if (isStoring)
  121. {
  122. xFrameId = m_nFrameId;
  123. slo.Serialize(true, classDoc, rootNode);
  124. }
  125. else
  126. {
  127. slo.Serialize(false, classDoc, rootNode);
  128. m_nFrameId = xFrameId.value();
  129. }
  130. }
  131. // cleanup
  132. void CGBFieldData::Cleanup()
  133. {
  134. }
  135. // initialization
  136. void CGBFieldData::Init()
  137. {
  138. // id
  139. m_nFrameId = -1;
  140. // A level
  141. m_pALevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::A_TYPE));
  142. // B level
  143. m_pBLevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::B_TYPE));
  144. // C level
  145. m_pCLevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::C_TYPE));
  146. // D level
  147. m_pDLevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::D_TYPE));
  148. // DS level
  149. m_pDSLevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::DS_TYPE));
  150. // DSulfide level
  151. m_pDSulfidLevel = CGBLevelPtr(new CGBLevel(this, GB_LEVEL_TYPE::DSulfide_TYPE));
  152. listAThinParticles.clear();
  153. listAWideParticles.clear();
  154. listASuperParticles.clear();
  155. listBThinParticles.clear();
  156. listBWideParticles.clear();
  157. listBSuperParticles.clear();
  158. listCThinParticles.clear();
  159. listCWideParticles.clear();
  160. listCSuperParticles.clear();
  161. listDThinParticles.clear();
  162. listDWideParticles.clear();
  163. listDSuperParticles.clear();
  164. listDSParticles.clear();
  165. listDSulfideThinParticles.clear();
  166. listDSulfideWideParticles.clear();
  167. listDSulfideSuperParticles.clear();
  168. }
  169. // duplication
  170. void CGBFieldData::Duplicate(const CGBFieldData& a_oSource)
  171. {
  172. // initialization
  173. Init();
  174. // id
  175. int m_nFrameId;
  176. // A level
  177. m_pALevel = CGBLevelPtr(new CGBLevel(*a_oSource.m_pALevel.get()));
  178. // B level
  179. m_pBLevel = CGBLevelPtr(new CGBLevel(*a_oSource.m_pBLevel.get()));
  180. // C level
  181. m_pCLevel = CGBLevelPtr(new CGBLevel(*a_oSource.m_pCLevel.get()));
  182. // D level
  183. m_pDLevel = CGBLevelPtr(new CGBLevel(*a_oSource.m_pDLevel.get()));
  184. // DS level
  185. m_pDSLevel = CGBLevelPtr(new CGBLevel(*a_oSource.m_pDSLevel.get()));
  186. m_nFrameId = a_oSource.m_nFrameId;
  187. }
  188. // caculate Level by method 1
  189. void CGBFieldData::CaculateLevelByMethod1()
  190. {
  191. // according to the shape
  192. if (m_listParticles.empty())
  193. {
  194. return;
  195. }
  196. vector<GBParticle> listBAndDParticles;//
  197. listBAndDParticles.clear();
  198. // get all the all particles for each level
  199. mapAllParticles.clear();
  200. for (auto pParticle : m_listParticles)
  201. { // compute length width ratio
  202. CRect rectParticle = pParticle->GetParticleRect();
  203. //check the denominator is zero or not
  204. if (rectParticle.Width() == 0)
  205. {
  206. continue;
  207. }
  208. //获取最大长度和最小宽度
  209. double h = pParticle->GetDMax();
  210. double w = pParticle->GetDMin();
  211. double dLengthWidthRatio = h / w;
  212. if (dLengthWidthRatio < 1)
  213. {
  214. dLengthWidthRatio = 1 / dLengthWidthRatio;
  215. }
  216. if (dLengthWidthRatio >= 3)//长宽比大于3的颗粒,根据化学元素不同,分为A类和C类
  217. {
  218. //A or C class
  219. GB_CHEMICAL_TYPE nChemicalType = pParticle->GetChemical();
  220. if (nChemicalType == GB_CHEMICAL_TYPE::CHE_S)
  221. {
  222. // A
  223. //计算颗粒宽度是属于细系粗系还是超尺寸
  224. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::A_TYPE);
  225. switch (wt)
  226. {
  227. case GB_WIDTH_TYPE::THIN:
  228. listAThinParticles.push_back(pParticle);
  229. break;
  230. case GB_WIDTH_TYPE::WIDE:
  231. listAWideParticles.push_back(pParticle);
  232. break;
  233. case GB_WIDTH_TYPE::SUPER:
  234. listASuperParticles.push_back(pParticle);
  235. break;
  236. }
  237. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::A_TYPE, wt);
  238. }
  239. else if (nChemicalType == GB_CHEMICAL_TYPE::CHE_O)
  240. {
  241. // C
  242. //计算颗粒宽度是属于细系粗系还是超尺寸
  243. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::C_TYPE);
  244. switch (wt)
  245. {
  246. case GB_WIDTH_TYPE::THIN:
  247. listCThinParticles.push_back(pParticle);
  248. break;
  249. case GB_WIDTH_TYPE::WIDE:
  250. listCWideParticles.push_back(pParticle);
  251. break;
  252. case GB_WIDTH_TYPE::SUPER:
  253. listCSuperParticles.push_back(pParticle);
  254. break;
  255. }
  256. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::C_TYPE, wt);
  257. }
  258. }
  259. else//长宽比小于3的颗粒,有3种情况,一种是串条状的B类颗粒,一种是单独的D类颗粒,如果费雷特直径大于13则为DS类颗粒
  260. {
  261. // B, or D or DS
  262. // compute Feret's diameter
  263. double dFeretDiameter = pParticle->GetFeretDiameter();
  264. if (dFeretDiameter >= 13)
  265. {
  266. // DS
  267. listDSParticles.push_back(pParticle);
  268. }
  269. else
  270. {
  271. // B or D
  272. GBParticle gbP = GBParticle(pParticle, GB_LEVEL_TYPE::INVALID, GB_WIDTH_TYPE::INVALID);
  273. //不能确定是B或D,先设为INVALID
  274. listBAndDParticles.push_back(gbP);
  275. }
  276. }
  277. }
  278. {
  279. for (auto pGBParticle : listBAndDParticles)
  280. {
  281. // check if the particle is alone
  282. auto adjacentPart = find_if(listBAndDParticles.begin(), listBAndDParticles.end(), [pGBParticle](GBParticle pBParticle)
  283. {
  284. CRect rectParticle = pGBParticle.myPart->GetParticleRect();
  285. CPoint ptParticleCenter = rectParticle.CenterPoint();
  286. int Bottom = rectParticle.BottomRight().y;
  287. int Top = rectParticle.TopLeft().y;
  288. CRect rectBCurParticle = pBParticle.myPart->GetParticleRect();
  289. CPoint ptBParticleCenter = rectBCurParticle.CenterPoint();
  290. int BottomB = rectBCurParticle.BottomRight().y;
  291. int TopB = rectBCurParticle.TopLeft().y;
  292. double dd = 0, ds = 0;
  293. ds = abs(ptParticleCenter.x - ptBParticleCenter.x);
  294. if (ds < 10)//认为两个颗粒在一条竖直线上,但不在一起
  295. {
  296. if (Bottom > TopB)//current particle is on the above
  297. {
  298. dd = Bottom - TopB;
  299. if (dd < 40)//认为这两个颗粒在一个串条上
  300. {
  301. return true;
  302. }
  303. }
  304. else if (BottomB > Top) //current particle is on the below
  305. {
  306. dd = BottomB - Top;
  307. if (dd < 40)
  308. {
  309. return true;
  310. }
  311. }
  312. }
  313. return false;
  314. });
  315. if (adjacentPart == listBAndDParticles.end())//没找到
  316. {
  317. pGBParticle.myType = GB_LEVEL_TYPE::D_TYPE;
  318. //计算颗粒宽度是属于细系粗系还是超尺寸
  319. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE);
  320. switch (wt)
  321. {
  322. case GB_WIDTH_TYPE::THIN:
  323. listDThinParticles.push_back(pGBParticle.myPart);
  324. break;
  325. case GB_WIDTH_TYPE::WIDE:
  326. listDWideParticles.push_back(pGBParticle.myPart);
  327. break;
  328. case GB_WIDTH_TYPE::SUPER:
  329. listDSuperParticles.push_back(pGBParticle.myPart);
  330. break;
  331. }
  332. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE, wt);
  333. }
  334. else//找到了相邻接的颗粒,不是孤立的则为B类
  335. {
  336. pGBParticle.myType = GB_LEVEL_TYPE::B_TYPE;//把类型设为有效类型,以便不再找这个颗粒
  337. adjacentPart->myType = GB_LEVEL_TYPE::B_TYPE;
  338. //计算颗粒宽度是属于细系粗系还是超尺寸
  339. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE);
  340. switch (wt)
  341. {
  342. case GB_WIDTH_TYPE::THIN:
  343. listBThinParticles.insert(pGBParticle.myPart);
  344. break;
  345. case GB_WIDTH_TYPE::WIDE:
  346. listBWideParticles.insert(pGBParticle.myPart);
  347. break;
  348. case GB_WIDTH_TYPE::SUPER:
  349. listBSuperParticles.insert(pGBParticle.myPart);
  350. break;
  351. }
  352. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  353. wt = this->CaculateLevelWidth(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE);
  354. switch (wt)
  355. {
  356. case GB_WIDTH_TYPE::THIN:
  357. listBThinParticles.insert(adjacentPart->myPart);
  358. break;
  359. case GB_WIDTH_TYPE::WIDE:
  360. listBWideParticles.insert(adjacentPart->myPart);
  361. break;
  362. case GB_WIDTH_TYPE::SUPER:
  363. listBSuperParticles.insert(adjacentPart->myPart);
  364. break;
  365. }
  366. mapAllParticles[adjacentPart->myPart] = GBParticle(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  367. }
  368. }
  369. }
  370. }
  371. // caculate Level by method 2
  372. void CGBFieldData::CaculateLevelByMethod2()
  373. {
  374. vector<COTSParticlePtr> listABCParticles;//
  375. listABCParticles.clear();
  376. if (m_listParticles.empty())
  377. {
  378. return;
  379. }
  380. // get all the all particles for each level
  381. for (auto pParticle : m_listParticles)
  382. {
  383. CRect rectParticle = pParticle->GetParticleRect();
  384. //check the denominator is zero or not
  385. if (rectParticle.Width() == 0)
  386. {
  387. continue;
  388. }
  389. //获取最小外接矩形的宽和高
  390. double h = pParticle->GetDMax();
  391. double w = pParticle->GetDMin();
  392. double dLengthWidthRatio = h / w;
  393. if (dLengthWidthRatio < 1)
  394. {
  395. dLengthWidthRatio = 1 / dLengthWidthRatio;
  396. }
  397. if (dLengthWidthRatio < 3)//长宽比小于3的颗粒,且为孤立的颗粒,根据是否含硫化物,分为D类和DSulfide类,如果费雷特直径大于13 归为DS类
  398. {
  399. double dFeretDiameter = pParticle->GetFeretDiameter();
  400. if (dFeretDiameter >= 13)
  401. {
  402. // DS
  403. listDSParticles.push_back(pParticle);
  404. }
  405. else
  406. {
  407. // D or Dsulfide
  408. auto p = FindAdjacentParticle(pParticle, m_listParticles);
  409. if (p == nullptr)//pParticle是一个孤立的颗粒
  410. {
  411. GB_CHEMICAL_TYPE ChemicalType = pParticle->GetChemical();
  412. if (ChemicalType == GB_CHEMICAL_TYPE::CHE_S)
  413. {
  414. auto wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::DSulfide_TYPE);
  415. switch (wt)
  416. {
  417. case GB_WIDTH_TYPE::THIN:
  418. listDSulfideThinParticles.push_back(pParticle);
  419. break;
  420. case GB_WIDTH_TYPE::WIDE:
  421. listDSulfideWideParticles.push_back(pParticle);
  422. break;
  423. case GB_WIDTH_TYPE::SUPER:
  424. listDSulfideSuperParticles.push_back(pParticle);
  425. break;
  426. }
  427. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::DSulfide_TYPE, wt);
  428. }
  429. else
  430. {
  431. auto wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::D_TYPE);
  432. switch (wt)
  433. {
  434. case GB_WIDTH_TYPE::THIN:
  435. listDThinParticles.push_back(pParticle);
  436. break;
  437. case GB_WIDTH_TYPE::WIDE:
  438. listDWideParticles.push_back(pParticle);
  439. break;
  440. case GB_WIDTH_TYPE::SUPER:
  441. listDSuperParticles.push_back(pParticle);
  442. break;
  443. }
  444. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::D_TYPE, wt);
  445. }
  446. }
  447. else
  448. {
  449. listABCParticles.push_back(pParticle);
  450. }
  451. }
  452. }
  453. else
  454. {
  455. listABCParticles.push_back(pParticle);
  456. }
  457. }
  458. for (auto pParticle : listABCParticles)
  459. {
  460. GB_CHEMICAL_TYPE nChemicalType = pParticle->GetChemical();
  461. if (nChemicalType == GB_CHEMICAL_TYPE::CHE_S)
  462. {
  463. // A
  464. //COTSParticlePtr pParticleNew = COTSParticlePtr(pParticle);
  465. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::A_TYPE);
  466. switch (wt)
  467. {
  468. case GB_WIDTH_TYPE::THIN:
  469. listAThinParticles.push_back(pParticle);
  470. break;
  471. case GB_WIDTH_TYPE::WIDE:
  472. listAWideParticles.push_back(pParticle);
  473. break;
  474. case GB_WIDTH_TYPE::SUPER:
  475. listASuperParticles.push_back(pParticle);
  476. break;
  477. }
  478. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::A_TYPE, wt);
  479. }
  480. else if (nChemicalType == GB_CHEMICAL_TYPE::CHE_Al)
  481. {
  482. // B
  483. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::B_TYPE);
  484. switch (wt)
  485. {
  486. case GB_WIDTH_TYPE::THIN:
  487. listBThinParticles.insert(pParticle);
  488. break;
  489. case GB_WIDTH_TYPE::WIDE:
  490. listBWideParticles.insert(pParticle);
  491. break;
  492. case GB_WIDTH_TYPE::SUPER:
  493. listBSuperParticles.insert(pParticle);
  494. break;
  495. }
  496. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::B_TYPE, wt);
  497. }
  498. else if (nChemicalType == GB_CHEMICAL_TYPE::CHE_Si)
  499. {
  500. // C
  501. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::C_TYPE);
  502. switch (wt)
  503. {
  504. case GB_WIDTH_TYPE::THIN:
  505. listCThinParticles.push_back(pParticle);
  506. break;
  507. case GB_WIDTH_TYPE::WIDE:
  508. listCWideParticles.push_back(pParticle);
  509. break;
  510. case GB_WIDTH_TYPE::SUPER:
  511. listCSuperParticles.push_back(pParticle);
  512. break;
  513. }
  514. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::C_TYPE, wt);
  515. }
  516. }
  517. }
  518. // caculate Level by ASTM
  519. void CGBFieldData::CaculateLevelASTM()
  520. {
  521. // according to the shape
  522. if (m_listParticles.empty())
  523. {
  524. return;
  525. }
  526. vector<GBParticle> listBAndDParticles;//
  527. listBAndDParticles.clear();
  528. // get all the all particles for each level
  529. mapAllParticles.clear();
  530. for (auto pParticle : m_listParticles)
  531. { // compute length width ratio
  532. CRect rectParticle = pParticle->GetParticleRect();
  533. //check the denominator is zero or not
  534. if (rectParticle.Width() == 0)
  535. {
  536. continue;
  537. }
  538. //获取最大长度和最小宽度
  539. double h = pParticle->GetDMax();
  540. double w = pParticle->GetDMin();
  541. double dLengthWidthRatio = h / w;
  542. if (dLengthWidthRatio < 1)
  543. {
  544. dLengthWidthRatio = 1 / dLengthWidthRatio;
  545. }
  546. if (dLengthWidthRatio >= 3)//长宽比大于3的颗粒,根据化学元素不同,分为A类和C类
  547. {
  548. //A or C class
  549. GB_CHEMICAL_TYPE nChemicalType = pParticle->GetChemical();
  550. if (nChemicalType == GB_CHEMICAL_TYPE::CHE_S)
  551. {
  552. // A
  553. //计算颗粒宽度是属于细系粗系还是超尺寸
  554. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::A_TYPE);
  555. switch (wt)
  556. {
  557. case GB_WIDTH_TYPE::THIN:
  558. listAThinParticles.push_back(pParticle);
  559. break;
  560. case GB_WIDTH_TYPE::WIDE:
  561. listAWideParticles.push_back(pParticle);
  562. break;
  563. case GB_WIDTH_TYPE::SUPER:
  564. listASuperParticles.push_back(pParticle);
  565. break;
  566. }
  567. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::A_TYPE, wt);
  568. }
  569. else if (nChemicalType == GB_CHEMICAL_TYPE::CHE_O)
  570. {
  571. // C
  572. //计算颗粒宽度是属于细系粗系还是超尺寸
  573. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::C_TYPE);
  574. switch (wt)
  575. {
  576. case GB_WIDTH_TYPE::THIN:
  577. listCThinParticles.push_back(pParticle);
  578. break;
  579. case GB_WIDTH_TYPE::WIDE:
  580. listCWideParticles.push_back(pParticle);
  581. break;
  582. case GB_WIDTH_TYPE::SUPER:
  583. listCSuperParticles.push_back(pParticle);
  584. break;
  585. }
  586. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::C_TYPE, wt);
  587. }
  588. }
  589. else//长宽比小于3的颗粒,有3种情况,一种是串条状的B类颗粒,一种是单独的D类颗粒,如果费雷特直径大于13则为DS类颗粒
  590. {
  591. // B, or D or DS
  592. // compute Feret's diameter
  593. double dFeretDiameter = pParticle->GetFeretDiameter();
  594. if (dFeretDiameter >= 13)
  595. {
  596. // DS
  597. listDSParticles.push_back(pParticle);
  598. }
  599. else
  600. {
  601. // B or D
  602. GBParticle gbP = GBParticle(pParticle, GB_LEVEL_TYPE::INVALID, GB_WIDTH_TYPE::INVALID);
  603. //不能确定是B或D,先设为INVALID
  604. listBAndDParticles.push_back(gbP);
  605. }
  606. }
  607. }
  608. {
  609. for (auto pGBParticle : listBAndDParticles)
  610. {
  611. // check if the particle is alone
  612. auto adjacentPart = find_if(listBAndDParticles.begin(), listBAndDParticles.end(), [pGBParticle](GBParticle pBParticle)
  613. {
  614. CRect rectParticle = pGBParticle.myPart->GetParticleRect();
  615. CPoint ptParticleCenter = rectParticle.CenterPoint();
  616. int Bottom = rectParticle.BottomRight().y;
  617. int Top = rectParticle.TopLeft().y;
  618. CRect rectBCurParticle = pBParticle.myPart->GetParticleRect();
  619. CPoint ptBParticleCenter = rectBCurParticle.CenterPoint();
  620. int BottomB = rectBCurParticle.BottomRight().y;
  621. int TopB = rectBCurParticle.TopLeft().y;
  622. double dd = 0, ds = 0;
  623. ds = abs(ptParticleCenter.x - ptBParticleCenter.x);
  624. if (ds <= 15)//认为两个颗粒在一条竖直线上,但不在一起
  625. {
  626. if (Bottom > TopB)//current particle is on the above
  627. {
  628. dd = Bottom - TopB;
  629. if (dd < 40)//认为这两个颗粒在一个串条上
  630. {
  631. return true;
  632. }
  633. }
  634. else if (BottomB > Top) //current particle is on the below
  635. {
  636. dd = BottomB - Top;
  637. if (dd < 40)
  638. {
  639. return true;
  640. }
  641. }
  642. }
  643. return false;
  644. });
  645. if (adjacentPart == listBAndDParticles.end())//没找到
  646. {
  647. pGBParticle.myType = GB_LEVEL_TYPE::D_TYPE;
  648. //计算颗粒宽度是属于细系粗系还是超尺寸
  649. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE);
  650. switch (wt)
  651. {
  652. case GB_WIDTH_TYPE::THIN:
  653. listDThinParticles.push_back(pGBParticle.myPart);
  654. break;
  655. case GB_WIDTH_TYPE::WIDE:
  656. listDWideParticles.push_back(pGBParticle.myPart);
  657. break;
  658. case GB_WIDTH_TYPE::SUPER:
  659. listDSuperParticles.push_back(pGBParticle.myPart);
  660. break;
  661. }
  662. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE, wt);
  663. }
  664. else//找到了相邻接的颗粒,不是孤立的则为B类
  665. {
  666. pGBParticle.myType = GB_LEVEL_TYPE::B_TYPE;//把类型设为有效类型,以便不再找这个颗粒
  667. adjacentPart->myType = GB_LEVEL_TYPE::B_TYPE;
  668. //计算颗粒宽度是属于细系粗系还是超尺寸
  669. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE);
  670. switch (wt)
  671. {
  672. case GB_WIDTH_TYPE::THIN:
  673. listBThinParticles.insert(pGBParticle.myPart);
  674. break;
  675. case GB_WIDTH_TYPE::WIDE:
  676. listBWideParticles.insert(pGBParticle.myPart);
  677. break;
  678. case GB_WIDTH_TYPE::SUPER:
  679. listBSuperParticles.insert(pGBParticle.myPart);
  680. break;
  681. }
  682. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  683. wt = this->CaculateLevelWidth(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE);
  684. switch (wt)
  685. {
  686. case GB_WIDTH_TYPE::THIN:
  687. listBThinParticles.insert(adjacentPart->myPart);
  688. break;
  689. case GB_WIDTH_TYPE::WIDE:
  690. listBWideParticles.insert(adjacentPart->myPart);
  691. break;
  692. case GB_WIDTH_TYPE::SUPER:
  693. listBSuperParticles.insert(adjacentPart->myPart);
  694. break;
  695. }
  696. mapAllParticles[adjacentPart->myPart] = GBParticle(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  697. }
  698. }
  699. }
  700. }
  701. // caculate Level by DIN
  702. void CGBFieldData::CaculateLevelDIN(COTSParticleList listParticle)
  703. {
  704. // according to the shape
  705. if (listParticle.empty())
  706. {
  707. return;
  708. }
  709. vector<GBParticle> listBAndDParticles;//
  710. listBAndDParticles.clear();
  711. // get all the all particles for each level
  712. mapAllParticles.clear();
  713. for (auto pParticle : listParticle)
  714. { // compute length width ratio
  715. CRect rectParticle = pParticle->GetParticleRect();
  716. //check the denominator is zero or not
  717. if (rectParticle.Width() == 0)
  718. {
  719. continue;
  720. }
  721. //获取最大长度和最小宽度
  722. double h = pParticle->GetDMax();
  723. double w = pParticle->GetDMin();
  724. double dLengthWidthRatio = h / w;
  725. if (dLengthWidthRatio < 1)
  726. {
  727. dLengthWidthRatio = 1 / dLengthWidthRatio;
  728. }
  729. if (dLengthWidthRatio >= 3)//长宽比大于3的颗粒,根据化学元素不同,分为A类和C类
  730. {
  731. //A or C class
  732. GB_CHEMICAL_TYPE nChemicalType = pParticle->GetChemical();
  733. if (nChemicalType == GB_CHEMICAL_TYPE::CHE_S)
  734. {
  735. // A
  736. //计算颗粒宽度是属于细系粗系还是超尺寸
  737. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::A_TYPE);
  738. if (wt == GB_WIDTH_TYPE::THIN || wt == GB_WIDTH_TYPE::WIDE || wt == GB_WIDTH_TYPE::SUPER)
  739. {
  740. listAThinParticles.push_back(pParticle);
  741. }
  742. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::A_TYPE, wt);
  743. }
  744. else if (nChemicalType == GB_CHEMICAL_TYPE::CHE_O)
  745. {
  746. // C
  747. //计算颗粒宽度是属于细系粗系还是超尺寸
  748. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pParticle, GB_LEVEL_TYPE::C_TYPE);
  749. if (wt == GB_WIDTH_TYPE::THIN || wt == GB_WIDTH_TYPE::WIDE || wt == GB_WIDTH_TYPE::SUPER)
  750. {
  751. listAThinParticles.push_back(pParticle);
  752. }
  753. mapAllParticles[pParticle] = GBParticle(pParticle, GB_LEVEL_TYPE::C_TYPE, wt);
  754. }
  755. }
  756. else//长宽比小于3的颗粒,有3种情况,一种是串条状的B类颗粒,一种是单独的D类颗粒,如果费雷特直径大于13则为DS类颗粒
  757. {
  758. // B, or D or DS
  759. // compute Feret's diameter
  760. double dFeretDiameter = pParticle->GetFeretDiameter();
  761. if (dFeretDiameter >= 13)
  762. {
  763. // DS
  764. listDSParticles.push_back(pParticle);
  765. }
  766. else
  767. {
  768. // B or D
  769. GBParticle gbP = GBParticle(pParticle, GB_LEVEL_TYPE::INVALID, GB_WIDTH_TYPE::INVALID);
  770. //不能确定是B或D,先设为INVALID
  771. listBAndDParticles.push_back(gbP);
  772. }
  773. }
  774. }
  775. {
  776. for (auto pGBParticle : listBAndDParticles)
  777. {
  778. // check if the particle is alone
  779. auto adjacentPart = find_if(listBAndDParticles.begin(), listBAndDParticles.end(), [pGBParticle](GBParticle pBParticle)
  780. {
  781. CRect rectParticle = pGBParticle.myPart->GetParticleRect();
  782. CPoint ptParticleCenter = rectParticle.CenterPoint();
  783. int Bottom = rectParticle.BottomRight().y;
  784. int Top = rectParticle.TopLeft().y;
  785. CRect rectBCurParticle = pBParticle.myPart->GetParticleRect();
  786. CPoint ptBParticleCenter = rectBCurParticle.CenterPoint();
  787. int BottomB = rectBCurParticle.BottomRight().y;
  788. int TopB = rectBCurParticle.TopLeft().y;
  789. double dd = 0, ds = 0;
  790. ds = abs(ptParticleCenter.x - ptBParticleCenter.x);
  791. if (ds <= 15)//认为两个颗粒在一条竖直线上,但不在一起
  792. {
  793. if (Bottom > TopB)//current particle is on the above
  794. {
  795. dd = Bottom - TopB;
  796. if (dd < 40)//认为这两个颗粒在一个串条上
  797. {
  798. return true;
  799. }
  800. }
  801. else if (BottomB > Top) //current particle is on the below
  802. {
  803. dd = BottomB - Top;
  804. if (dd < 40)
  805. {
  806. return true;
  807. }
  808. }
  809. }
  810. return false;
  811. });
  812. if (adjacentPart == listBAndDParticles.end())//没找到
  813. {
  814. pGBParticle.myType = GB_LEVEL_TYPE::D_TYPE;
  815. //计算颗粒宽度是属于细系粗系还是超尺寸
  816. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE);
  817. if (wt == GB_WIDTH_TYPE::THIN || wt == GB_WIDTH_TYPE::WIDE || wt == GB_WIDTH_TYPE::SUPER)
  818. {
  819. listDThinParticles.push_back(pGBParticle.myPart);
  820. }
  821. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::D_TYPE, wt);
  822. }
  823. else//找到了相邻接的颗粒,不是孤立的则为B类
  824. {
  825. pGBParticle.myType = GB_LEVEL_TYPE::B_TYPE;//把类型设为有效类型,以便不再找这个颗粒
  826. adjacentPart->myType = GB_LEVEL_TYPE::B_TYPE;
  827. //计算颗粒宽度是属于细系粗系还是超尺寸
  828. GB_WIDTH_TYPE wt = this->CaculateLevelWidth(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE);
  829. if (wt == GB_WIDTH_TYPE::THIN || wt == GB_WIDTH_TYPE::WIDE || wt == GB_WIDTH_TYPE::SUPER)
  830. {
  831. listBThinParticles.insert(pGBParticle.myPart);
  832. }
  833. mapAllParticles[pGBParticle.myPart] = GBParticle(pGBParticle.myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  834. wt = this->CaculateLevelWidth(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE);
  835. if (wt == GB_WIDTH_TYPE::THIN || wt == GB_WIDTH_TYPE::WIDE || wt == GB_WIDTH_TYPE::SUPER)
  836. {
  837. listBThinParticles.insert(adjacentPart->myPart);
  838. }
  839. mapAllParticles[adjacentPart->myPart] = GBParticle(adjacentPart->myPart, GB_LEVEL_TYPE::B_TYPE, wt);
  840. }
  841. }
  842. }
  843. }
  844. // caculate Level Width
  845. BOOL CGBFieldData::CaculateLevelThinWidth(COTSParticleList& a_listParticles, GB_LEVEL_TYPE a_nLevel)
  846. {
  847. if (a_listParticles.empty())
  848. {
  849. return FALSE;
  850. }
  851. double dMin = 2, dMax = 0;
  852. switch ((int)a_nLevel)
  853. {
  854. case (int)GB_LEVEL_TYPE::A_TYPE:
  855. dMax = 4;
  856. break;
  857. case (int)GB_LEVEL_TYPE::B_TYPE:
  858. dMax = 9;
  859. break;
  860. case (int)GB_LEVEL_TYPE::C_TYPE:
  861. dMax = 5;
  862. break;
  863. case (int)GB_LEVEL_TYPE::D_TYPE:
  864. dMax = 8;
  865. break;
  866. }
  867. BOOL bThin = TRUE;
  868. for (auto pParticle : a_listParticles)
  869. {
  870. CRect rectParticle = pParticle->GetParticleRect();
  871. double dWidth = (double)rectParticle.Width();
  872. if (dWidth < dMin || dWidth > dMax)
  873. {
  874. bThin = FALSE;
  875. break;
  876. }
  877. }
  878. return bThin;
  879. }
  880. GB_WIDTH_TYPE CGBFieldData::CaculateLevelWidth(COTSParticlePtr Particle, GB_LEVEL_TYPE a_nLevel)
  881. {
  882. double dWidth = (double)Particle->GetDMin();
  883. double dMin = 2, dMax = 0;
  884. switch ((int)a_nLevel)
  885. {
  886. case (int)GB_LEVEL_TYPE::A_TYPE:
  887. dMax = 4;
  888. break;
  889. case (int)GB_LEVEL_TYPE::B_TYPE:
  890. dMax = 9;
  891. break;
  892. case (int)GB_LEVEL_TYPE::C_TYPE:
  893. dMax = 5;
  894. break;
  895. case (int)GB_LEVEL_TYPE::D_TYPE:
  896. dMax = 8;
  897. break;
  898. }
  899. if (dWidth < dMin)
  900. {
  901. return GB_WIDTH_TYPE::INVALID;//小于2um不考虑
  902. }
  903. else if (dWidth >= dMin && dWidth < dMax)
  904. {
  905. return GB_WIDTH_TYPE::THIN;
  906. }
  907. switch ((int)a_nLevel)
  908. {
  909. case (int)GB_LEVEL_TYPE::A_TYPE:
  910. dMin = 4;
  911. dMax = 12;
  912. break;
  913. case (int)GB_LEVEL_TYPE::B_TYPE:
  914. dMin = 9;
  915. dMax = 15;
  916. break;
  917. case (int)GB_LEVEL_TYPE::C_TYPE:
  918. dMin = 5;
  919. dMax = 12;
  920. break;
  921. case (int)GB_LEVEL_TYPE::D_TYPE:
  922. dMin = 8;
  923. dMax = 13;
  924. break;
  925. }
  926. if (dWidth >= dMin && dWidth < dMax)
  927. {
  928. return GB_WIDTH_TYPE::WIDE;
  929. }
  930. switch ((int)a_nLevel)
  931. {
  932. case (int)GB_LEVEL_TYPE::A_TYPE:
  933. dMin = 12;
  934. break;
  935. case (int)GB_LEVEL_TYPE::B_TYPE:
  936. dMin = 15;
  937. break;
  938. case (int)GB_LEVEL_TYPE::C_TYPE:
  939. dMin = 12;
  940. break;
  941. case (int)GB_LEVEL_TYPE::D_TYPE:
  942. dMin = 13;
  943. break;
  944. }
  945. if (dWidth >= dMin)
  946. {
  947. return GB_WIDTH_TYPE::SUPER;
  948. }
  949. return GB_WIDTH_TYPE::INVALID;
  950. }
  951. BOOL CGBFieldData::CaculateLevelFatWidth(COTSParticleList& a_listParticles, GB_LEVEL_TYPE a_nLevel)
  952. {
  953. if (a_listParticles.empty())
  954. {
  955. return FALSE;
  956. }
  957. double dMin = 0, dMax = 0;
  958. switch ((int)a_nLevel)
  959. {
  960. case (int)GB_LEVEL_TYPE::A_TYPE:
  961. dMin = 4;
  962. dMax = 12;
  963. break;
  964. case (int)GB_LEVEL_TYPE::B_TYPE:
  965. dMin = 9;
  966. dMax = 15;
  967. break;
  968. case (int)GB_LEVEL_TYPE::C_TYPE:
  969. dMin = 5;
  970. dMax = 12;
  971. break;
  972. case (int)GB_LEVEL_TYPE::D_TYPE:
  973. dMin = 8;
  974. dMax = 13;
  975. break;
  976. }
  977. BOOL bFat = TRUE;
  978. for (auto pParticle : a_listParticles)
  979. {
  980. CRect rectParticle = pParticle->GetParticleRect();
  981. double dWidth = (double)rectParticle.Width();
  982. if (dWidth < dMin || dWidth > dMax)
  983. {
  984. bFat = FALSE;
  985. break;
  986. }
  987. }
  988. return bFat;
  989. }
  990. BOOL CGBFieldData::CaculateSuper(COTSParticleList& a_listParticles, GB_LEVEL_TYPE a_nLevel)
  991. {
  992. if (a_listParticles.empty())
  993. {
  994. return FALSE;
  995. }
  996. double dMin = 0;
  997. switch ((int)a_nLevel)
  998. {
  999. case (int)GB_LEVEL_TYPE::A_TYPE:
  1000. dMin = 12;
  1001. break;
  1002. case (int)GB_LEVEL_TYPE::B_TYPE:
  1003. dMin = 15;
  1004. break;
  1005. case (int)GB_LEVEL_TYPE::C_TYPE:
  1006. dMin = 12;
  1007. break;
  1008. case (int)GB_LEVEL_TYPE::D_TYPE:
  1009. dMin = 13;
  1010. break;
  1011. }
  1012. BOOL bSuper = TRUE;
  1013. for (auto pParticle : a_listParticles)
  1014. {
  1015. CRect rectParticle = pParticle->GetParticleRect();
  1016. double dWidth = (double)rectParticle.Width();
  1017. if (dWidth < dMin)
  1018. {
  1019. bSuper = FALSE;
  1020. break;
  1021. }
  1022. }
  1023. return bSuper;
  1024. }
  1025. }