#pragma once #include "stdafx.h" #include #include #include "SmplMeasure.h" #include "SmplMsrResultFileMgr.h" #include "FieldMgr.h" #include "StageFile.h" namespace OTSMODEL { using namespace OTSDATA; using namespace std; CSmplMeasure::CSmplMeasure() { Init(); } CSmplMeasure::CSmplMeasure(CString a_strWorkingFolder, COTSSamplePtr a_pSample) { m_pMsrThread = nullptr; SetSample(a_pSample); SetWorkingFolder(a_strWorkingFolder); m_pSmplMsrResultFileMgr = CSmplMsrResultFileMgrPtr(new CSmplMsrResultFileMgr(m_strWorkingFolder)); if (!m_pSmplMsrResultFileMgr->Init(m_pSample)) {// failed to initialize measure result file LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: initialize measure result file.")); return; } } CSmplMeasure::~CSmplMeasure() { } void CSmplMeasure::SetSample(COTSSamplePtr a_pSample) { ASSERT(a_pSample); if (!a_pSample) { LogErrorTrace(__FILE__, __LINE__, _T("SetSample: invalid Sample.")); return; } m_pSample = a_pSample; } // measure thread void CSmplMeasure::SetMsrThread(CMsrThread* a_pMsrThread) { ASSERT(a_pMsrThread); if (!a_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("SetMsrThread: invalid thread.")); return; } m_pMsrThread = a_pMsrThread; } void CSmplMeasure::SetWorkingFolder(CString a_strWorkingFolder) { // add "\\" at the string end if it is not "\\" if (a_strWorkingFolder.Right(1) != _T('\\')) { a_strWorkingFolder += _T("\\"); } m_strWorkingFolder = a_strWorkingFolder + m_pSample->GetName() + _T("\\"); } // measurement void CSmplMeasure::DoMeasureOneSample() { ASSERT(m_pSample); // let the main thread to know that this sample measurement starts CMsrSampleStatusPtr pStatus = m_pSample->GetMsrStatus(); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::INPROCESS); // set current time to current time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::START); // let main App know that the sample begin to measure ST_MSTMsg MsgSmpStart; memset(&MsgSmpStart, 0, sizeof(ST_MSTMsg)); MsgSmpStart.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS; MsgSmpStart.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::INPROCESS; memset(MsgSmpStart.STMSampleStu.cSampleName, 0, sizeof(MsgSmpStart.STMSampleStu.cSampleName)); strcpy(MsgSmpStart.STMSampleStu.cSampleName, m_pSample->GetName()); m_pMsrThread->SendMessageToMeasureApp(MsgSmpStart); m_pMsrThread->SendLogMessageToMeasureApp(_T(m_pSample->GetName() + " Measurement started!"), PostLogLevel::info); // get SEM controller to set magnification and working distance if (!SetSEMDataMrs()) { //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM data.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // get SEM external controll on if (!SetSEMExteralOn()) { //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM external.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } m_pMsrThread->SendLogMessageToMeasureApp(_T(" Set External On!"), PostLogLevel::info); // set the BSE scan param if (!SetBSEParam()) { //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set BSE param.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // will be called before quit this method ON_SCOPE_EXIT([&]() {// disconnect hardware SetSEMExteralOff(); ResetScan(); } ); // record SEM working condition CSEMDataGnrPtr pSEMDataGnr = m_pMsrThread->GetSEMDataGnr(); ASSERT(pSEMDataGnr); if (!pSEMDataGnr) { // failed to call RecordSEMCondition method //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call RecordSEMCondition method.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } m_pSmplMsrResultFileMgr->SetSEMGnr(pSEMDataGnr); // record SEM data COTSProjMgrFilePtr pProjMgrFile = m_pMsrThread->GetProjMgrFile(); ASSERT(pProjMgrFile); if (!pProjMgrFile) { // failed to call RecordSEMCondition method //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get project file.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } CSEMStageDataPtr pSEMStageData = pProjMgrFile->GetSEMStageData(); ASSERT(pSEMStageData); if (!pSEMStageData) { // failed to call RecordSEMCondition method //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get SEM data.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } m_pSmplMsrResultFileMgr->SetSEMStageData(pSEMStageData); // record stage CStagePtr pStage = pProjMgrFile->GetStage(); ASSERT(pStage); if (!pStage) {// failed to call RecordSEMCondition method //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to get stage.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } m_pSmplMsrResultFileMgr->SetSEMStage(pStage); // check if sample measurement completes COTSImageScanParamPtr pScanParam = m_pSample->GetMsrParams()->GetImageScanParam(); //int nTotalFieldSize = (int)umMeasuredlistFieldCenter.size(); ASSERT(pScanParam); if (!pScanParam) { //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure:invalid Scan param.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // calculate field centers std::vector umMeasuredlistFieldCenter; //umMeasuredlistFieldCenter.clear(); if (!CalculateUnMeasuredFieldsCenters(umMeasuredlistFieldCenter)) {// failed to calculate field centers //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to calculate field centers.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } //-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database CString strPathName = m_pSmplMsrResultFileMgr->GetPathName(); if (!m_pSmplMsrResultFileMgr->Save(strPathName)) {// failed to call measure result file Save method //LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: failed to call measure result file Save method.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } m_pMsrThread->SendLogMessageToMeasureApp(_T("Created Result File!"), PostLogLevel::info); //------ int nNewFieldId = 0; int numOfAllFields = pStatus->GetCompletedFields() + umMeasuredlistFieldCenter.size();// int completedFields = pStatus->GetCompletedFields(); CString s; s.Format("%d", umMeasuredlistFieldCenter.size()); m_pMsrThread->SendLogMessageToMeasureApp(_T("Unmeasured fields:") + s, PostLogLevel::info); for (int i = 0; i < (int)umMeasuredlistFieldCenter.size(); ++i) {// check and break if stop button is clicked if (IsAborted()) {// measure stopped pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); //must wait for the saving data thread finished,or we'll get null pointer exception when we stop the measure process. while (fieldQueue.size() > 0) { Sleep(100); } return; } if (IsSampleOver(pScanParam, numOfAllFields)) { pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); break; } // get a field center CPoint poiFieldCentre = umMeasuredlistFieldCenter[i]; // update thread measure status class, let the main thread know that starts a new field pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); ST_MSTMsg MsgFieldStart; memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg)); MsgFieldStart.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET::START_MSR_FIELD; MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre; m_pMsrThread->SendMessageToMeasureApp(MsgFieldStart); CString str; str.Format("%d", i+ completedFields+1); m_pMsrThread->SendLogMessageToMeasureApp(_T("Current field:") + str, PostLogLevel::warn); str.Empty(); str.Format("(%d,%d)", poiFieldCentre.x, poiFieldCentre.y); m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to move SEM to ") + str, PostLogLevel::info); // move SEM to the field center if (!MoveSEMToPoint(poiFieldCentre)) {// failed to move SEM to the position pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); continue; } m_pMsrThread->SendLogMessageToMeasureApp(_T("Begin to Acquire BSEImage"), PostLogLevel::info); // take BSE image for the fields CBSEImgPtr pBSEIamge = AcquireABSEImage(); if (pBSEIamge==nullptr) {// failed to acquire a BSE image pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); m_pMsrThread->SendLogMessageToMeasureApp(_T("Failed to Acquire BSEImage"), PostLogLevel::info); continue; } //BSEData ST_MSTMsg MsgFieldBSE; memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg)); MsgFieldBSE.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET::BSE_DATA; MsgFieldBSE.STMSampleRetData.BSEData.pos.x = poiFieldCentre.x; MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y; MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge->GetHeight(); MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge->GetWidth(); BYTE* pImgData = pBSEIamge->GetImageDataPointer(); MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData; m_pMsrThread->SendMessageToMeasureApp(MsgFieldBSE); m_pMsrThread->SendLogMessageToMeasureApp(_T("Acquire BSE image success! Processing Image....."), PostLogLevel::info); // get a new field id nNewFieldId = m_pSmplMsrResultFileMgr->GetIdForANewField(nNewFieldId); // create a field COTSFieldDataPtr pNewFieldData = COTSFieldDataPtr(new COTSFieldData()); pNewFieldData->SetId(nNewFieldId); pNewFieldData->SetPosition(poiFieldCentre); pNewFieldData->SetFieldFileFolder(m_pSmplMsrResultFileMgr->GetFieldFileSubFolderStr()); // image process try { ImageProcess(pNewFieldData, pBSEIamge); } catch (...) {// catch an exception when call AcquireBSEImage method m_pMsrThread->SendLogMessageToMeasureApp(_T("Image process failed."), PostLogLevel::warn); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); continue; } // is the field data empty if (!pNewFieldData->IsEmpty()) { // add the field into the field m_pSmplMsrResultFileMgr->AddAField(pNewFieldData); } // prepare for the next ++nNewFieldId; // completed fields pStatus->SetCompletedFields(pStatus->GetCompletedFields() + 1); // completed fieldCenter std::vector& listCpltedCenter = pStatus->GetCompletedFieldsCenter(); listCpltedCenter.push_back(poiFieldCentre); m_pMsrThread->SendLogMessageToMeasureApp(_T("Send result to the screen!"), PostLogLevel::info); //Field Data // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); ST_MSTMsg MsgFieldEnd; memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg)); MsgFieldEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET::FIELD_DATA; MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = pStatus->GetCompletedFields(); MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = numOfAllFields; MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = (int)pNewFieldData->GetParticleList().size(); MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.x = poiFieldCentre.x; MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.y = poiFieldCentre.y; m_pMsrThread->SendMessageToMeasureApp(MsgFieldEnd); pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); } while (fieldQueue.size() > 0)//wait untill all the field data has been saved. { Sleep(100); } //calculate measure time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::SUCCESSED); // let main thread to know that this sample measurement completes ST_MSTMsg MsgSmplEnd; memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg)); MsgSmplEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS; MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED; memcpy(MsgSmplEnd.STMSampleStu.cSampleName, m_pSample->GetName(), sizeof(m_pSample->GetName())); m_pMsrThread->SendMessageToMeasureApp(MsgSmplEnd); return; } // hole preview void CSmplMeasure::DoHolePreviewOneSample(int a_nHoleID) {// safety check ASSERT(m_pSample); // let the main thread to know that this sample measurement starts CMsrSampleStatusPtr pStatus = m_pSample->GetMsrStatus(); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::INPROCESS); // set current time to current time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::START); // let main App know that the sample begin to measure ST_MSTMsg MsgSmpStart; memset(&MsgSmpStart, 0, sizeof(ST_MSTMsg)); MsgSmpStart.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS; MsgSmpStart.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::INPROCESS; memset(MsgSmpStart.STMSampleStu.cSampleName, 0, sizeof(MsgSmpStart.STMSampleStu.cSampleName)); strcpy(MsgSmpStart.STMSampleStu.cSampleName, m_pSample->GetName()); // get SEM controller to set magnification and working distance if (!SetSEMDataMrs()) { LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: fail to set SEM data.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // get SEM external controll on if (!SetSEMExteralOn()) { LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set SEM external.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // set the BSE scan param if (!SetBSEParam()) { LogErrorTrace(__FILE__, __LINE__, _T("DoMeasure: fail to set BSE param.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // will be called before quit this method ON_SCOPE_EXIT([&]() {// disconnect hardware SetSEMExteralOff(); ResetScan(); } ); // check if measurement is aborted if (IsAborted()) {// measurement aborted LogTrace(__FILE__, __LINE__, _T("DoHolePreview: measurement aborted before get SEM condition.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // calculate field centers std::vector listFieldCenter; listFieldCenter.clear(); if (!CalculateUnMeasuredFieldsCenters(listFieldCenter)) {// failed to calculate field centers LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to calculate field centers.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // go through each field int nNewFieldId = 0; for (int i = 0; i < (int)listFieldCenter.size(); ++i) {// check and break if stop button is clicked if (IsAborted()) {// measure stopped LogTrace(__FILE__, __LINE__, _T("DoHolePreview: measure thread is stopped.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::STOPPED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // check if sample measurement completes COTSImageScanParamPtr pScanParam = m_pSample->GetMsrParams()->GetImageScanParam(); int nTotalFieldSize = (int)listFieldCenter.size(); ASSERT(pScanParam); if (!pScanParam) { LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview:invalid Scan param.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } if (IsSampleOver(pScanParam, nTotalFieldSize)) { pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); break; } // get a field center CPoint poiFieldCentre = listFieldCenter[i]; LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 1: field %d begin."), i); // update thread measure status class, let the main thread know that starts a new field pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); ST_MSTMsg MsgFieldStart; memset(&MsgFieldStart, 0, sizeof(ST_MSTMsg)); MsgFieldStart.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET::START_MSR_FIELD; MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre; LogInfoTrace(__FILE__, __LINE__, _T("Message :DoHolePreview: field %d measure begin. message type is %d"), i, MsgFieldStart.iMsgType); m_pMsrThread->SendMessageToMeasureApp(MsgFieldStart); // move SEM to the field center if (!MoveSEMToPoint(poiFieldCentre)) {// failed to move SEM to the position LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to move SEM to the field centre point.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } // take BSE image for the fields CBSEImgPtr pBSEIamge = AcquireABSEImage(); if (!pBSEIamge) { // failed to acquire a BSE image LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: failed to acquire a BSE image.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } //BSEData ST_MSTMsg MsgFieldBSE; memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg)); MsgFieldBSE.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET::BSE_DATA; MsgFieldBSE.STMSampleRetData.BSEData.pos.x = poiFieldCentre.x; MsgFieldBSE.STMSampleRetData.BSEData.pos.y = poiFieldCentre.y; MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight = pBSEIamge->GetHeight(); MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth = pBSEIamge->GetWidth(); BYTE* pImgData = pBSEIamge->GetImageDataPointer(); MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData; //MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = new BYTE[MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth]; //memcpy(MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData, pImgData, sizeof(BYTE)*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataHeight*MsgFieldBSE.STMSampleRetData.BSEData.iBSEDataWidth); LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 4: OTS position x is %d, y is %d is sent in the message."), poiFieldCentre.x, poiFieldCentre.y); LogInfoTrace(__FILE__, __LINE__, _T("Message : ImageProcess: send BSE data. message type is %d"), MsgFieldBSE.iMsgType); m_pMsrThread->SendMessageToMeasureApp(MsgFieldBSE); if (pStatus->GetStatus() != OTS_MSR_SAMPLE_STATUS::INPROCESS) { // measurement failed or stopped LogErrorTrace(__FILE__, __LINE__, _T("DoHolePreview: measurement failed or stopped.")); pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::FAILED); // record end time pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); return; } //save the result to project file CHoleBSEImgPtr pHoleBSEImg = CHoleBSEImgPtr(new CHoleBSEImg()); pHoleBSEImg->SetHoleID(a_nHoleID); pHoleBSEImg->SetPosition(poiFieldCentre); CRect oImageRect = pBSEIamge->GetImageRect(); long nImageSize = pBSEIamge->GetHeight() * pBSEIamge->GetWidth(); pHoleBSEImg->SetImageRect(oImageRect); memcpy(pHoleBSEImg->GetImageDataPointer(), pBSEIamge->GetImageDataPointer(), sizeof(BYTE)*nImageSize); m_listHoleBSEImg.push_back(pHoleBSEImg); COTSProjMgrFilePtr pProjMgrFile = m_pMsrThread->GetProjMgrFile(); pProjMgrFile->SetHoleBESImgList(m_listHoleBSEImg); // prepare for the next ++nNewFieldId; pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); ST_MSTMsg MsgFieldEnd; memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg)); MsgFieldEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLERESULT; MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET::FIELD_DATA; MsgFieldEnd.STMSampleRetData.SFieldData.iCompleteFieldCount = (i + 1); MsgFieldEnd.STMSampleRetData.SFieldData.iMeasureFieldCount = (int)listFieldCenter.size(); MsgFieldEnd.STMSampleRetData.SFieldData.iSParticleCount = 0; MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.x = poiFieldCentre.x; MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.y = poiFieldCentre.y; LogInfoTrace(__FILE__, __LINE__, _T("Message: DoHolePreview: field %d measure end. message type is %d"), i, MsgFieldEnd.iMsgType); m_pMsrThread->SendMessageToMeasureApp(MsgFieldEnd); } pStatus->ComputeTime(OTS_MSR_TIME_TYPE::STOPPED); //calculate measure time pStatus->SetStatus(OTS_MSR_SAMPLE_STATUS::SUCCESSED); // let main thread to know that this sample measurement completes ST_MSTMsg MsgSmplEnd; memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg)); MsgSmplEnd.iMsgType = ENUM_MSG_TYPE::MSAMPLESTATUS; MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS::SUCCESSED; memcpy(MsgSmplEnd.STMSampleStu.cSampleName, m_pSample->GetName(), sizeof(m_pSample->GetName())); LogInfoTrace(__FILE__, __LINE__, _T("Message : DoHolePreview: sample %s end. message type is %d"), m_pSample->GetName(), MsgSmplEnd.iMsgType); m_pMsrThread->SendMessageToMeasureApp(MsgSmplEnd); } // hole BSE images list void CSmplMeasure::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) {// add the new hole BSE image into HoleBSEImage list m_listHoleBSEImg.push_back(pHoleBSEImg); } } // samples list bool CSmplMeasure::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 // add the new sample into sample list m_listSysSTDItem.push_back(pItem); } return true; } BOOL CSmplMeasure::IsSampleOver(COTSImageScanParamPtr a_pScanParam, int a_nTotalFields) { ASSERT(a_pScanParam); if (!a_pScanParam) { LogErrorTrace(__FILE__, __LINE__, _T("IsSampleOver: invalid sample scan param.")); return FALSE; } int nStopMode = (int)a_pScanParam->GetStopMode(); int nStopField = a_pScanParam->GetStopParamFields(); // completed fields number CMsrSampleStatusPtr pMsrSampleStatus = m_pSample->GetMsrStatus(); int nCompeltedField = pMsrSampleStatus->GetCompletedFields(); CMsrResultsPtr pMsrResults = m_pSample->GetMsrResults(); CMsrResultItemsList listMsrResult = pMsrResults->GetResultItems(); int nNumParticle = 0; for (auto pResult : listMsrResult) { if (pResult->GetTypeId() >(int) OTS_PARTCLE_TYPE::NO_ANALYSIS_X_RAY)//summarize the number of the identified particle in this condition { nNumParticle += pResult->GetNumber(); } } COleDateTimeSpan timeSpan = pMsrSampleStatus->GetUsedTime(); int nDay = timeSpan.GetDays(); int nHour = timeSpan.GetHours(); int nMin = timeSpan.GetMinutes(); int nSec = timeSpan.GetSeconds(); int nUsedTime = nSec + nMin * 60 + nHour * 3600 + nDay * 86400; int nParticlAim = a_pScanParam->GetStopParamParticles(); int nMeasTimeAim = a_pScanParam->GetStopParamMeasTime(); BOOL bRet = TRUE; switch(nStopMode) { case (int)OTS_MEASURE_STOP_MODE::CoverMode: // completed fields number if (nCompeltedField < a_nTotalFields ) { LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished.")); bRet = FALSE; } break; case (int)OTS_MEASURE_STOP_MODE::FieldMode: if (nCompeltedField < nStopField) { LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished.")); bRet = FALSE; } break; case (int)OTS_MEASURE_STOP_MODE::ParticleMode: if (nNumParticle < nParticlAim) { LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished.")); bRet = FALSE; } break; case (int)OTS_MEASURE_STOP_MODE::TimeMode: if (nUsedTime < nMeasTimeAim) { LogInfoTrace(__FILE__, __LINE__, _T("IsSampleOver: sample measure has not finished.")); bRet = FALSE; } break; default: break; } return bRet; } BOOL CSmplMeasure::SetPrjFileSave() { ASSERT(m_pMsrThread); if (!m_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("SetPrjFileSave: thread is null.")); return FALSE; } COTSProjMgrFilePtr pProjMgr = m_pMsrThread->GetProjMgrFile(); ASSERT(pProjMgr); if (!pProjMgr) { LogErrorTrace(__FILE__, __LINE__, _T("SetPrjFileSave: thread is null.")); return FALSE; } pProjMgr->SetModify(TRUE); return TRUE; } BOOL CSmplMeasure::SetSEMDataMrs() { ASSERT(m_pSample); if (!m_pSample) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: prject sample is empty.")); return FALSE; } CSEMDataMsrPtr pSEMDataMsr = m_pSample->GetSEMDataMsr(); ASSERT(pSEMDataMsr); if (!pSEMDataMsr) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: failed to get SEM measure data.")); return FALSE; } if (*pSEMDataMsr.get() == CSEMDataMsr()) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: SEM measure data is empty.")); return FALSE; } double dMag = pSEMDataMsr->GetMagnification(); double dWorkDis = pSEMDataMsr->GetWorkingDistance(); CSemBasePtr pSEMCtrlPtr = GetSEMControl(); ASSERT(pSEMCtrlPtr); if (!pSEMCtrlPtr) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: failed to get SEM controller.")); return FALSE; } // get SEM controller if (!pSEMCtrlPtr->IsConnected()) { if (!pSEMCtrlPtr->Connect()) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMDataMrs: can't connect SEM.")); return FALSE; } } //LogInfoTrace(__FILE__, __LINE__, _T("SetSEMDataMrs:set mag and dis")); m_pMsrThread->SendLogMessageToMeasureApp("Set mag and dis", PostLogLevel::info); pSEMCtrlPtr->SetMagnification(dMag); pSEMCtrlPtr->SetWorkingDistance(dWorkDis); //LogInfoTrace(__FILE__, __LINE__, _T("SetSEMDataMrs:set mag and dis is over")); return TRUE; } // set SEM external on BOOL CSmplMeasure::SetSEMExteralOn() { CSemBasePtr pSEMCtrlPtr = m_pMsrThread->GetSEMController(); ASSERT(pSEMCtrlPtr); if (!pSEMCtrlPtr) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOn: failed to get SEM controller.")); return FALSE; } // get SEM controller if (!pSEMCtrlPtr->IsConnected()) { if (!pSEMCtrlPtr->Connect()) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOn: can't connect SEM.")); return FALSE; } } pSEMCtrlPtr->SetScanExternal(TRUE); return TRUE; } // set SEM external off BOOL CSmplMeasure::SetSEMExteralOff() { CSemBasePtr pSEMCtrlPtr = m_pMsrThread->GetSEMController(); ASSERT(pSEMCtrlPtr); if (!pSEMCtrlPtr) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOff: failed to get SEM controller.")); return FALSE; } // get SEM controller if (!pSEMCtrlPtr->IsConnected()) { if (!pSEMCtrlPtr->Connect()) { LogErrorTrace(__FILE__, __LINE__, _T("SetSEMExteralOff: can't connect SEM.")); return FALSE; } } pSEMCtrlPtr->SetScanExternal(FALSE); m_pMsrThread->SendLogMessageToMeasureApp(_T("Set External Off!"), PostLogLevel::info); return TRUE; } // set BSE param BOOL CSmplMeasure::SetBSEParam() { ASSERT(m_pSample); if (!m_pSample) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: prject sample is empty.")); return FALSE; } // get SEM controller CSemBasePtr pSEMController = GetSEMControl(); if (!pSEMController) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get SEM control.")); return FALSE; } // get scan controller COTSScanBasePtr pScanController = GetScanControl(); if (!pScanController) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control.")); return FALSE; } // scan parameters CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams(); COTSImageScanParamPtr pImgScanParam = pMsrParam->GetImageScanParam(); // get image size OTS_FIVE_TIES_OPTIONS nImageSizeId = pImgScanParam->GetImagePixelSize(); int nResulotionId = RESOLUTION_ID_FIRST_TIE + (int)nImageSizeId; CSize sizePixelImage = RESOLUTION_VALUE[nResulotionId]; // get SEM controller if (!pSEMController->IsConnected()) { if (!pSEMController->Connect()) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: can't connect SEM.")); return FALSE; } } // get scan field size double dScanFieldSizeX = sizePixelImage.cx; double dScanFieldSizeY = sizePixelImage.cy; if (!pSEMController->GetScanFieldSize(dScanFieldSizeX, dScanFieldSizeY)) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to call GetScanFieldSize method.")); return FALSE; } // get dwell time OTS_THREE_TIES_OPTIONS nDwellTime = pImgScanParam->GetScanImageSpeed(); // convert dwell time to bruker dwell time (6, 16, 32) long nBrukerDwellTimeId = DWELLTIME_BRUKER_ID_THREE_TIE_MIN + (int)nDwellTime; long nBrukerDwellTime = DWELLTIME_BRUKER_VALUES[nBrukerDwellTimeId]; if (!pScanController->Init()) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control.")); return FALSE; } // set dwell time if (!pScanController->SetDwellTime(nBrukerDwellTime)) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to set dwell time (%d) for bruker system."), nBrukerDwellTime); return FALSE; } // set image size if (!pScanController->SetImageSize(sizePixelImage.cx)) { // failed to set dwell time LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to set dwell time (%d)."), sizePixelImage.cx); return FALSE; } return TRUE; } // reset Scan BOOL CSmplMeasure::ResetScan() { // get scan controller COTSScanBasePtr pScanController = GetScanControl(); if (!pScanController) { LogErrorTrace(__FILE__, __LINE__, _T("SetBSEParam: failed to get scan control.")); return FALSE; } // reset Scanner if (!pScanController->SetAndStartScan()) { LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: failed to call SetAndStartScan method.")); return FALSE; } m_pMsrThread->SendLogMessageToMeasureApp(_T("Reset Scan!"), PostLogLevel::info); return true; } // initialization void CSmplMeasure::Init() { m_pMsrThread = nullptr; m_strWorkingFolder = _T(""); } // check if measurement is aborted BOOL CSmplMeasure::IsAborted() { ASSERT(m_pMsrThread); return m_pMsrThread->IsMeasureStopped(); } // hardware control CSemBasePtr CSmplMeasure::GetSEMControl() { // SEM controller CSemBasePtr pSEMController = nullptr; // safety check ASSERT(m_pMsrThread); if (!m_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("GetSEMControl: invalid measure thread pointer.")); return pSEMController; } // get SEM controller pSEMController = m_pMsrThread->GetSEMController(); // return SEM controller return pSEMController; } COTSScanBasePtr CSmplMeasure::GetScanControl() { // scan controller COTSScanBasePtr pScanController = nullptr; // safety check ASSERT(m_pMsrThread); if (!m_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("GetScanControl: invalid measure thread pointer.")); return pScanController; } // get scan controller pScanController = m_pMsrThread->GetScanController(); // return scan controller return pScanController; } COTSEDSBasePtr CSmplMeasure::GetEDSControl() { // EDS controller COTSEDSBasePtr pEDSController = nullptr; // safety check ASSERT(m_pMsrThread); if (!m_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("GetEDSControl: invalid measure thread pointer.")); return pEDSController; } // get EDS controller pEDSController = m_pMsrThread->GetEDSController(); // return EDS controller return pEDSController; } // get SEM condition (general) BOOL CSmplMeasure::RecordSEMCondition(CSEMDataGnrPtr a_pSEMDataGnr) { // safety check ASSERT(a_pSEMDataGnr); if (!a_pSEMDataGnr) { LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: invalid input pointer.")); return FALSE; } // get SEM controller CSemBasePtr pSEMCotroller = GetSEMControl(); ASSERT(pSEMCotroller); if (!pSEMCotroller) { LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: failed to get SEM controller.")); return FALSE; } // get SEM condition (general) if (!pSEMCotroller->GetSEMDataGnr(a_pSEMDataGnr)) { LogErrorTrace(__FILE__, __LINE__, _T("RecordSEMCondition: failed to call GetSEMDataGnr method.")); return FALSE; } // ok, return TRUE return TRUE; } // calculate field centers BOOL CSmplMeasure::CalculateUnMeasuredFieldsCenters(std::vector& a_listFieldCenter) { // safety check ASSERT(m_pSample); // sample measure parameters CMsrParamsPtr pMsrParam = m_pSample->GetMsrParams(); COTSImageScanParamPtr poImageScanParam = pMsrParam->GetImageScanParam(); CSEMDataMsrPtr poSEMDataMsr = m_pSample->GetSEMDataMsr(); CMsrSampleStatusPtr pMsrStatus = m_pSample->GetMsrStatus(); // measured field centers list std::vector& listCompletedCenter = pMsrStatus->GetCompletedFieldsCenter(); // field centers list manager CFieldMgrPtr pFieldMgr = CFieldMgrPtr(new CFieldMgr()); // init field centers list manager if (!pFieldMgr->Init(m_pSample->GetMsrArea(), poImageScanParam, poSEMDataMsr, listCompletedCenter)) { LogErrorTrace(__FILE__, __LINE__, _T("CalculateFieldsCenters: failed to init field centres list manager.")); return FALSE; } // get field centers list a_listFieldCenter = pFieldMgr->GetUnmeasuredFieldCentrePoints();// GetFieldCentrePoints(); // ok, return TRUE return TRUE; } // move SEM to the point BOOL CSmplMeasure::MoveSEMToPoint(CPoint a_poi) { /*Sleep(500);*/ // get SEM controller CSemBasePtr pSEMController = GetSEMControl(); ASSERT(pSEMController); if (!pSEMController) { // failed to get SEM control LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: failed to get SEM control.")); return FALSE; } CPoint a_SEMpt; CStageFilePtr pStageFile = CStageFilePtr(new CStageFile()); CSEMStageDataPtr a_pCSEMStageData = m_pMsrThread->GetProjMgrFile()->GetSEMStageData(); pStageFile->SetStageData(a_pCSEMStageData); //LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 2: OTS position x is %d, y is %d."), a_poi.x, a_poi.y); if (!pStageFile->ConverOTSToSEMPoint(a_poi, a_SEMpt)) { return FALSE; } //LogErrorTrace(__FILE__, __LINE__, _T("C++ Position Message 3: SEM position x is %d, y is %d."), a_SEMpt.x, a_SEMpt.y); if (!pSEMController->IsConnected()) { if (!pSEMController->Connect()) { LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: can't connect SEM.")); return FALSE; } } // move SEM to the position (rotation 0) if (!pSEMController->MoveSEMToPoint(a_SEMpt, 0)) { LogErrorTrace(__FILE__, __LINE__, _T("MoveSEMToPoint: failed to call MoveSEMToPoint method.")); return FALSE; } //Sleep(500); return TRUE; } // Acquire a BSE image CBSEImgPtr CSmplMeasure::AcquireABSEImage() { // BSE image CBSEImgPtr pBSEImage = nullptr; // safety check ASSERT(m_pSample); if (!m_pSample) { LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: invalid sample pointer.")); return FALSE; } // get scan controller COTSScanBasePtr pScanController = GetScanControl(); if (!pScanController) { LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: failed to get scan control.")); return pBSEImage; } try { pBSEImage = pScanController->AcquireBSEImage(0, 0, 2); if (pBSEImage==nullptr) { return nullptr; //LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: the BSE image is invalid.")); } } catch (...) { //LogErrorTrace(__FILE__, __LINE__, _T("AcquireABSEImage: catch an exception when call AcquireBSEImage method.")); return nullptr; } return pBSEImage; } // get x-ray acquire time BOOL CSmplMeasure::GetXRayAcquireTime(XRAY_TYPE a_nXrayType, OTS_THREE_TIES_OPTIONS a_nXraySpeed, DWORD& a_nXRayAQTime) { // safety check ASSERT(m_pMsrThread); if (!m_pMsrThread) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: invalid thread pointer.")); return FALSE; } // get project manager file COTSProjMgrFilePtr pOTSProjMgrFile = m_pMsrThread->GetProjMgrFile(); ASSERT(pOTSProjMgrFile); if (!pOTSProjMgrFile) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: failed to get project manager file.")); return FALSE; } // x-ray parameters COTSXRayParamPtr pXRayParam = pOTSProjMgrFile->GetXRayParam(); ASSERT(pXRayParam); if (!pXRayParam) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayAcquireTime: failed to get x-ray parameters.")); return FALSE; } a_nXRayAQTime = (DWORD)pXRayParam->GetMidAnalyAQTime(); // ok, return TRUE return TRUE; } // get x-rays BOOL CSmplMeasure::GetXRayByPoints(CPosXraysList& a_listPosXRay, DWORD a_nXRayAQTime, BOOL a_bElementInfo /*= FALSE*/) { // get EDS controller COTSEDSBasePtr pEDSController = GetEDSControl(); ASSERT(pEDSController); if (!pEDSController) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get EDS controller.")); return FALSE; } // init EDS controller if (!pEDSController->Init()) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to inti EDS (%s)."), pEDSController->GetName()); return FALSE; } //// set get quantify info flag, firstly only get x-ray data if (!a_bElementInfo) { pEDSController->SetQuantification(FALSE); } else { // get element, because only the first point can get element pEDSController->SetQuantification(TRUE); } int nSize = (int)a_listPosXRay.size(); if (nSize > 1024) { m_pMsrThread->SendLogMessageToMeasureApp(_T("Too many point Xray! Divide into multi times!"), PostLogLevel::error); int nTimes = nSize / 1024; CPosXraysList listPosXRayTemp; for (int i = 0; i < nTimes; i++) { listPosXRayTemp.clear(); for (int m = 0; m < 1024; m++) { listPosXRayTemp.push_back(a_listPosXRay[i * 1024 + m]); } if (!pEDSController->GetXRayByPoints(listPosXRayTemp, a_nXRayAQTime)) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element.")); return FALSE; } } int nLast = nSize % 1024; if (nLast != 0) { listPosXRayTemp.clear(); for (int m = 0; m < nLast; m++) { listPosXRayTemp.push_back(a_listPosXRay[nTimes * 1024 + m]); } if (!pEDSController->GetXRayByPoints(listPosXRayTemp, a_nXRayAQTime)) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element.")); return FALSE; } } } else { if (!pEDSController->GetXRayByPoints(a_listPosXRay, a_nXRayAQTime)) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByPoints: failed to get element.")); return FALSE; } } // ok, return TRUE return TRUE; } BOOL CSmplMeasure::GetXRayByFeatures(COTSParticleList& a_listParticles, CPosXraysList& a_listPosXRay, DWORD a_nXRayAQTime, BOOL a_bElementInfo /*= FALSE*/) { // get EDS controller COTSEDSBasePtr pEDSController = GetEDSControl(); ASSERT(pEDSController); if (!pEDSController) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to get EDS controller.")); return FALSE; } // get out if particles list is empty if (a_listParticles.size() == 0) { return TRUE; } // init EDS controller if (!pEDSController->Init()) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to inti EDS (%s)."), pEDSController->GetName()); return FALSE; } // set get quantify info flag pEDSController->SetQuantification(a_bElementInfo); int nSize = (int)a_listParticles.size(); if (nSize > 512) { m_pMsrThread->SendLogMessageToMeasureApp(_T("Too many feature Xray! Divide into multi times!"), PostLogLevel::error); } int nTimes = nSize / 512; int nLast = nSize % 512; if (nLast != 0) { nTimes += 1; } COTSParticleList listPartTemp; CPosXraysList listPosXRayTemp; for (int i = 0; i < nTimes; i++) { listPartTemp.clear(); listPosXRayTemp.clear(); for (int m = 0; m < 512; m++) { if (i * 512 + m < nSize) { listPartTemp.push_back(a_listParticles[i * 512 + m]); listPosXRayTemp.push_back(a_listPosXRay[i * 512 + m]); } else { break; } } // get the features list of the particles std::vector> listBrukerFeatures;//covert these particles into brukerfeatures. for (auto pPart : listPartTemp) { auto pFeature = pPart->GetFeature(); COTSSegmentsList listSegment = pFeature->GetSegmentsList(); std::vector listBrukSegment; for (auto Segment : listSegment) { BrukerSegment BrukSeg; BrukSeg.XCount = Segment->GetLength(); BrukSeg.Y = Segment->GetHeight(); BrukSeg.XStart = Segment->GetStart(); listBrukSegment.push_back(BrukSeg); } listBrukerFeatures.push_back(listBrukSegment); } if (listPosXRayTemp.size() > 0) { if (!pEDSController->GetXRayByFeatures(listPosXRayTemp, listBrukerFeatures, a_nXRayAQTime)) { LogErrorTrace(__FILE__, __LINE__, _T("GetXRayByFeatures: failed to get xray by features.")); return FALSE; } } } return TRUE; } // get pixel size BOOL CSmplMeasure::GetPixelSize(double& a_dPixelSize) { // safety check ASSERT(m_pSample); if (!m_pSample) { LogErrorTrace(__FILE__, __LINE__, _T("GetPixelSize: invalid sample pointer.")); return FALSE; } a_dPixelSize = m_pSample->CalculatePixelSize(); return TRUE; } // save a field BOOL CSmplMeasure::SaveSampleFile() { // save the file CString strPathName = m_pSmplMsrResultFileMgr->GetPathName(); if (!m_pSmplMsrResultFileMgr->Save(strPathName)) { // failed to save the file LogErrorTrace(__FILE__, __LINE__, _T("SaveAField: failed to save the file.")); return FALSE; } // ok, return TRUE return TRUE; } }