#pragma once #include "stdafx.h" #include "OTSProjMgrFile.h" #include "OTSProgMgr.h" #include "StageFile.h" #include "STDXMLFileMnr.h" #include "MsrParamFileMgr.h" #include "OTSImageProcess.h" #include "OTSFileSys.h" #include "OTSHelper.h" #include "resource.h" #include "SmplMsrResultFile.h" #include "IncAFileMgr.h" #include #include #include namespace OTSMODEL { using namespace OTSIMGPROC; // project file mark const int PROJ_MGR_FILE_MARK = 'P' + 'R' + 'O' + 'J' + 'E' + 'T' + 'M' + 'A' + 'N' + 'A' + 'G' + 'E' + 'R'; // project file version string const CString PROJ_MGR_FILE_VERSION = _T("1.1.1"); // project file extension const CString PROJ_EXTION = _T("prj"); // project file filter const CString PROJECT_FILE_FILTER = _T("Project Files (*.prj)|*.prj|All Files (*.*)|*.*||"); // EDGE threshold if length > 15000 edge is 1000, if length > 10000 edge is 500, otherwise no edge, unit is um const long LENGTH_THRESHOLD = 150000; const long LENGTH_THRESHOLD_MIN = 10000; const long EDGE = 1000; const long EDGE_MIN = 500; // COTSProjMgrFile // constructor COTSProjMgrFile::COTSProjMgrFile() { Init(); } // copy constructor COTSProjMgrFile::COTSProjMgrFile(const COTSProjMgrFile& a_oSource) { // can't copy itself if (&a_oSource == this) { return; } // copy data over Duplicate(a_oSource); } COTSProjMgrFile::COTSProjMgrFile(COTSProjMgrFile* 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 COTSProjMgrFile& COTSProjMgrFile::operator=(const COTSProjMgrFile& a_oSource) { // cleanup Cleanup(); // copy the class data over Duplicate(a_oSource); // return class return *this; } // destructor COTSProjMgrFile::~COTSProjMgrFile() { // cleanup Cleanup(); } // serialization void COTSProjMgrFile::Serialize(bool isStoring, tinyxml2::XMLDocument * classDoc, tinyxml2::XMLElement * rootNode) { xmls::xInt xProjMgrFileMark; xmls::xString xProjMgrFileVersion; xmls::xString xstrPathName; xmls::Collection< CHoleBSEImg> xholeBSEImgs; xmls::Collection xsamples; xmls::Slo slo; slo.Register("ProjMgrFileMark", &xProjMgrFileMark); slo.Register("ProjMgrFileVersion", &xProjMgrFileVersion); slo.Register("strPathName", &xstrPathName); slo.Register("SEMStageData", m_pSEMStageData.get()); slo.Register("Stage", m_pStage.get()); slo.Register("HoleBSEImg", &xholeBSEImgs); slo.Register("Samples", &xsamples); if (isStoring) { xProjMgrFileMark = PROJ_MGR_FILE_MARK; xProjMgrFileVersion = PROJ_MGR_FILE_VERSION; xstrPathName = m_strPathName; xholeBSEImgs.Clear(); for (auto hole : m_listHoleBSEImg) { xholeBSEImgs.addItem(hole.get()); } xsamples.Clear(); for (auto sample : m_listSamples) { xsamples.addItem(sample.get()); } slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_strPathName = xstrPathName.value().c_str(); m_listHoleBSEImg.clear(); for (unsigned int i = 0; i < xholeBSEImgs.size(); i++) { m_listHoleBSEImg.push_back(CHoleBSEImgPtr(xholeBSEImgs.getItem(i))); } m_listSamples.clear(); for (int i = 0; i < (int)xsamples.size(); i++) { m_listSamples.push_back(COTSSamplePtr(xsamples.getItem(i))); } } } // class member functions // public // file BOOL COTSProjMgrFile::NewFile() { // file invalidation if (!IsValid()) { // shouldn't happen, file is invalid LogErrorTrace(__FILE__, __LINE__, _T("Load: file is invalid.")); return FALSE; } // set file name SetPathName(UNTITLED_FILE_NAME); // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::Load() { // use dll resource AFX_MANAGE_STATE(AfxGetStaticModuleState()); // open file dialog, CFileDialog dlg(TRUE, NULL, NULL, OFN_FILEMUSTEXIST, PROJECT_FILE_FILTER); if (dlg.DoModal() != IDOK) { // user didn't click OK button, return FALSE LogTrace(__FILE__, __LINE__, _T("Load: user canceled on file open dialog.")); return FALSE; } //Init data Cleanup(); // get file name CString strPathName = dlg.GetPathName(); // check if the file exist if (!COTSFileSys::Exists(strPathName)) { // shouldn't happen, file does not exist LogErrorTrace(__FILE__, __LINE__, _T("Load: file (%s) does not exist."), strPathName); return FALSE; } tinyxml2::XMLDocument doc; doc.LoadFile(strPathName);//载入xml文件 tinyxml2::XMLElement *rootNode; rootNode = doc.FirstChildElement(RootClassName); Serialize(false, &doc, rootNode); m_strPathName = strPathName; // get path of the pathname CString strFilePath = COTSHelper::GetFolderName(strPathName); if (strFilePath.IsEmpty()) { // file path string is an empty string LogErrorTrace(__FILE__, __LINE__, _T("Load: file path string is an empty string.")); return FALSE; } //------------- for(auto smpl:m_listSamples) { // field file sub folder string CString strFieldFileSubFolder = strFilePath + _T("\\")+smpl->GetName()+_T("\\") + SMPL_MSR_RESULT_FIELDS_FILE_SUBFOLDER + _T("\\"); // check if the field file sub folder exists if (!COTSFileSys::Exists(strFieldFileSubFolder)) {// field files folder doesn't exist //LogErrorTrace(__FILE__, __LINE__, _T("Load: field files folder doesn't exist (%s)."), strFieldFileSubFolder); continue; } CString strIncAFilename = strFieldFileSubFolder + _T("\\") + SMPL_MSR_RESULT_INCLUSION_FILE; CIncAFileMgrPtr pIncAFileMgr = CIncAFileMgrPtr(new CIncAFileMgr(strIncAFilename)); COTSFieldDataList allFlds; CMsrSampleStatusPtr poMsrStatus = smpl->GetMsrStatus(); CMsrResultsPtr poMsrResults = smpl->GetMsrResults(); double aFldArea = smpl->CalculateAFieldArea(); if (pIncAFileMgr->GetAllFieldsFromDB(allFlds, poMsrStatus, poMsrResults, aFldArea)) { smpl->SetFieldsData(allFlds); // file validation if (!m_pSEMStageData || *(m_pSEMStageData.get()) == CSEMStageData()) { // invalid SME stage data LogErrorTrace(__FILE__, __LINE__, _T("Load: invalid SME stage data.")); return FALSE; } if (!m_pStage || *(m_pStage.get()) == CStage()) { // invalid stage LogErrorTrace(__FILE__, __LINE__, _T("Load: empty SEM stage data.")); return FALSE; } // set modify flag SetModify(FALSE); // set pathname SetPathName(strPathName); // set working sample if (m_listSamples.size() > 0) { m_nWorkingSampeIndex = 0; } else { m_nWorkingSampeIndex = -1; } } else { return FALSE; } } if (!m_listSamples.empty()) { m_nWorkingSampeIndex = 0; } //----------------------------------------- return TRUE; } BOOL COTSProjMgrFile::Save() { // Save or Save As, if strPathName is not empty, it is exist in the computer, this is a save action CString strPathName = GetPathName(); // is this a new file? strPathName.Trim(); if (strPathName.CompareNoCase(UNTITLED_FILE_NAME) == 0) { if (!SaveAs()) { return FALSE; } // this is a new file for (auto pSample : m_listSamples) { DeleteSampleFiles(pSample->GetName()); } //DeleteSampleFiles // return save as result } tinyxml2::XMLDocument doc; if (COTSFileSys::Exists(strPathName)) { doc.LoadFile(strPathName);//载入xml文件 } doc.Clear(); tinyxml2::XMLDeclaration* declaration = doc.NewDeclaration();//添加xml文件头申明 doc.InsertFirstChild(declaration); tinyxml2::XMLElement *rootNode; rootNode = doc.NewElement(RootClassName); Serialize(true, &doc, rootNode); doc.InsertEndChild(rootNode); int result = doc.SaveFile(strPathName); // set file modify flag SetModify(FALSE); // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::SaveAs() { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // save file dialog CString strFileName = _T(""); if (!m_strPathName.IsEmpty()) { strFileName = COTSHelper::GetFileName(m_strPathName); } CFileDialog dlg(FALSE, PROJ_EXTION, strFileName, OFN_OVERWRITEPROMPT, PROJECT_FILE_FILTER); if (dlg.DoModal() != IDOK) { // user didn't click OK button, return FALSE LogTrace(__FILE__, __LINE__, _T("SaveAs: user canceled on file open dialog.")); return FALSE; } // get file pathname CString strPathName = dlg.GetPathName(); //--------xml serialize------- tinyxml2::XMLDocument doc; if (COTSFileSys::Exists(strPathName)) { doc.LoadFile(strPathName);//载入xml文件 } doc.Clear(); tinyxml2::XMLDeclaration* declaration = doc.NewDeclaration();//添加xml文件头申明 doc.InsertFirstChild(declaration); tinyxml2::XMLElement *rootNode; rootNode = doc.NewElement(RootClassName); doc.InsertEndChild(rootNode); Serialize(true, &doc, rootNode); int result = doc.SaveFile(strPathName); //----------------------------- // set file modify flag m_bModify = FALSE; // Set project Path SetPathName(strPathName); // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::IsValid() { if (!m_pSEMStageData || m_pSEMStageData.get() == nullptr) { return FALSE; } else if (!m_pStage || m_pStage.get() == nullptr) { return FALSE; } else if (!m_pGenParam || !m_pImageProcParam || !m_pImageScanParam || !m_pXRayParam) { return FALSE; } // Ok, return TRUE return TRUE; } // SEM stage data void COTSProjMgrFile::SetSEMStageData(CSEMStageDataPtr a_pCSEMStageData) { // safety check ASSERT(a_pCSEMStageData); if (!a_pCSEMStageData) { // invalid stage data pointer LogErrorTrace(__FILE__, __LINE__, _T("SetStageData: invalid input stage data pointer.")); return; } m_pSEMStageData = CSEMStageDataPtr(new CSEMStageData(a_pCSEMStageData.get())); } // stage (working stage) void COTSProjMgrFile::SetStage(CStagePtr a_pStage) { // safety check ASSERT(a_pStage); if (!a_pStage) { // invalid input LogErrorTrace(__FILE__, __LINE__, _T("SetStage: invalid input stage pointer.")); return; } m_pStage = CStagePtr(new CStage(a_pStage.get())); } // general parameters void COTSProjMgrFile::SetGenParam(COTSGeneralParametersPtr a_pGenParam) { ASSERT(a_pGenParam); if (!a_pGenParam) { // invalid input LogErrorTrace(__FILE__, __LINE__, _T("SetGenParam: invalid input general parameter pointer.")); return; } m_pGenParam = COTSGeneralParametersPtr(new COTSGeneralParameters(a_pGenParam.get())); } // image scan parameters void COTSProjMgrFile::SetImageScanParam(COTSImageScanParamPtr a_pImageScanParam) { ASSERT(a_pImageScanParam); if (!a_pImageScanParam) { // invalid input LogErrorTrace(__FILE__, __LINE__, _T("SetImageScanParam: invalid input image scan parameter pointer.")); return; } m_pImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam(a_pImageScanParam.get())); } // image process parameters void COTSProjMgrFile::SetImageProcParam(COTSImageProcessParamPtr a_pImageProcParam) { ASSERT(a_pImageProcParam); if (!a_pImageProcParam) { // invalid input LogErrorTrace(__FILE__, __LINE__, _T("SetImageProcParam: invalid input image process parameter pointer.")); return; } m_pImageProcParam = COTSImageProcessParamPtr(new COTSImageProcessParam(a_pImageProcParam.get())); } // x ray parameters void COTSProjMgrFile::SetXRayParam(COTSXRayParamPtr a_pXRayParam) { ASSERT(a_pXRayParam); if (!a_pXRayParam) { LogErrorTrace(__FILE__, __LINE__, _T("SetXRayParam: invalid X-Ray parameter pointer.")); return; } m_pXRayParam = COTSXRayParamPtr(new COTSXRayParam(a_pXRayParam.get())); } // samples list bool COTSProjMgrFile::SetSampleList(COTSSamplesList& a_listSample, BOOL a_bClear/* = TRUE*/) { // clear samples list if necessary if (a_bClear) { m_listSamples.clear(); } // go through the sample list of the source for (auto pSample : a_listSample) { // add the new sample into sample list m_listSamples.push_back(pSample); } return true; } COTSSamplePtr COTSProjMgrFile::GetSampleByIndex(int a_nIndex) { // safe check if (a_nIndex < 0 || a_nIndex >= (int)m_listSamples.size()) { // invalid sample id LogErrorTrace(__FILE__, __LINE__, _T("GetSample: invalid sample id.")); return nullptr; } // get the matching sample COTSSamplePtr pSample = m_listSamples[a_nIndex]; // return the sample return pSample; } COTSSamplePtr COTSProjMgrFile::GetSampleByName(CString a_strSampleName) { // find the name matching sample auto itr = std::find_if(m_listSamples.begin(), m_listSamples.end(), [a_strSampleName](COTSSamplePtr p) { return p->GetName().CompareNoCase(a_strSampleName) == 0; }); // get the matching sample if found COTSSamplePtr pSample = nullptr; if (itr != m_listSamples.end()) { pSample = *itr; } // return the sample return pSample; } COTSSamplePtr COTSProjMgrFile::AddSample(CString a_strHoleName) { // this file is valid, pass the test will make sure all the parameters are ok. if (!IsValid()) { // shouldn't be here, invalid file LogErrorTrace(__FILE__, __LINE__, _T("AddSample: invalid file.")); return nullptr; } // get new sample name CString strNewSampleName = GetNewSampleName(); // make sure the new sample name is not an empty string strNewSampleName.Trim(); //判断当前文件夹下是否有新的文件 有就删除 DeleteSampleFiles(strNewSampleName); // get a suitable sample hole for the new sample CHolePtr pHole = SelectASmpleHole(a_strHoleName); // check the sample hole if (!pHole) { // failed to get sample hole for the new sample LogErrorTrace(__FILE__, __LINE__, _T("AddSample: failed to get sample hole for the new sample.")); return nullptr; } // particle analysis STD lib CPartSTDDataPtr pPartSTDDataPtr = m_pGenParam->GetPartSTDLib(); // measure data parameters containing particle analysis std, image scan parameter, image process parameter and x-ray parameter CMsrParamsPtr poMsrParams = CMsrParamsPtr(new CMsrParams()); STEEL_TECHNOLOGY a_nVal = (STEEL_TECHNOLOGY)m_pGenParam->GetSteelTechnology(); poMsrParams->SetSteelTechnology(a_nVal); poMsrParams->SetPartSTDData(pPartSTDDataPtr); poMsrParams->SetImageScanParam(m_pImageScanParam); poMsrParams->SetImageProcessParam(m_pImageProcParam); poMsrParams->SetXRayParam(m_pXRayParam); // measurement area //CDomainPtr pMsrArea = CalculateMsrArea(pHole); CDomainPtr pMsrArea = CalculateDefaultArea(pHole); // create a sample COTSSamplePtr pSample = COTSSamplePtr(new COTSSample()); // set sample parameters pSample->SetName(strNewSampleName); pSample->SetSampleHoleName(pHole->GetName()); pSample->SetSwitch(m_pGenParam->GetMeasurementSwitch()); pSample->SetMsrParams(poMsrParams); pSample->SetMsrArea(pMsrArea); // add the new sample into the samples list m_listSamples.push_back(pSample); // set the project file modified. SetModify(); // set the new as working sample m_nWorkingSampeIndex = (int)m_listSamples.size() - 1; // return the new sample return pSample; } //2020-7-30 张佳鑫 BOOL COTSProjMgrFile::DeleteSampleFiles(CString a_nString) { CString strSamplePath = COTSHelper::GetFolderName(m_strPathName); //m_strPathName + _T("\\") + m_listSamples[a_nIndex]->GetName(); // this sample has been measured, need to delete all the measure result files. if (COTSFileSys::IsFolder(strSamplePath)) { strSamplePath = strSamplePath + _T("\\") + a_nString; CString strSampleFieldPath = strSamplePath + _T("\\") + SMPL_MSR_RESULT_FIELDS_FILE_SUBFOLDER; if (!COTSFileSys::DeleteAllFiles(strSampleFieldPath)) { return FALSE; } SetFileAttributes(strSampleFieldPath, FILE_ATTRIBUTE_NORMAL); //设置文件夹的属性 RemoveDirectory(strSampleFieldPath); //删除文件夹 if (!COTSFileSys::DeleteAllFiles(strSamplePath)) { return FALSE; } SetFileAttributes(strSamplePath, FILE_ATTRIBUTE_NORMAL); //设置文件夹的属性 RemoveDirectory(strSamplePath); //删除文件夹 } } BOOL COTSProjMgrFile::DeleteSampleByIndex(int a_nIndex) { // find the sample's result file CString strSamplePath = COTSHelper::GetFolderName(m_strPathName); //m_strPathName + _T("\\") + m_listSamples[a_nIndex]->GetName(); // this sample has been measured, need to delete all the measure result files. if(COTSFileSys::IsFolder(strSamplePath)) { strSamplePath = strSamplePath + _T("\\") + m_listSamples[a_nIndex]->GetName(); CString strSampleFieldPath = strSamplePath + _T("\\") + SMPL_MSR_RESULT_FIELDS_FILE_SUBFOLDER; if (!COTSFileSys::DeleteAllFiles(strSampleFieldPath)) { return FALSE; } SetFileAttributes(strSampleFieldPath, FILE_ATTRIBUTE_NORMAL); //设置文件夹的属性 RemoveDirectory(strSampleFieldPath); //删除文件夹 if (!COTSFileSys::DeleteAllFiles(strSamplePath)) { return FALSE; } SetFileAttributes(strSamplePath, FILE_ATTRIBUTE_NORMAL); //设置文件夹的属性 RemoveDirectory(strSamplePath); //删除文件夹 } // check the index if (a_nIndex < 0 || a_nIndex >= (int)m_listSamples.size()) { // invalid input sample index LogErrorTrace(__FILE__, __LINE__, _T("DeleteSampleByIndex::input sample index")); return FALSE; } // calculate new working sample index int nNewWorkingSampeIndex; if (a_nIndex < m_nWorkingSampeIndex) { nNewWorkingSampeIndex = m_nWorkingSampeIndex - 1; } else if (a_nIndex > m_nWorkingSampeIndex) { nNewWorkingSampeIndex = m_nWorkingSampeIndex; } else { // deleting working sample. if (a_nIndex == (int)m_listSamples.size() - 1) { // this is the last sample, select the above sample as working sample // if this is only sample in the list working sample index will be -1; nNewWorkingSampeIndex = m_nWorkingSampeIndex - 1; } else { // select next sample as working sample nNewWorkingSampeIndex = m_nWorkingSampeIndex; } } // delete the sample m_listSamples.erase(m_listSamples.begin() + a_nIndex); // the file is modified. SetModify(); // reset working sample index m_nWorkingSampeIndex = nNewWorkingSampeIndex; // ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::DeleteSampleByName(CString a_strSampleName) { // check input sample name a_strSampleName.Trim(); if (a_strSampleName.IsEmpty()) { // input sample name is empty LogErrorTrace(__FILE__, __LINE__, _T("DeleteSampleByName: input sample name is an empty string.")); return FALSE; } // go through sample list int nIndex = 0; for (auto pSample : m_listSamples) { // return TRUE if this is not an exclude sample and its name is same with input CString strSampleName = pSample->GetName(); if (strSampleName.CompareNoCase(a_strSampleName) == 0) { // find the sample, return deleting result return DeleteSampleByIndex(nIndex); } ++nIndex; } // can't find the sample in the samples list, return FALSE return FALSE; } BOOL COTSProjMgrFile::SameNameInList(CString a_strSampleName, int a_nExclude /*= -1*/) { // make sure the input sample name is not empty a_strSampleName.Trim(); if (a_strSampleName.IsEmpty()) { // shouldn't happen, input name is an empty string LogErrorTrace(__FILE__, __LINE__, _T("SameNameInList: input name is an empty string.")); return FALSE; } // go through sample list int nIndex = 0; for (auto pSample : m_listSamples) { // return TRUE if this is not an exclude sample and its name is same with input CString strSampleName = pSample->GetName(); if (nIndex != a_nExclude && strSampleName.CompareNoCase(a_strSampleName) == 0) { // find a same name sample return TRUE; } ++nIndex; } // no, same name sample in the same list, return FALSE return FALSE; } BOOL COTSProjMgrFile::ResetSamplesListOrder(std::vector a_listSampleNames) { // no sample in the samples list; shouldn't be here if (m_listSamples.size() == 0) { LogErrorTrace(__FILE__, __LINE__, _T("ResetSamplesListOrder: no sample in samples list.")); return FALSE; } // make sure that input sample names list size is same with the samples list if (m_listSamples.size() != a_listSampleNames.size()) { LogErrorTrace(__FILE__, __LINE__, _T("ResetSamplesListOrder: sample names list has different size with the samples list.")); return FALSE; } // new sample list COTSSamplesList listSamples; // go through the sample names list for (auto strSampleName : a_listSampleNames) { // find the sample auto itr = find_if(m_listSamples.begin(), m_listSamples.end(), [strSampleName](COTSSamplePtr p) { return p->GetName().CompareNoCase(strSampleName) == 0; }); if (itr == m_listSamples.end()) { // failed to find the sample LogErrorTrace(__FILE__, __LINE__, _T("ResetSamplesListOrder: failed to find the sample (%s)."), strSampleName); return FALSE; } // add the sample into the new list listSamples.push_back(*itr); } // reset the samples list m_listSamples.clear(); for (auto pSample : listSamples) { m_listSamples.push_back(pSample); } // set modify flag SetModify(); // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::InsrtSample(COTSSamplePtr a_pSample, int a_nIndex) { // input check ASSERT(a_pSample); if (!a_pSample) { // invalid input sample pointer LogErrorTrace(__FILE__, __LINE__, _T("InsrtSample: invalid input sample pointer.")); return FALSE; } if (m_listSamples.size() == 0 || a_nIndex >= (int)m_listSamples.size()) { m_listSamples.push_back(a_pSample); } else if (a_nIndex <= 0) { m_listSamples.insert(m_listSamples.begin(), a_pSample); } else { m_listSamples.insert(m_listSamples.begin() + a_nIndex, a_pSample); } // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::ChangeSamplePosition(int a_nIndexFrom, int a_nIndexTo) { // make sure both index are valid if (a_nIndexFrom < 0 || a_nIndexFrom >= (int)m_listSamples.size()) { // invalid from index LogErrorTrace(__FILE__, __LINE__, _T("ChangeSamplePosition: invalid from index.")); return FALSE; } if (a_nIndexTo < 0 || a_nIndexTo >= (int)m_listSamples.size()) { // invalid to index LogErrorTrace(__FILE__, __LINE__, _T("ChangeSamplePosition: invalid to index.")); return FALSE; } // need to do nothing if the two indexes are the same if (a_nIndexFrom != a_nIndexTo) { // move to last? BOOL bLast = (a_nIndexTo == ((int)m_listSamples.size() - 1)); // get the sample COTSSamplePtr pSample = m_listSamples.at(a_nIndexFrom); // remove it from the samples list m_listSamples.erase(m_listSamples.begin() + a_nIndexFrom); // put the sample back in if (bLast) { m_listSamples.push_back(pSample); } else { m_listSamples.insert(m_listSamples.begin() + a_nIndexTo, pSample); } } // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::MoveSamplePosition(COTSSamplePtr a_pTargetSample, COTSSamplePtr a_RefpSample, BOOL a_bBefore /*= TRUE*/) { // check input ASSERT(a_pTargetSample); if (!a_pTargetSample) { // invalid input target sample pointer LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: invalid input target sample pointer.")); return FALSE; } ASSERT(a_RefpSample); if (!a_RefpSample) { // invalid input ref sample pointer LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: invalid input ref sample pointer.")); return FALSE; } auto itrTarget = std::find(m_listSamples.begin(), m_listSamples.end(), a_pTargetSample); if (itrTarget == m_listSamples.end()) { // target sample in not in the samples list LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: target sample in not in the samples list.")); return FALSE; } auto itrRef = std::find(m_listSamples.begin(), m_listSamples.end(), a_RefpSample); if (itrRef == m_listSamples.end()) { // ref sample in not in the samples list LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: ref sample in not in the samples list.")); return FALSE; } // need to do nothing if the two sample are same if (itrTarget != itrRef) { // remove the sample from the samples list m_listSamples.erase(itrTarget); // find ref sample position again itrRef = std::find(m_listSamples.begin(), m_listSamples.end(), a_RefpSample); if (itrRef == m_listSamples.end()) { // shouldn't happen, ref sample in not in the samples list LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: ref sample in not in the samples list.")); return FALSE; } // put the sample back in if (a_bBefore) { m_listSamples.insert(itrRef, a_pTargetSample); } else { m_listSamples.insert(itrRef + 1, a_pTargetSample); } } // Ok, return TRUE return TRUE; } BOOL COTSProjMgrFile::MoveSamplePosition(CString a_strTargetSampleName, CString a_strRefSampleName, BOOL a_bBefore /*= TRUE*/) { // input check a_strTargetSampleName.Trim(); if (a_strTargetSampleName.IsEmpty()) { // input target sample is an empty string LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: input target sample is an empty string.")); return FALSE; } a_strRefSampleName.Trim(); if (a_strRefSampleName.IsEmpty()) { // input ref sample is an empty string LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: input ref sample is an empty string.")); return FALSE; } auto itr = std::find_if(m_listSamples.begin(), m_listSamples.end(), [a_strTargetSampleName](COTSSamplePtr p) { return p->GetName().CompareNoCase(a_strTargetSampleName) == 0; }); if (itr == m_listSamples.end()) { // target sample name is not the name of any sample in the samples list LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: target sample is not the name of any sample in the samples list.")); return FALSE; } COTSSamplePtr pTargetSample = *itr; itr = std::find_if(m_listSamples.begin(), m_listSamples.end(), [a_strRefSampleName](COTSSamplePtr p) { return p->GetName().CompareNoCase(a_strRefSampleName) == 0; }); if (itr == m_listSamples.end()) { // ref sample name is not the name of any sample in the samples list LogErrorTrace(__FILE__, __LINE__, _T("MoveSamplePosition: ref sample is not the name of any sample in the samples list.")); return FALSE; } COTSSamplePtr pRefSample = *itr; // need to do nothing if the two name are same if (a_strTargetSampleName.CompareNoCase(a_strRefSampleName) != 0) { return MoveSamplePosition(pTargetSample, pRefSample, a_bBefore); } // Ok, return TRUE return TRUE; } // working sample COTSSamplePtr COTSProjMgrFile::GetWorkingSample() { // check if the working sample index if ( m_nWorkingSampeIndex < 0 || m_nWorkingSampeIndex >= (int)m_listSamples.size()) { // invalid working sample index return nullptr; } return GetSampleByIndex(m_nWorkingSampeIndex); } BOOL COTSProjMgrFile::SetWorkingSampleByIndex(int a_nIndex) { // special treatment if (a_nIndex == -1 && m_listSamples.size() == 0) { m_nWorkingSampeIndex = -1; return TRUE; } // check if the working sample index if (0 > a_nIndex || a_nIndex >= (int)m_listSamples.size()) { // invalid sample index return FALSE; } m_nWorkingSampeIndex = a_nIndex; return TRUE; } BOOL COTSProjMgrFile::SetWorkingSampleByName(CString a_pSampleName) { // check input sample name a_pSampleName.Trim(); if (a_pSampleName.IsEmpty()) { // input sample name is empty LogErrorTrace(__FILE__, __LINE__, _T("SetWorkingSampleByName: input sample name is an empty string.")); return FALSE; } // go through sample list int nIndex = 0; for (auto pSample : m_listSamples) { // return TRUE if this is not an exclude sample and its name is same with input CString strSampleName = pSample->GetName(); if (strSampleName.CompareNoCase(a_pSampleName) == 0) { // find the sample, return deleting result return SetWorkingSampleByIndex(nIndex); } ++nIndex; } // failed to find the named sample LogErrorTrace(__FILE__, __LINE__, _T("SetWorkingSampleByName: failed to find the named sample.")); // failed to find the named sample return FALSE return FALSE; } BOOL COTSProjMgrFile::DeleteWorkingSample() { // check if the working sample index if (m_nWorkingSampeIndex < 0 || m_nWorkingSampeIndex >= (int)m_listSamples.size()) { // invalid working sample index return FALSE; } // return the result of DeleteSampleByIndex return DeleteSampleByIndex(m_nWorkingSampeIndex); } // hole BSE images list void COTSProjMgrFile::SetHoleBESImgList(CHoleBSEImgsList& a_listHoleBSEImg, BOOL a_bClear/* = TRUE*/) { // clear the hole BSE image list if necessary if (a_bClear) { m_listHoleBSEImg.clear(); } // go through the input list for (auto pHoleBSEImg : a_listHoleBSEImg) { // create a hole BSE image copy CHoleBSEImgPtr pHoleBSEImgNew(new CHoleBSEImg(pHoleBSEImg.get())); // add the new hole BSE image into HoleBSEImage list m_listHoleBSEImg.push_back(pHoleBSEImgNew); } if (m_nWorkingSampeIndex != -1) { COTSSamplePtr pSample = GetWorkingSample(); pSample->SetPropItemGrps(); } } // samples list bool COTSProjMgrFile::SetSysSTDItem(CSTDItemsList& a_listSysSTDItem, BOOL a_bClear/* = TRUE*/) { // clear samples list if necessary if (a_bClear) { m_listSysSTDItem.clear(); } // go through the sample list of the source for (auto pItem : a_listSysSTDItem) { // create a sample copy //CSTDItemPtr pItemNew(new CSTDItem(*pItem.get())); // add the new sample into sample list m_listSysSTDItem.push_back(pItem); } return true; } // file name CString COTSProjMgrFile::GetFileName() { // make a copy of file path name CString strPathName = m_strPathName; // is this a new file? strPathName.Trim(); if (strPathName.CompareNoCase(UNTITLED_FILE_NAME) == 0) { return strPathName; } // get file name CString strFileName = COTSHelper::GetFileNameWithoutExtension(strPathName); strFileName = COTSHelper::GetFileName(strFileName); // return file name return strFileName; } // if the new sample name can be used. BOOL COTSProjMgrFile::IsValidSampleName(CString a_sName) { int nindex = -1; for (auto pSample : m_listSamples) { nindex++; CString sSampleName = pSample->GetName(); if (!a_sName.CompareNoCase(sSampleName)) { if (nindex != m_nWorkingSampeIndex) { LogErrorTrace(__FILE__, __LINE__, _T("This name has been used.")); return FALSE; } } } return TRUE; } // get std file list, a_nPos = -1, current do not use any STD lib, a_nPos = 0, current use STD lib. BOOL COTSProjMgrFile::GetParamFileList(int& a_nPos, std::vector& a_listParamFileName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // get folder name from general GetParamFileListparameter. ASSERT(m_pGenParam); if (!m_pGenParam) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: Can't find the folder.")); return false; } CString a_strFolderName = m_pGenParam->GetMsrParamFileFolderName(); if (a_strFolderName == _T("")) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: empty folder name.")); return false; } // lib name list a_listParamFileName.clear(); // file list std::vector listParamFile; listParamFile.clear(); // get file list if (!COTSHelper::GetFileNameList(a_strFolderName, MESUREMENT_PARAM_FILE_EXT, listParamFile)) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList::There is no %s file in the folder %s"), STD_FILE_EXT, a_strFolderName); return FALSE; } a_nPos = -1; // the first postion is default value CString sDefault; sDefault= MultiLang::GetInstance().GetCStringByKey(IDS_DEFAULT); a_listParamFileName.push_back(sDefault); // get the param CMsrParamFileMgrPtr pParamMrg = CMsrParamFileMgrPtr(new CMsrParamFileMrg()); // get current param CMsrParamsPtr pCurrentParam = CMsrParamsPtr(new CMsrParams()); COTSSamplePtr pSample = GetWorkingSample(); if (pSample == nullptr) { LogTrace(__FILE__, __LINE__, _T("GetParamFileList: failed to get working sample.")); } else { pCurrentParam = pSample->GetMsrParams(); if (pCurrentParam == nullptr) { LogTrace(__FILE__, __LINE__, _T("GetParamFileList: failed to get working sample's param.")); } else { if ((*(pCurrentParam->GetPartSTDData().get()) == *(m_pGenParam->GetPartSTDLib().get())) && (*(pCurrentParam->GetImageProcessParam().get()) == *(m_pImageProcParam.get())) && (*(pCurrentParam->GetImageScanParam().get()) == *(m_pImageScanParam.get())) && (*(pCurrentParam->GetXRayParam().get()) == *(m_pXRayParam.get()))) { a_nPos = 0; } } } int index = -1; for (auto sPathName : listParamFile) { // get file name CString strFileName = COTSHelper::GetFileNameWithoutExtension(sPathName); strFileName = COTSHelper::GetFileName(strFileName); index++; //compare which param is used in the list CString sParamFileName = listParamFile[index]; if (sParamFileName.IsEmpty()) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::wrong param file name.")); return FALSE; } //load STD CString sPathName = a_strFolderName + sParamFileName; if (!pParamMrg->Load(sPathName)) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::can't load param.")); return FALSE; } CMsrParamsPtr pNewParam = pParamMrg->GetMsrParams(); if (*pNewParam.get() == *pCurrentParam.get()) { a_nPos = (index+1); } a_listParamFileName.push_back(strFileName); } return TRUE; } // change param from file BOOL COTSProjMgrFile::ChangeParamFromList(int a_nPos) { // get folder name from general parameter. ASSERT(m_pGenParam); if (!m_pGenParam) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: Can't find the folder.")); return false; } CString a_strFolderName = m_pGenParam->GetMsrParamFileFolderName(); if (a_strFolderName == _T("")) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: empty folder name.")); return false; } // file list std::vector listParamFile; listParamFile.clear(); // get file list if (!COTSHelper::GetFileNameList(a_strFolderName, MESUREMENT_PARAM_FILE_EXT, listParamFile)) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList::There is no %s file in the folder %s"), STD_FILE_EXT, a_strFolderName); return FALSE; } // check the pos if is valid CMsrParamsPtr pNewParam = CMsrParamsPtr(new CMsrParams()); int nSize = (int)listParamFile.size(); if(a_nPos == 0) { //set param to default value CPartSTDDataPtr pPartSTD = m_pGenParam->GetPartSTDLib(); pNewParam->SetPartSTDData(pPartSTD); pNewParam->SetImageScanParam(m_pImageScanParam); pNewParam->SetImageProcessParam(m_pImageProcParam); pNewParam->SetXRayParam(m_pXRayParam); } else if (a_nPos < 0 || a_nPos >(nSize+1)) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::choose wrong position.")); return FALSE; } else { // get the param CMsrParamFileMgrPtr pParamMrg = CMsrParamFileMgrPtr(new CMsrParamFileMrg()); CString sParamFileName = listParamFile[a_nPos-1]; if (sParamFileName.IsEmpty()) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::wrong param file name.")); return FALSE; } //load STD CString sPathName = a_strFolderName + sParamFileName; if (!pParamMrg->Load(sPathName)) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::can't load param.")); return FALSE; } pNewParam = pParamMrg->GetMsrParams(); ASSERT(pNewParam); if (!pNewParam) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::load an empty param.")); return FALSE; } } // updata STD to working sample COTSSamplePtr pSample = GetWorkingSample(); ASSERT(pSample); if (!pSample) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList: failed to get working sample.")); return FALSE; } pSample->SetMsrParams(pNewParam); return TRUE; } // get std file list, a_nPos = -1, current do not use any STD lib, a_nPos = 0, current use STD lib. BOOL COTSProjMgrFile::GetSTDFileList(int& a_nPos, std::vector& a_listSTDLibName) { AFX_MANAGE_STATE(AfxGetStaticModuleState()); // get folder name from general parameter. ASSERT(m_pGenParam); if (!m_pGenParam) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: Can't find the folder.")); return false; } CString a_strFolderName = m_pGenParam->GetPartSTDLibFolderName(); if (a_strFolderName == _T("")) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList: empty folder name.")); return false; } // lib name list a_listSTDLibName.clear(); // file list std::vector listSTDFile; listSTDFile.clear(); // get file list if (!COTSHelper::GetFileNameList(a_strFolderName, STD_FILE_EXT, listSTDFile)) { LogErrorTrace(__FILE__, __LINE__, _T("GetSTDFileList::There is no %s file in the folder %s"), STD_FILE_EXT, a_strFolderName); return FALSE; } //before the use choose one STD, always should be null. a_nPos = -1; // get folder's STD name. CPartSTDFileMnrPtr pPartSTDFileMnr = CPartSTDFileMnrPtr(new CSTDXMLFileMnr()); // get current std CPartSTDDataPtr pCurrentSTD ; CMsrParamsPtr pCurrentParam ; COTSSamplePtr pSample = GetWorkingSample(); if (pSample == nullptr) { LogTrace(__FILE__, __LINE__, _T("GetSTDFileList: failed to get working sample.")); } else { pCurrentParam = pSample->GetMsrParams(); if (pCurrentParam == nullptr) { LogTrace(__FILE__, __LINE__, _T("GetSTDFileList: failed to get working param.")); } pCurrentSTD = pCurrentParam->GetPartSTDData(); CString sDefault = pCurrentSTD->GetName(); a_nPos = 0; a_listSTDLibName.push_back(sDefault); } // read file name int index = -1; for (auto sFileName : listSTDFile) { index++; // read the file CString sPathName = a_strFolderName + sFileName; if (!pPartSTDFileMnr->Load(sPathName)) { LogTrace(__FILE__, __LINE__, _T("GetSTDFileList::There is no %s in the folder %s"), sFileName, a_strFolderName); return FALSE; } // get STDData from file CPartSTDDataPtr pPartSTDData = pPartSTDFileMnr->GetPartSTDData(); ASSERT(pPartSTDData); if (!pPartSTDData) { LogTrace(__FILE__, __LINE__, _T("There is no %s in the folder %s"), sFileName, a_strFolderName); return FALSE; } if (*pCurrentSTD.get() == *pPartSTDData.get()) { a_nPos = (index+1); } // get lib name CString sLibName = pPartSTDData->GetName(); a_listSTDLibName.push_back(sLibName); } return TRUE; } // change STD BOOL COTSProjMgrFile::ChangeSTDFromList(int a_nPos) { // get folder name from general parameter. ASSERT(m_pGenParam); if (!m_pGenParam) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList: Can't find the folder.")); return false; } CString a_strFolderName = m_pGenParam->GetPartSTDLibFolderName(); if (a_strFolderName == _T("")) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList: empty folder name.")); return false; } // file list std::vector listSTDFile; listSTDFile.clear(); // get file list if (!COTSHelper::GetFileNameList(a_strFolderName, STD_FILE_EXT, listSTDFile)) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::There is no %s file in the folder %s"), STD_FILE_EXT, a_strFolderName); return FALSE; } // check the pos if is valid CPartSTDDataPtr pNewSTD = CPartSTDDataPtr(new CPartSTDData()); int nSize = (int)listSTDFile.size(); if (a_nPos == 0) { pNewSTD = m_pGenParam->GetPartSTDLib(); } else if (a_nPos < 0 || a_nPos > nSize) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::choose wrong position.")); return FALSE; } else { // get the STD CPartSTDFileMnrPtr pSTDMnr = CPartSTDFileMnrPtr(new CSTDXMLFileMnr()); CString sSTDFileName = listSTDFile[a_nPos-1]; if (sSTDFileName.IsEmpty()) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::wrong STD file name.")); return FALSE; } //load STD CString sPathName = a_strFolderName + sSTDFileName; if (!pSTDMnr->Load(sPathName)) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::can't load STD.")); return FALSE; } pNewSTD = pSTDMnr->GetPartSTDData(); pNewSTD->SetName(sSTDFileName); ASSERT(pNewSTD); if (!pNewSTD) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList::load an empty STD.")); return FALSE; } } // updata STD to working sample COTSSamplePtr pSample = GetWorkingSample(); ASSERT(pSample); if (!pSample) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList: failed to get working sample.")); return FALSE; } CMsrParamsPtr pParam = pSample->GetMsrParams(); ASSERT(pParam); if (!pParam) { LogErrorTrace(__FILE__, __LINE__, _T("ChangeSTDFromList: working sample's param is empty.")); return FALSE; } pParam->SetPartSTDData(pNewSTD); pSample->SetMsrParams(pParam); return TRUE; } // get measured sample list BOOL COTSProjMgrFile::GetMsredSampleList(COTSSamplesList& a_listMsredSample) { a_listMsredSample.clear(); for (auto pSample : m_listSamples) { if (*(pSample->GetMsrResults().get()) == CMsrResults()) { continue; } else { a_listMsredSample.push_back(pSample);//the reference count will increament automatically. } } return TRUE; } // remove background BOOL COTSProjMgrFile::RemoveBackGround(CBSEImgPtr a_pImgIn, COTSImageProcessParamPtr a_pImgProcessParam, CBSEImgPtr a_pImgOut) { //safety check ASSERT(a_pImgIn); if (!a_pImgIn) { LogTrace(__FILE__, __LINE__, _T("RemoveBackGround: invalid input BSE.")); return FALSE; } ASSERT(a_pImgProcessParam); if (!a_pImgProcessParam) { LogTrace(__FILE__, __LINE__, _T("RemoveBackGround: invalid image process param.")); return FALSE; } ASSERT(a_pImgOut); if (!a_pImgOut) { LogTrace(__FILE__, __LINE__, _T("RemoveBackGround: invalid output BSE.")); return FALSE; } // Binary int nWidth = a_pImgIn->GetWidth(); int nHeight = a_pImgIn->GetHeight(); int nImgSize = nWidth * nHeight; BYTE* pPixel = new BYTE[nImgSize]; BYTE* pSrcImg = a_pImgIn->GetImageDataPointer(); BYTE* pTargetImg = new BYTE[nImgSize]; long nBGStart = a_pImgProcessParam->GetBGGray().GetStart(); long nBGEnd = a_pImgProcessParam->GetBGGray().GetEnd(); long nPtStart = a_pImgProcessParam->GetParticleGray().GetStart(); long nPtEnd = a_pImgProcessParam->GetParticleGray().GetEnd(); // delete background for (int i = 0; i < nImgSize; i++) { if (pSrcImg[i] >= nBGStart && pSrcImg[i] <= nBGEnd) { pPixel[i] = 0; } else { pPixel[i] = 255; } } // image process COTSImageProcess::BErode3(pPixel, pTargetImg, 5, nHeight, nWidth); COTSImageProcess::BDilate3(pTargetImg, pPixel, 5, nHeight, nWidth); // show the image for (int i = 0; i < nImgSize; i++) { *(pPixel + i) = 255 - *(pPixel + i); if (*(pPixel + i) == 0) { *(pPixel + i) = *(pSrcImg + i); } } a_pImgOut->SetImageRect(a_pImgIn->GetImageRect()); a_pImgOut->SetImageData(pPixel); // memory release delete[]pPixel; delete[]pTargetImg; return TRUE; } BOOL COTSProjMgrFile::GetSystemSTDLib(OTS_SOFT_PACKAGE_ID a_nPacketId) { CSTDFileMgrPtr pSTDFileMgr = CSTDFileMgrPtr(new CSTDFileMgr()); // get software pack measure preference file pathname //CString SysSTDLibFilePath = COTSFileSys::GetOTSPackSysSTDLibFilePathName(a_nPacketId); //if (SysSTDLibFilePath.IsEmpty()) //{ // // shouldn't happen, software pack measure preference file pathname is empty, return nullptr // LogErrorTrace(__FILE__, __LINE__, _T("GetSystemSTDLib: failed to find program manager param file pathname.")); // return FALSE; //} // program manager param file exists? /*if (!COTSFileSys::Exists(SysSTDLibFilePath)) { LogErrorTrace(__FILE__, __LINE__, _T("GetSystemSTDLib: there is no STD lib file.")); return FALSE; }*/ CSTDItemsList listSTDItem = pSTDFileMgr->GetSTDItemList(); if (listSTDItem.empty()) { if (!pSTDFileMgr->Load( TRUE)) { LogErrorTrace(__FILE__, __LINE__, _T("GetSystemSTDLib: can't load system STD lib data.")); return FALSE; } } SetSysSTDItem(listSTDItem, TRUE); return TRUE; } // protected // cleanup void COTSProjMgrFile::Cleanup() { m_listHoleBSEImg.clear(); m_listSamples.clear(); m_listSysSTDItem.clear(); m_bModify = FALSE; m_strPathName = _T(""); m_nWorkingSampeIndex = -1; } // initialization void COTSProjMgrFile::Init() { m_pSEMStageData = CSEMStageDataPtr(new CSEMStageData()); m_pStage = CStagePtr(new CStage()); m_pGenParam = COTSGeneralParametersPtr(new COTSGeneralParameters()); m_pImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam()); m_pImageProcParam = COTSImageProcessParamPtr(new COTSImageProcessParam()); m_pXRayParam = COTSXRayParamPtr(new COTSXRayParam()); m_listSamples.clear(); m_listHoleBSEImg.clear(); m_listSysSTDItem.clear(); m_bModify = FALSE; m_strPathName = _T(""); m_nWorkingSampeIndex = -1; } // duplication void COTSProjMgrFile::Duplicate(const COTSProjMgrFile& a_oSource) { // initialization Init(); // copy data over m_pSEMStageData = CSEMStageDataPtr(new CSEMStageData( a_oSource.m_pSEMStageData.get())); m_pStage = CStagePtr(new CStage(a_oSource.m_pStage.get())); m_pGenParam = COTSGeneralParametersPtr(new COTSGeneralParameters( a_oSource.m_pGenParam.get())); m_pImageScanParam = COTSImageScanParamPtr(new COTSImageScanParam( a_oSource.m_pImageScanParam.get())); m_pImageProcParam = COTSImageProcessParamPtr(new COTSImageProcessParam(a_oSource.m_pImageProcParam.get())); m_pXRayParam = COTSXRayParamPtr(new COTSXRayParam(a_oSource.m_pXRayParam.get())); for (auto pHoleBSEImg : a_oSource.m_listHoleBSEImg) { CHoleBSEImgPtr pHoleBSEImgNew(new CHoleBSEImg(pHoleBSEImg.get())); m_listHoleBSEImg.push_back(pHoleBSEImgNew); } for (auto pSample : a_oSource.m_listSamples) { COTSSamplePtr pSampleNew(new COTSSample(pSample.get())); m_listSamples.push_back(pSampleNew); } for (auto pItem : a_oSource.m_listSysSTDItem) { CSTDItemPtr pItemNew = CSTDItemPtr(new CSTDItem(*pItem.get())); m_listSysSTDItem.push_back(pItemNew); } m_bModify = a_oSource.m_bModify; m_strPathName = a_oSource.m_strPathName; m_nWorkingSampeIndex = a_oSource.m_nWorkingSampeIndex; } // get new sample name CString COTSProjMgrFile::GetNewSampleName() { // new sample name CString strNewSmplName = _T(""); // safety check ASSERT(m_pGenParam); if (!m_pGenParam) { // shouldn't happen, invalid general parameter pointer. LogErrorTrace(__FILE__, __LINE__, _T("GetNewSampleName: invalid general parameter pointer.")); return strNewSmplName; } // new sample name base CString strNewSmplNameBase = m_pGenParam->GetSampleName() + _T("%d"); int nIndex = 1; do { // new sample name is new sample name base + number string strNewSmplName.Format(strNewSmplNameBase, nIndex); ++nIndex; } // make sure that the new sample name is not same with any sample in the samples list while (SameNameInList(strNewSmplName)); // new sample name return strNewSmplName; } // select a suitable sample hole for a new sample CHolePtr COTSProjMgrFile::SelectASmpleHole(CString a_strHoleName /*= _T("")*/) { // safety check ASSERT(m_pStage); if (!m_pStage) { // shouldn't happen, invalid stage pointer. LogErrorTrace(__FILE__, __LINE__, _T("COTSProjMgrFile: invalid stage pointer.")); return nullptr; } // get holes list of the stage CHolesList& listHoles = m_pStage->GetHoleList(); // make sure the holes list is not empty if (listHoles.size() == 0) { // shouldn't happen, stage have no hole. LogErrorTrace(__FILE__, __LINE__, _T("COTSProjMgrFile: stage have no hole.")); return nullptr; } // check the input hole name a_strHoleName.Trim(); if (!a_strHoleName.IsEmpty()) { // try to find matched hole auto itr = std::find_if(listHoles.begin(), listHoles.end(), [a_strHoleName](CHolePtr p) { return p->GetName().CompareNoCase(a_strHoleName) == 0; }); if (itr != listHoles.end()) { // found the matched hole, return its pointer CHolePtr pHole = *itr; return pHole; } } // can't find a matched hole, then pick the first empty hole // go through the holes list for (auto pHole : listHoles) { // has this hole any sample in it? CString strHoleName = pHole->GetName(); auto itr = find_if(m_listSamples.begin(), m_listSamples.end(), [strHoleName](COTSSamplePtr p) { return p->GetSampleHoleName().CompareNoCase(strHoleName) == 0; }); if (itr == m_listSamples.end()) { // this hole has no sample in it return pHole; } } // no empty hole, then the first hole will be the one return listHoles[0]; } // calculate measurement area CDomainPtr COTSProjMgrFile::CalculateMsrArea(CHolePtr a_pHole) { // safety check ASSERT(a_pHole); if (!a_pHole) { // input hole invalid. LogErrorTrace(__FILE__, __LINE__, _T("CalculateMsrArea: input hole invalid.")); return nullptr; } CDomainPtr pMsrArea = CDomainPtr(new CDomain(a_pHole->GetShape(), a_pHole->GetDomainRect())); // create measurement area // reset measurement area // measurement area should smaller than the sample hole CRect rectMsrArea = pMsrArea->GetDomainRect(); int nWidth = rectMsrArea.Width(); int nHeight = rectMsrArea.Height(); int nDeflateX = CalculateDeflateValue(nWidth); int nDeflateY = CalculateDeflateValue(nHeight); rectMsrArea.DeflateRect(nDeflateX, nDeflateY); pMsrArea->SetDomainRect(rectMsrArea); // return measurement area return pMsrArea; } CDomainPtr COTSProjMgrFile::CalculateDefaultArea(CHolePtr a_pHole) { // safety check ASSERT(m_pGenParam); if (!m_pGenParam) { // input hole invalid. LogErrorTrace(__FILE__, __LINE__, _T("CalculateDefaultArea: input invalid.")); return nullptr; } ASSERT(a_pHole); if (!a_pHole) { // input hole invalid. LogErrorTrace(__FILE__, __LINE__, _T("CalculateDefaultArea: input hole invalid.")); return nullptr; } CRect rectHole = a_pHole->GetDomainRect(); CPoint ptCenter = rectHole.CenterPoint(); DOMAIN_SHAPE nShape = m_pGenParam->GetShape(); double dArea = m_pGenParam->GetArea() * 1000000; CPoint ptLeftTop; CPoint ptRightBottom; int nEdge = 0; int nRadius = 0; switch ((int)nShape) { case (int)DOMAIN_SHAPE::RECTANGLE: nEdge = (int)sqrt(dArea) / 2; ptLeftTop.x = ptCenter.x - nEdge; ptLeftTop.y = ptCenter.y - nEdge; ptRightBottom.x = ptCenter.x + nEdge; ptRightBottom.y = ptCenter.y + nEdge; break; case (int)DOMAIN_SHAPE::ROUND: nRadius = (int)sqrt(dArea / 3.1415926); ptLeftTop.x = ptCenter.x - nRadius; ptLeftTop.y = ptCenter.y - nRadius; ptRightBottom.x = ptCenter.x + nRadius; ptRightBottom.y = ptCenter.y + nRadius; break; } CRect MsrRect = CRect(ptLeftTop, ptRightBottom); CDomainPtr pMsrArea = CDomainPtr(new CDomain(nShape, MsrRect)); // return measurement area return pMsrArea; } // calculate deflate value int COTSProjMgrFile::CalculateDeflateValue(int a_nWitchOrHeight) { // deflate 1000 if width or height is greater than 15000 if (a_nWitchOrHeight >= LENGTH_THRESHOLD) { return EDGE; } // deflate 500 if width or height is greater than 15000 else if (a_nWitchOrHeight >= LENGTH_THRESHOLD_MIN) { return EDGE_MIN; } // otherwise, no deflate return 0; } }