// describe elements #include "stdafx.h" #include "Element.h" namespace OTSDATA { #pragma warning(disable: 4835) const CString CElement::theElementNameList{ _T("H,He") _T(",Li,Be,B,C,N,O,F,Ne") _T(",Na,Mg,Al,Si,P,S,Cl,Ar") _T(",K,Ca,Sc,Ti,V,Cr,Mn,Fe,Co,Ni,Cu,Zn,Ga,Ge,As,Se,Br,Kr") _T(",Rb,Sr,Y,Zr,Nb,Mo,Tc,Ru,Rh,Pd,Ag,Cd,In,Sn,Sb,Te,I,Xe") _T(",Cs,Ba,La") _T(",Ce,Pr,Nd,Pm,Sm,Eu,Gd,Tb,Dy,Ho,Er,Tm,Yb,Lu") _T(",Hf,Ta,W,Re,Os,Ir,Pt,Au,Hg,Tl,Pb,Bi,Po,At,Rn") _T(",Fr,Ra,Ac") _T(",Th,Pa,U,Np,Pu,Am,Cm,Bk,Cf,Es,Fm,Md,No,Lr") }; std::vector CElement::m_theElementNameVector; #pragma warning(default: 4835) // CElementChemistry // constructor CElementChemistry::CElementChemistry() { // initialization Init(); } CElementChemistry::CElementChemistry(CString a_strName, const double a_dPercentage) : m_strName(a_strName) , m_dPercentage(a_dPercentage) { } // copy constructor CElementChemistry::CElementChemistry(const CElementChemistry& a_oSource) { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } // copy constructor CElementChemistry::CElementChemistry(CElementChemistry* a_poSource) { // input check ASSERT(a_poSource); if (!a_poSource) { return; } // can't copy itself if (a_poSource == this) { return; } // copy data over Duplicate(*a_poSource); } // =operator CElementChemistry& CElementChemistry::operator=(const CElementChemistry& a_oSource) { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } // ==operator BOOL CElementChemistry::operator==(const CElementChemistry& a_oSource) { // return test result return m_strName.Compare(a_oSource.m_strName) == 0 && abs(m_dPercentage - a_oSource.m_dPercentage) < MIN_DOUBLE_VALUE; } // detractor CElementChemistry::~CElementChemistry() { Cleanup(); } // CElementChemistry member functions // serialization /*void CElementChemistry::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode) { xmls::xString xStrName; xmls::xDouble xPercentage; xmls::Slo slo; slo.Register("StrName", &xStrName); slo.Register("Percentage", &xPercentage); if (isStoring) { xStrName = m_strName; xPercentage = m_dPercentage; slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_strName=xStrName.value().c_str(); xPercentage = m_dPercentage; } }*/ // protected // cleanup void CElementChemistry::Cleanup() { // nothing needs to be done at the moment } // initialization void CElementChemistry::Init() { m_strName = _T(""); m_dPercentage = 0.0; } // duplication void CElementChemistry::Duplicate(const CElementChemistry& a_oSource) { // initialization Init(); // copy data over m_strName = a_oSource.m_strName; m_dPercentage = a_oSource.m_dPercentage; } // CElementArea // public: CElementArea::CElementArea() // constructor { // initialization Init(); } CElementArea::CElementArea(const CElementArea& a_oSource) // copy constructor { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } CElementArea::CElementArea(CElementArea* a_poSource) // copy constructor { // input check ASSERT(a_poSource); if (!a_poSource) { return; } // can't copy itself if (a_poSource == this) { return; } // copy data over Duplicate(*a_poSource); } CElementArea& CElementArea::operator=(const CElementArea& a_oSource) // =operator { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } BOOL CElementArea::operator==(const CElementArea& a_oSource) // ==operator { // element chemistry list if ((int)m_listCElementChemistries.size() == (int)a_oSource.m_listCElementChemistries.size()) { return FALSE; } for (int i = 0; i< (int)m_listCElementChemistries.size(); i++) { if (!(m_listCElementChemistries[i] == a_oSource.m_listCElementChemistries[i])) { return FALSE; } } // return test result return abs(m_dArea - a_oSource.m_dArea) < MIN_DOUBLE_VALUE; } CElementArea::~CElementArea() // detractor { Cleanup(); } // serialization // element chemistry list void CElementArea::SetElementList(CElementChemistriesList a_listElementChemistries) { for (auto pElementChemisty : a_listElementChemistries) { CElementChemistryPtr pElementChemistyNew = CElementChemistryPtr(new CElementChemistry(*pElementChemisty.get())); m_listCElementChemistries.push_back(pElementChemistyNew); } } // protected: // cleanup void CElementArea::Cleanup() { m_listCElementChemistries.clear(); } // initialization void CElementArea::Init() { m_listCElementChemistries.clear(); } // duplication void CElementArea::Duplicate(const CElementArea& a_oSource) { // initialization Init(); // copy data over m_dArea = a_oSource.m_dArea; SetElementList(a_oSource.m_listCElementChemistries); } // CElement // constructor CElement::CElement() { // initialization Init(); } CElement::CElement(long a_nAtomNum) { // initialization Init(); // assign class member if (a_nAtomNum >= ATOMIC_NUMBER_MIN && a_nAtomNum <= ATOMIC_NUMBER_MAX) { m_nAtomNum = a_nAtomNum; } } CElement::CElement(CString a_strName) { // initialization Init(); // try to find matched name //InitNamesList(); for(int i = 0; i < ATOMIC_NUMBER_MAX; ++i) { if (ELEMENT_NAMES[i].Compare(a_strName) == 0) { // got it m_nAtomNum = i + 1; break; } } } // copy constructor CElement::CElement(const CElement& a_oSource) { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } // copy constructor CElement::CElement(CElement* a_poSource) { // input check ASSERT(a_poSource); if (!a_poSource) { return; } // can't copy itself if (a_poSource == this) { return; } // copy data over Duplicate(*a_poSource); } // =operator CElement& CElement::operator=(const CElement& a_oSource) { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } // ==operator BOOL CElement::operator==(const CElement& a_oSource) { // return test result return m_nAtomNum == a_oSource.m_nAtomNum && abs(m_dPercentage - a_oSource.m_dPercentage) < MIN_DOUBLE_VALUE; } // destructor CElement::~CElement() { // cleanup Cleanup(); } // CElement member functions // serialization // percentage void CElement::SetPercentage(double a_dPercentage) { if (a_dPercentage >= PERCENTAGE_MIN && a_dPercentage <= PERCENTAGE_MAX) { m_dPercentage = a_dPercentage; } } double CElement::GetMolarPercentage() { double dMolarPercentage = MIN_DOUBLE_VALUE; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { double dAtomWeight = GetAtomWeight(); dMolarPercentage = m_dPercentage / dAtomWeight; } return dMolarPercentage; } // name CString CElement::GetName() { CString strName = _T(""); if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return strName; } strName = ELEMENT_NAMES[m_nAtomNum - 1]; return strName; } CString CElement::GetName(long a_nAtomNum) { CString strName = _T(""); if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX) { return strName; } strName = ELEMENT_NAMES[a_nAtomNum - 1]; return strName; } long CElement::GetAtomicNum(CString a_strName) { long nNum = -1; for (int i = 0; i < ATOMIC_NUMBER_MAX; i++) { if (a_strName.CompareNoCase(ELEMENT_NAMES[i]) == 0) { nNum = (i + 1); break; } } return nNum; } // atomic weight double CElement::GetAtomWeight() { double dAtomWeight = ATOMIC_WEIGHT_INVALID; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return dAtomWeight; } dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[m_nAtomNum - 1]; return dAtomWeight; } double CElement::GetAtomWeight(long a_nAtomNum) { double dAtomWeight = ATOMIC_WEIGHT_INVALID; if (a_nAtomNum < 0 || a_nAtomNum >= ATOMIC_NUMBER_MAX) { return dAtomWeight; } dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[a_nAtomNum - 1]; return dAtomWeight; } double CElement::GetAtomWeight(CString a_strName) { double dAtomWeight = ATOMIC_WEIGHT_INVALID; for (int i = 0; i < ATOMIC_NUMBER_MAX; i++) { if (a_strName.CompareNoCase(ELEMENT_NAMES[i]) == 0) { dAtomWeight = ELEMENT_ATOMIC_WEIGHT_VALUES[i]; break; } } return dAtomWeight; } // energy values double CElement::GetEnergyValueK() { double dEnergyValueK = ENERGY_VALUE_INVALID; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return dEnergyValueK; } dEnergyValueK = ELEMENT_ENERGY_VALUES_K[m_nAtomNum - 1]; return dEnergyValueK; } double CElement::GetEnergyValueL() { double dEnergyValueL = ENERGY_VALUE_INVALID; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return dEnergyValueL; } dEnergyValueL = ELEMENT_ENERGY_VALUES_L[m_nAtomNum - 1]; return dEnergyValueL; } double CElement::GetEnergyValueM() { double dEnergyValueM = ENERGY_VALUE_INVALID; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return dEnergyValueM; } dEnergyValueM = ELEMENT_ENERGY_VALUES_M[m_nAtomNum - 1]; return dEnergyValueM; } std::vector CElement::GetEnergyValues() { std::vector vEnergyValues; if (m_nAtomNum < 0 || m_nAtomNum >= ATOMIC_NUMBER_MAX) { return vEnergyValues; } double dEnergyValue = ELEMENT_ENERGY_VALUES_K[m_nAtomNum - 1]; vEnergyValues.push_back(dEnergyValue); dEnergyValue = ELEMENT_ENERGY_VALUES_L[m_nAtomNum - 1]; vEnergyValues.push_back(dEnergyValue); dEnergyValue = ELEMENT_ENERGY_VALUES_M[m_nAtomNum - 1]; vEnergyValues.push_back(dEnergyValue); return vEnergyValues; } std::vector& CElement::GetElementNameList() { if (CElement::m_theElementNameVector.empty()) { int tokenPos = 0; auto strToken = theElementNameList.Tokenize(_T(","), tokenPos); while (!strToken.IsEmpty()) { CElement::m_theElementNameVector.push_back(strToken); strToken = theElementNameList.Tokenize(_T(","), tokenPos); } } return CElement::m_theElementNameVector; } CElementChemistriesList CElement::ExtractElementChemistrys(CString a_strSource) { CElementChemistriesList listElementChemistrys; std::vector& vElementNames = GetElementNameList(); // separate the source strings into strings CString strSeperator = _T("\n"); std::vector vLineStrings = CElement::SplitString(a_strSource, strSeperator); // strings to elements const long ELEMENT_STRING_NUMBER = 3; const long EXTRA_CHAR_NUMBER = 6; long count = 1; for (auto& str : vLineStrings) { str.Trim(_T("\n")); if (str.GetLength() <= EXTRA_CHAR_NUMBER) { continue; } strSeperator = _T(","); std::vector vStrings = CElement::SplitString(str, strSeperator); if (vStrings.size() == ELEMENT_STRING_NUMBER) { // create an element chemistry data CElementChemistryPtr oElementChemistry = CElementChemistryPtr(new CElementChemistry()); // name (extra char "Quant=") CString strTemp = vStrings[0]; long nNameStringLength = strTemp.GetLength(); // invalid name string? if (nNameStringLength <= EXTRA_CHAR_NUMBER) { continue; } // element name CString strName = strTemp.Right(nNameStringLength - EXTRA_CHAR_NUMBER); // make sure the element name is valid auto itr = std::find(vElementNames.begin(), vElementNames.end(), strName); if (itr == vElementNames.end()) { // invalid element name continue; } oElementChemistry->SetName(strName); // percentage double dPercentge = _tstof(vStrings[2]); oElementChemistry->SetPercentage(dPercentge); listElementChemistrys.push_back(oElementChemistry); } } return listElementChemistrys; } void CElement::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode) { // atomic number xmls::xLong xnAtomNum; // percentage xmls::xDouble xdPercentage; xmls::xString xEleName; xmls::Slo slo; slo.Register("ElementName", &xEleName); slo.Register("AtomNum", &xnAtomNum); slo.Register("Percentage", &xdPercentage); if (isStoring) { xEleName = this->GetName(); xnAtomNum = m_nAtomNum; xdPercentage = m_dPercentage; slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_nAtomNum = xnAtomNum.value(); m_dPercentage = xdPercentage.value(); } } // cleanup void CElement::Cleanup() { // nothing needs to be done at the moment } // initialization void CElement::Init() { m_nAtomNum = ATOMIC_NUMBER_INVALID; m_dPercentage = PERCENTAGE_DEFAULT; } // duplication void CElement::Duplicate(const CElement& a_oSource) { // initialization Init(); // copy data over m_nAtomNum = a_oSource.m_nAtomNum; m_dPercentage = a_oSource.m_dPercentage; } // const CString& a_sSource // LPCTSTR a_sSep -- separator std::vector CElement::SplitString(const CString& a_strSource, LPCTSTR a_strSep) { // string list std::vector listString; // source string CString strSource = a_strSource; // find the first separator int nPosLast = 0; auto nPos = strSource.Find(a_strSep, nPosLast); // found the separator? while (nPos >= nPosLast) { // there is no string between two seperator if nPos == nPosLast if (nPos == nPosLast) { listString.push_back(_T("")); nPosLast++; } else { // get the string between two separator CString strValue = strSource.Mid(nPosLast, nPos - nPosLast); strValue.Trim(); // add the string into the string list listString.push_back(strValue); nPosLast = nPos + 1; } // try to find the next separator nPos = strSource.Find(a_strSep, nPosLast); } // push the last one into the string list CString strLastValue = strSource.Right(strSource.GetLength() - nPosLast); strLastValue.Trim(); listString.push_back(strLastValue); // return the string list return listString; } double CElementChemistry::GetMolarPercentage() { // molar percentage double dMolarPercentage = 0.0; // get atomic weight of the element double dAtomWeight = CElement::GetAtomWeight(m_strName); // make sure atomic weight is valid if (dAtomWeight > 0.0) { // calculate molar percentage dMolarPercentage = m_dPercentage / dAtomWeight; } return dMolarPercentage; } void CElementChemistry::SetMolarPercentage(double a_dMolarPer) { // get atomic weight of the element double dAtomWeight = CElement::GetAtomWeight(m_strName); // set percentage m_dPercentage = a_dMolarPer * dAtomWeight / 100.0; } }