Element.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715
  1. // describe elements
  2. #include "stdafx.h"
  3. #include "Element.h"
  4. namespace OTSDATA
  5. {
  6. #pragma warning(disable: 4835)
  7. const CString CElement::theElementNameList{ _T("H,He")
  8. _T(",Li,Be,B,C,N,O,F,Ne")
  9. _T(",Na,Mg,Al,Si,P,S,Cl,Ar")
  10. _T(",K,Ca,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr")
  11. _T(",Rb,Sr,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I,Xe")
  12. _T(",Cs,Ba,La")
  13. _T(",Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu")
  14. _T(",Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn")
  15. _T(",Fr,Ra,Ac")
  16. _T(",Th,Pa,U,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Lr") };
  17. std::vector<CString> CElement::m_theElementNameVector;
  18. #pragma warning(default: 4835)
  19. // CElementChemistry
  20. // constructor
  21. CElementChemistry::CElementChemistry()
  22. {
  23. // initialization
  24. Init();
  25. }
  26. CElementChemistry::CElementChemistry(CString a_strName, const double a_dPercentage)
  27. : m_strName(a_strName)
  28. , m_dPercentage(a_dPercentage)
  29. {
  30. }
  31. // copy constructor
  32. CElementChemistry::CElementChemistry(const CElementChemistry& a_oSource)
  33. {
  34. // can't copy itself
  35. if (&a_oSource == this)
  36. {
  37. return;
  38. }
  39. // copy data over
  40. Duplicate(a_oSource);
  41. }
  42. // copy constructor
  43. CElementChemistry::CElementChemistry(CElementChemistry* a_poSource)
  44. {
  45. // input check
  46. ASSERT(a_poSource);
  47. if (!a_poSource)
  48. {
  49. return;
  50. }
  51. // can't copy itself
  52. if (a_poSource == this)
  53. {
  54. return;
  55. }
  56. // copy data over
  57. Duplicate(*a_poSource);
  58. }
  59. // =operator
  60. CElementChemistry& CElementChemistry::operator=(const CElementChemistry& a_oSource)
  61. {
  62. // cleanup
  63. Cleanup();
  64. // copy the class data over
  65. Duplicate(a_oSource);
  66. // return class
  67. return *this;
  68. }
  69. // ==operator
  70. BOOL CElementChemistry::operator==(const CElementChemistry& a_oSource)
  71. {
  72. // return test result
  73. return m_strName.Compare(a_oSource.m_strName) == 0 &&
  74. abs(m_dPercentage - a_oSource.m_dPercentage) < MIN_DOUBLE_VALUE;
  75. }
  76. // detractor
  77. CElementChemistry::~CElementChemistry()
  78. {
  79. Cleanup();
  80. }
  81. // CElementChemistry member functions
  82. // serialization
  83. /*void CElementChemistry::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode)
  84. {
  85. xmls::xString xStrName;
  86. xmls::xDouble xPercentage;
  87. xmls::Slo slo;
  88. slo.Register("StrName", &xStrName);
  89. slo.Register("Percentage", &xPercentage);
  90. if (isStoring)
  91. {
  92. xStrName = m_strName;
  93. xPercentage = m_dPercentage;
  94. slo.Serialize(true, classDoc, rootNode);
  95. }
  96. else
  97. {
  98. slo.Serialize(false, classDoc, rootNode);
  99. m_strName=xStrName.value().c_str();
  100. xPercentage = m_dPercentage;
  101. }
  102. }*/
  103. // protected
  104. // cleanup
  105. void CElementChemistry::Cleanup()
  106. {
  107. // nothing needs to be done at the moment
  108. }
  109. // initialization
  110. void CElementChemistry::Init()
  111. {
  112. m_strName = _T("");
  113. m_dPercentage = 0.0;
  114. }
  115. // duplication
  116. void CElementChemistry::Duplicate(const CElementChemistry& a_oSource)
  117. {
  118. // initialization
  119. Init();
  120. // copy data over
  121. m_strName = a_oSource.m_strName;
  122. m_dPercentage = a_oSource.m_dPercentage;
  123. }
  124. // CElementArea
  125. // public:
  126. CElementArea::CElementArea() // constructor
  127. {
  128. // initialization
  129. Init();
  130. }
  131. CElementArea::CElementArea(const CElementArea& a_oSource) // copy constructor
  132. {
  133. // can't copy itself
  134. if (&a_oSource == this)
  135. {
  136. return;
  137. }
  138. // copy data over
  139. Duplicate(a_oSource);
  140. }
  141. CElementArea::CElementArea(CElementArea* a_poSource) // copy constructor
  142. {
  143. // input check
  144. ASSERT(a_poSource);
  145. if (!a_poSource)
  146. {
  147. return;
  148. }
  149. // can't copy itself
  150. if (a_poSource == this)
  151. {
  152. return;
  153. }
  154. // copy data over
  155. Duplicate(*a_poSource);
  156. }
  157. CElementArea& CElementArea::operator=(const CElementArea& a_oSource) // =operator
  158. {
  159. // cleanup
  160. Cleanup();
  161. // copy the class data over
  162. Duplicate(a_oSource);
  163. // return class
  164. return *this;
  165. }
  166. BOOL CElementArea::operator==(const CElementArea& a_oSource) // ==operator
  167. {
  168. // element chemistry list
  169. if ((int)m_listCElementChemistries.size() == (int)a_oSource.m_listCElementChemistries.size())
  170. {
  171. return FALSE;
  172. }
  173. for (int i = 0; i< (int)m_listCElementChemistries.size(); i++)
  174. {
  175. if (!(m_listCElementChemistries[i] == a_oSource.m_listCElementChemistries[i]))
  176. {
  177. return FALSE;
  178. }
  179. }
  180. // return test result
  181. return abs(m_dArea - a_oSource.m_dArea) < MIN_DOUBLE_VALUE;
  182. }
  183. CElementArea::~CElementArea() // detractor
  184. {
  185. Cleanup();
  186. }
  187. // serialization
  188. // element chemistry list
  189. void CElementArea::SetElementList(CElementChemistriesList a_listElementChemistries)
  190. {
  191. for (auto pElementChemisty : a_listElementChemistries)
  192. {
  193. CElementChemistryPtr pElementChemistyNew = CElementChemistryPtr(new CElementChemistry(*pElementChemisty.get()));
  194. m_listCElementChemistries.push_back(pElementChemistyNew);
  195. }
  196. }
  197. // protected:
  198. // cleanup
  199. void CElementArea::Cleanup()
  200. {
  201. m_listCElementChemistries.clear();
  202. }
  203. // initialization
  204. void CElementArea::Init()
  205. {
  206. m_listCElementChemistries.clear();
  207. }
  208. // duplication
  209. void CElementArea::Duplicate(const CElementArea& a_oSource)
  210. {
  211. // initialization
  212. Init();
  213. // copy data over
  214. m_dArea = a_oSource.m_dArea;
  215. SetElementList(a_oSource.m_listCElementChemistries);
  216. }
  217. // CElement
  218. // constructor
  219. CElement::CElement()
  220. {
  221. // initialization
  222. Init();
  223. }
  224. CElement::CElement(long a_nAtomNum)
  225. {
  226. // initialization
  227. Init();
  228. // assign class member
  229. if (a_nAtomNum >= ATOMIC_NUMBER_MIN && a_nAtomNum <= ATOMIC_NUMBER_MAX)
  230. {
  231. m_nAtomNum = a_nAtomNum;
  232. }
  233. }
  234. CElement::CElement(CString a_strName)
  235. {
  236. // initialization
  237. Init();
  238. // try to find matched name
  239. //InitNamesList();
  240. for(int i = 0; i < ATOMIC_NUMBER_MAX; ++i)
  241. {
  242. if (ELEMENT_NAMES[i].Compare(a_strName) == 0)
  243. {
  244. // got it
  245. m_nAtomNum = i + 1;
  246. break;
  247. }
  248. }
  249. }
  250. // copy constructor
  251. CElement::CElement(const CElement& a_oSource)
  252. {
  253. // can't copy itself
  254. if (&a_oSource == this)
  255. {
  256. return;
  257. }
  258. // copy data over
  259. Duplicate(a_oSource);
  260. }
  261. // copy constructor
  262. CElement::CElement(CElement* a_poSource)
  263. {
  264. // input check
  265. ASSERT(a_poSource);
  266. if (!a_poSource)
  267. {
  268. return;
  269. }
  270. // can't copy itself
  271. if (a_poSource == this)
  272. {
  273. return;
  274. }
  275. // copy data over
  276. Duplicate(*a_poSource);
  277. }
  278. // =operator
  279. CElement& CElement::operator=(const CElement& a_oSource)
  280. {
  281. // cleanup
  282. Cleanup();
  283. // copy the class data over
  284. Duplicate(a_oSource);
  285. // return class
  286. return *this;
  287. }
  288. // ==operator
  289. BOOL CElement::operator==(const CElement& a_oSource)
  290. {
  291. // return test result
  292. return m_nAtomNum == a_oSource.m_nAtomNum && abs(m_dPercentage - a_oSource.m_dPercentage) < MIN_DOUBLE_VALUE;
  293. }
  294. // destructor
  295. CElement::~CElement()
  296. {
  297. // cleanup
  298. Cleanup();
  299. }
  300. // CElement member functions
  301. // serialization
  302. // percentage
  303. void CElement::SetPercentage(double a_dPercentage)
  304. {
  305. if (a_dPercentage >= PERCENTAGE_MIN && a_dPercentage <= PERCENTAGE_MAX)
  306. {
  307. m_dPercentage = a_dPercentage;
  308. }
  309. }
  310. double CElement::GetMolarPercentage()
  311. {
  312. double dMolarPercentage = MIN_DOUBLE_VALUE;
  313. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  314. {
  315. double dAtomWeight = GetAtomWeight();
  316. dMolarPercentage = m_dPercentage / dAtomWeight;
  317. }
  318. return dMolarPercentage;
  319. }
  320. // name
  321. CString CElement::GetName()
  322. {
  323. CString strName = _T("");
  324. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  325. {
  326. return strName;
  327. }
  328. strName = ELEMENT_NAMES[m_nAtomNum - 1];
  329. return strName;
  330. }
  331. CString CElement::GetName(long a_nAtomNum)
  332. {
  333. CString strName = _T("");
  334. if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
  335. {
  336. return strName;
  337. }
  338. strName = ELEMENT_NAMES[a_nAtomNum - 1];
  339. return strName;
  340. }
  341. long CElement::GetAtomicNum(CString a_strName)
  342. {
  343. long nNum = -1;
  344. for (int i = 0; i < ATOMIC_NUMBER_MAX; i++)
  345. {
  346. if (a_strName.CompareNoCase(ELEMENT_NAMES[i]) == 0)
  347. {
  348. nNum = (i + 1);
  349. break;
  350. }
  351. }
  352. return nNum;
  353. }
  354. // atomic weight
  355. double CElement::GetAtomWeight()
  356. {
  357. double dAtomWeight = ATOMIC_WEIGHT_INVALID;
  358. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  359. {
  360. return dAtomWeight;
  361. }
  362. dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[m_nAtomNum - 1];
  363. return dAtomWeight;
  364. }
  365. double CElement::GetAtomWeight(long a_nAtomNum)
  366. {
  367. double dAtomWeight = ATOMIC_WEIGHT_INVALID;
  368. if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX)
  369. {
  370. return dAtomWeight;
  371. }
  372. dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[a_nAtomNum - 1];
  373. return dAtomWeight;
  374. }
  375. double CElement::GetAtomWeight(CString a_strName)
  376. {
  377. double dAtomWeight = ATOMIC_WEIGHT_INVALID;
  378. for (int i = 0; i < ATOMIC_NUMBER_MAX; i++)
  379. {
  380. if (a_strName.CompareNoCase(ELEMENT_NAMES[i]) == 0)
  381. {
  382. dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[i];
  383. break;
  384. }
  385. }
  386. return dAtomWeight;
  387. }
  388. // energy values
  389. double CElement::GetEnergyValueK()
  390. {
  391. double dEnergyValueK = ENERGY_VALUE_INVALID;
  392. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  393. {
  394. return dEnergyValueK;
  395. }
  396. dEnergyValueK = ELEMENT_ENERGY_VALUES_K[m_nAtomNum - 1];
  397. return dEnergyValueK;
  398. }
  399. double CElement::GetEnergyValueL()
  400. {
  401. double dEnergyValueL = ENERGY_VALUE_INVALID;
  402. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  403. {
  404. return dEnergyValueL;
  405. }
  406. dEnergyValueL = ELEMENT_ENERGY_VALUES_L[m_nAtomNum - 1];
  407. return dEnergyValueL;
  408. }
  409. double CElement::GetEnergyValueM()
  410. {
  411. double dEnergyValueM = ENERGY_VALUE_INVALID;
  412. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  413. {
  414. return dEnergyValueM;
  415. }
  416. dEnergyValueM = ELEMENT_ENERGY_VALUES_M[m_nAtomNum - 1];
  417. return dEnergyValueM;
  418. }
  419. std::vector<double> CElement::GetEnergyValues()
  420. {
  421. std::vector<double> vEnergyValues;
  422. if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX)
  423. {
  424. return vEnergyValues;
  425. }
  426. double dEnergyValue = ELEMENT_ENERGY_VALUES_K[m_nAtomNum - 1];
  427. vEnergyValues.push_back(dEnergyValue);
  428. dEnergyValue = ELEMENT_ENERGY_VALUES_L[m_nAtomNum - 1];
  429. vEnergyValues.push_back(dEnergyValue);
  430. dEnergyValue = ELEMENT_ENERGY_VALUES_M[m_nAtomNum - 1];
  431. vEnergyValues.push_back(dEnergyValue);
  432. return vEnergyValues;
  433. }
  434. std::vector<CString>& CElement::GetElementNameList()
  435. {
  436. if (CElement::m_theElementNameVector.empty())
  437. {
  438. int tokenPos = 0;
  439. auto strToken = theElementNameList.Tokenize(_T(","), tokenPos);
  440. while (!strToken.IsEmpty())
  441. {
  442. CElement::m_theElementNameVector.push_back(strToken);
  443. strToken = theElementNameList.Tokenize(_T(","), tokenPos);
  444. }
  445. }
  446. return CElement::m_theElementNameVector;
  447. }
  448. CElementChemistriesList CElement::ExtractElementChemistrys(CString a_strSource)
  449. {
  450. CElementChemistriesList listElementChemistrys;
  451. std::vector<CString>& vElementNames = GetElementNameList();
  452. // separate the source strings into strings
  453. CString strSeperator = _T("\n");
  454. std::vector<CString> vLineStrings = CElement::SplitString(a_strSource, strSeperator);
  455. // strings to elements
  456. const long ELEMENT_STRING_NUMBER = 3;
  457. const long EXTRA_CHAR_NUMBER = 6;
  458. long count = 1;
  459. for (auto& str : vLineStrings)
  460. {
  461. str.Trim(_T("\n"));
  462. if (str.GetLength() <= EXTRA_CHAR_NUMBER)
  463. {
  464. continue;
  465. }
  466. strSeperator = _T(",");
  467. std::vector<CString> vStrings = CElement::SplitString(str, strSeperator);
  468. if (vStrings.size() == ELEMENT_STRING_NUMBER)
  469. {
  470. // create an element chemistry data
  471. CElementChemistryPtr oElementChemistry = CElementChemistryPtr(new CElementChemistry());
  472. // name (extra char "Quant=")
  473. CString strTemp = vStrings[0];
  474. long nNameStringLength = strTemp.GetLength();
  475. // invalid name string?
  476. if (nNameStringLength <= EXTRA_CHAR_NUMBER)
  477. {
  478. continue;
  479. }
  480. // element name
  481. CString strName = strTemp.Right(nNameStringLength - EXTRA_CHAR_NUMBER);
  482. // make sure the element name is valid
  483. auto itr = std::find(vElementNames.begin(), vElementNames.end(), strName);
  484. if (itr == vElementNames.end())
  485. {
  486. // invalid element name
  487. continue;
  488. }
  489. oElementChemistry->SetName(strName);
  490. // percentage
  491. double dPercentge = _tstof(vStrings[2]);
  492. oElementChemistry->SetPercentage(dPercentge);
  493. listElementChemistrys.push_back(oElementChemistry);
  494. }
  495. }
  496. return listElementChemistrys;
  497. }
  498. void CElement::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode)
  499. {
  500. // atomic number
  501. xmls::xLong xnAtomNum;
  502. // percentage
  503. xmls::xDouble xdPercentage;
  504. xmls::xString xEleName;
  505. xmls::Slo slo;
  506. slo.Register("ElementName", &xEleName);
  507. slo.Register("AtomNum", &xnAtomNum);
  508. slo.Register("Percentage", &xdPercentage);
  509. if (isStoring)
  510. {
  511. xEleName = this->GetName();
  512. xnAtomNum = m_nAtomNum;
  513. xdPercentage = m_dPercentage;
  514. slo.Serialize(true, classDoc, rootNode);
  515. }
  516. else
  517. {
  518. slo.Serialize(false, classDoc, rootNode);
  519. m_nAtomNum = xnAtomNum.value();
  520. m_dPercentage = xdPercentage.value();
  521. }
  522. }
  523. // cleanup
  524. void CElement::Cleanup()
  525. {
  526. // nothing needs to be done at the moment
  527. }
  528. // initialization
  529. void CElement::Init()
  530. {
  531. m_nAtomNum = ATOMIC_NUMBER_INVALID;
  532. m_dPercentage = PERCENTAGE_DEFAULT;
  533. }
  534. // duplication
  535. void CElement::Duplicate(const CElement& a_oSource)
  536. {
  537. // initialization
  538. Init();
  539. // copy data over
  540. m_nAtomNum = a_oSource.m_nAtomNum;
  541. m_dPercentage = a_oSource.m_dPercentage;
  542. }
  543. // const CString& a_sSource
  544. // LPCTSTR a_sSep -- separator
  545. std::vector<CString> CElement::SplitString(const CString& a_strSource, LPCTSTR a_strSep)
  546. {
  547. // string list
  548. std::vector<CString> listString;
  549. // source string
  550. CString strSource = a_strSource;
  551. // find the first separator
  552. int nPosLast = 0;
  553. auto nPos = strSource.Find(a_strSep, nPosLast);
  554. // found the separator?
  555. while (nPos >= nPosLast)
  556. {
  557. // there is no string between two seperator if nPos == nPosLast
  558. if (nPos == nPosLast)
  559. {
  560. listString.push_back(_T(""));
  561. nPosLast++;
  562. }
  563. else
  564. {
  565. // get the string between two separator
  566. CString strValue = strSource.Mid(nPosLast, nPos - nPosLast);
  567. strValue.Trim();
  568. // add the string into the string list
  569. listString.push_back(strValue);
  570. nPosLast = nPos + 1;
  571. }
  572. // try to find the next separator
  573. nPos = strSource.Find(a_strSep, nPosLast);
  574. }
  575. // push the last one into the string list
  576. CString strLastValue = strSource.Right(strSource.GetLength() - nPosLast);
  577. strLastValue.Trim();
  578. listString.push_back(strLastValue);
  579. // return the string list
  580. return listString;
  581. }
  582. double CElementChemistry::GetMolarPercentage()
  583. {
  584. // molar percentage
  585. double dMolarPercentage = 0.0;
  586. // get atomic weight of the element
  587. double dAtomWeight = CElement::GetAtomWeight(m_strName);
  588. // make sure atomic weight is valid
  589. if (dAtomWeight > 0.0)
  590. {
  591. // calculate molar percentage
  592. dMolarPercentage = m_dPercentage / dAtomWeight;
  593. }
  594. return dMolarPercentage;
  595. }
  596. void CElementChemistry::SetMolarPercentage(double a_dMolarPer)
  597. {
  598. // get atomic weight of the element
  599. double dAtomWeight = CElement::GetAtomWeight(m_strName);
  600. // set percentage
  601. m_dPercentage = a_dMolarPer * dAtomWeight / 100.0;
  602. }
  603. }