|
@@ -0,0 +1,531 @@
|
|
|
+using System.Collections.Generic;
|
|
|
+using OTSDataType;
|
|
|
+using System;
|
|
|
+using System.Drawing;
|
|
|
+using static OTSDataType.otsdataconst;
|
|
|
+
|
|
|
+using OTSModelSharp.ImageProcess;
|
|
|
+using OTSModelSharp.ServiceInterface;
|
|
|
+
|
|
|
+namespace OTSModelSharp
|
|
|
+{
|
|
|
+
|
|
|
+
|
|
|
+ // enum and struct used for send message to App
|
|
|
+ public enum ENUM_MSG_TYPE
|
|
|
+ {
|
|
|
+ MTHREADSTATUS = 1001,
|
|
|
+ MSAMPLESTATUS = 1002,
|
|
|
+ MSAMPLERESULT = 1003
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ public enum MSAMPLE_RET
|
|
|
+ {
|
|
|
+ BSE_DATA = 0,
|
|
|
+ FIELD_DATA = 1,
|
|
|
+ START_MSR_FIELD = 2
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ public struct SMSR_COMPLETE_DATA
|
|
|
+ {
|
|
|
+ public OTS_MSR_THREAD_STATUS MsrStatus;
|
|
|
+ public string csMsrStartTime;
|
|
|
+ public int iMsrCompleteSampleCount;
|
|
|
+ public int iMsrCompleteFieldCount;
|
|
|
+ public int iParticleCount;
|
|
|
+ public TimeSpan MsrUsedTime;
|
|
|
+ public string csMsrEndTime;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ public struct STMThreadStatus
|
|
|
+ {
|
|
|
+ public OTS_MSR_THREAD_STATUS iMsrStatu; //OTS_MSR_THREAD_STATUS
|
|
|
+ public string csMsrStartTime; //MSR_START_TIME
|
|
|
+ public string csMsrEndTime; //MSR_END_TIME
|
|
|
+ public SMSR_COMPLETE_DATA SMsrCompleteData;
|
|
|
+ };
|
|
|
+ public struct STMSampleStatus
|
|
|
+ {
|
|
|
+ public OTS_MSR_SAMPLE_STATUS iMsrSampleStatu; //OTS_MSR_SAMPLE_STATUS
|
|
|
+ public string cSampleName;
|
|
|
+ public string csSampleMsrStartTime;
|
|
|
+ public List<Point> BCompleteFieldList;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ public struct STMSampleResultData
|
|
|
+ {
|
|
|
+ public MSAMPLE_RET iRetDataType; //ENUM_MEASURE_SAMPLE_RESULT
|
|
|
+
|
|
|
+ public struct RBSEDATA
|
|
|
+ {
|
|
|
+
|
|
|
+ public System.Drawing.Point pos;
|
|
|
+ public int iBSEDataHeight;
|
|
|
+ public int iBSEDataWidth;
|
|
|
+ public byte[] lpBSEData;
|
|
|
+ };
|
|
|
+
|
|
|
+ public struct SAMPLEFIELDDATA
|
|
|
+ {
|
|
|
+ public System.Drawing.Point FieldPos;
|
|
|
+ public int iMeasureFieldCount;
|
|
|
+ public int iCompleteFieldCount;
|
|
|
+ public int iSParticleCount; // Field particle count
|
|
|
+ public TimeSpan TUsedTime;
|
|
|
+ };
|
|
|
+
|
|
|
+ public struct StartToMsrField
|
|
|
+ {
|
|
|
+ public System.Drawing.Point FieldPos;
|
|
|
+ };
|
|
|
+
|
|
|
+ public RBSEDATA BSEData;
|
|
|
+ public SAMPLEFIELDDATA SFieldData;
|
|
|
+ public StartToMsrField SMsrField;
|
|
|
+ };
|
|
|
+
|
|
|
+ public struct ST_MSTMsg
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ public ENUM_MSG_TYPE iMsgType;
|
|
|
+ public STMThreadStatus STMThreadStu;
|
|
|
+ public STMSampleStatus STMSampleStu;
|
|
|
+ public STMSampleResultData STMSampleRetData;
|
|
|
+
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ public class CMeasure
|
|
|
+ {
|
|
|
+
|
|
|
+ private const string UNTITLED_FILE_NAME = "Untitled";
|
|
|
+ public delegate void ProgressEventHandler(ST_MSTMsg msg);
|
|
|
+ public event ProgressEventHandler ProgressEvent;
|
|
|
+ COTSMsrPrjResultData m_pProjData;
|
|
|
+ List< COTSSample> m_listMeasurableSamples;
|
|
|
+ string m_strWorkingFolder;
|
|
|
+ CMsrThreadStatus m_ThreadStatus;
|
|
|
+
|
|
|
+
|
|
|
+ SemController m_SemController;// there is no correspondense clr,so use this instead temporarilly
|
|
|
+ protected static NLog.Logger loger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
+
|
|
|
+
|
|
|
+ public CMeasure()
|
|
|
+ {
|
|
|
+ m_strWorkingFolder = "";
|
|
|
+ m_ThreadStatus = new CMsrThreadStatus();
|
|
|
+
|
|
|
+
|
|
|
+ m_SemController = new SemController();
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public COTSMsrPrjResultData GetProjResultData()
|
|
|
+ {
|
|
|
+ return m_pProjData;
|
|
|
+ }
|
|
|
+ public ISemController GetSEMController()
|
|
|
+ {
|
|
|
+
|
|
|
+ // get SEM, scanner and x-ray controller via hardware manager
|
|
|
+ return m_SemController;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public CMsrThreadStatus GetMsrThreadStatus() { return m_ThreadStatus; }
|
|
|
+ public void Init(COTSMsrPrjResultData a_pProjMgrFile)
|
|
|
+ {
|
|
|
+ m_pProjData = a_pProjMgrFile;
|
|
|
+ m_listMeasurableSamples = a_pProjMgrFile.GetSampleList() ;
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ void ThreadOver()
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ DateTime timeEnd = m_ThreadStatus.GetEndTime();
|
|
|
+
|
|
|
+ ST_MSTMsg MsrMsg = new ST_MSTMsg();
|
|
|
+ MsrMsg.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
|
|
|
+
|
|
|
+ MsrMsg.STMThreadStu.iMsrStatu = m_ThreadStatus.GetStatus();
|
|
|
+
|
|
|
+
|
|
|
+ MsrMsg.STMThreadStu.csMsrEndTime = timeEnd.ToShortDateString();
|
|
|
+
|
|
|
+ ProgressEvent(MsrMsg);
|
|
|
+ //disconnect the semcontroller when we exit this task.
|
|
|
+ m_SemController.DisConnect();
|
|
|
+ }
|
|
|
+ void SetWorkingFolderStr()
|
|
|
+ {
|
|
|
+ // get project file pathname
|
|
|
+ string strSettingFilePathName = m_pProjData.GetPathName();
|
|
|
+ strSettingFilePathName.Trim();
|
|
|
+
|
|
|
+ if (strSettingFilePathName == "")
|
|
|
+ {
|
|
|
+ loger .Error("SetWorkingFolderStr: project file pathname is an empty string");
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ else if (strSettingFilePathName==UNTITLED_FILE_NAME)
|
|
|
+ {
|
|
|
+ loger .Error ("SetWorkingFolderStr: project file pathname is an invalid string");
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+
|
|
|
+ // working folder string
|
|
|
+ m_strWorkingFolder = FileHelper.GetFolderName(strSettingFilePathName);
|
|
|
+
|
|
|
+
|
|
|
+ return ;
|
|
|
+ }
|
|
|
+ public void SendMessageToMeasureApp(ST_MSTMsg msg)
|
|
|
+ {
|
|
|
+ ProgressEvent(msg);
|
|
|
+ }
|
|
|
+ public bool IsMeasureStopped()
|
|
|
+ {
|
|
|
+ return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.STOPPED;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool IsMeasureRunning() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.INPROCESS; }
|
|
|
+ public bool IsMeasureFailed() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.FAILED; }
|
|
|
+ public bool IsMeasureCompleted() { return m_ThreadStatus.GetStatus() == OTS_MSR_THREAD_STATUS.COMPLETED; }
|
|
|
+ public void DoMeasure()
|
|
|
+ {
|
|
|
+ // start measurement, creat thread measure status class, let the main thread know that measurement started
|
|
|
+
|
|
|
+
|
|
|
+ SortedDictionary<string , CSmplMeasure> mapSmplMsr=new SortedDictionary<string, CSmplMeasure>();//use this map to hold all the smplMeasure object
|
|
|
+
|
|
|
+
|
|
|
+ m_ThreadStatus.SetStartTime(System.DateTime.Now);
|
|
|
+ DateTime timeStart = m_ThreadStatus.GetStartTime();
|
|
|
+
|
|
|
+ ST_MSTMsg MsgMsrStart=new ST_MSTMsg();
|
|
|
+ MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
|
|
|
+ MsgMsrStart.STMThreadStu.iMsrStatu = OTS_MSR_THREAD_STATUS.INPROCESS;
|
|
|
+ MsgMsrStart.STMThreadStu.csMsrStartTime = timeStart.ToShortDateString();
|
|
|
+
|
|
|
+ ProgressEvent (MsgMsrStart);
|
|
|
+ loger.Info("Measurement started!");
|
|
|
+ // connect hardware
|
|
|
+ loger.Info("Connect SEM!");
|
|
|
+ if (!m_SemController.Connect())
|
|
|
+ {
|
|
|
+ loger .Error("DoMeasure: failed to connect hardware.");
|
|
|
+ m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
|
|
|
+
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // set working directory which is the same directory of the setting file
|
|
|
+ SetWorkingFolderStr();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ List <string > listMeasuredSamples = m_ThreadStatus.GetCompletedSamples();
|
|
|
+
|
|
|
+ // got through measure list
|
|
|
+ foreach (var pSample in m_listMeasurableSamples)
|
|
|
+ {// check and break if stop button is clicked
|
|
|
+ if (m_ThreadStatus.GetStatus()== OTS_MSR_THREAD_STATUS.STOPPED )
|
|
|
+ {
|
|
|
+ // stop button clicked
|
|
|
+ loger .Info("DoMeasure: stop button is clicked.");
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!pSample.GetSwitch())
|
|
|
+ {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ CSmplMeasure pSmplMeasure;
|
|
|
+ if (!mapSmplMsr.ContainsKey(pSample.GetName()))
|
|
|
+ {// create a sample measure object for the sample
|
|
|
+ switch (m_pProjData.m_nPackId)
|
|
|
+ {
|
|
|
+ case OTS_SysType_ID.IncA:
|
|
|
+ pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
|
|
|
+ break;
|
|
|
+ case OTS_SysType_ID.CleanlinessA:
|
|
|
+ pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder, pSample);
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ pSmplMeasure = new CSmplMeasureInclution(m_strWorkingFolder, pSample);
|
|
|
+ break;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // set measure thread
|
|
|
+ pSmplMeasure.SetMsrThread(this);
|
|
|
+
|
|
|
+ mapSmplMsr[pSample.GetName()] = pSmplMeasure;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pSmplMeasure = mapSmplMsr[pSample.GetName()];
|
|
|
+ pSample.GetMsrStatus().SetStatus(OTS_MSR_SAMPLE_STATUS.INPROCESS);
|
|
|
+ m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.INPROCESS);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ pSmplMeasure.DoMeasureForOneSample();
|
|
|
+
|
|
|
+
|
|
|
+ // check if measurement is successful
|
|
|
+ if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
|
|
|
+ {// record end time
|
|
|
+ m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.STOPPED);
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement stopped
|
|
|
+ ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
|
|
|
+ MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
|
|
|
+ MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
|
|
|
+ MsgSmpStop.STMThreadStu.csMsrEndTime = DateTime .Now .ToShortDateString();
|
|
|
+ MsgSmpStop.STMThreadStu.iMsrStatu= OTS_MSR_THREAD_STATUS.STOPPED;
|
|
|
+ ProgressEvent(MsgSmpStop);
|
|
|
+
|
|
|
+
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (pSample.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
|
|
|
+ {
|
|
|
+ // measurement failed
|
|
|
+ m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.FAILED);
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement failed
|
|
|
+ ST_MSTMsg MsgSmpFailed=new ST_MSTMsg();
|
|
|
+
|
|
|
+ MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
|
|
|
+
|
|
|
+
|
|
|
+ ProgressEvent(MsgSmpFailed);
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement successes
|
|
|
+ ST_MSTMsg MsgSmpSuccess=new ST_MSTMsg();
|
|
|
+ MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
+ ProgressEvent(MsgSmpSuccess);
|
|
|
+
|
|
|
+
|
|
|
+ // continue to the next sample
|
|
|
+ listMeasuredSamples.Add (pSample.GetName());
|
|
|
+ }
|
|
|
+
|
|
|
+ // measurement completed
|
|
|
+ m_ThreadStatus.SetStatus(OTS_MSR_THREAD_STATUS.COMPLETED);
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ ThreadOver();
|
|
|
+ }
|
|
|
+
|
|
|
+ // hole preview
|
|
|
+ public void DoHolePreview(int a_nHoleID, CDomain a_pMeasureArea)
|
|
|
+ {
|
|
|
+ // start measurement, creat thread measure status class, let the main thread know that measurement started
|
|
|
+ // set measure status to in-process
|
|
|
+ //record time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.START);
|
|
|
+ DateTime timeStart = m_ThreadStatus.GetStartTime();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ ST_MSTMsg MsgMsrStart = new ST_MSTMsg();
|
|
|
+
|
|
|
+ MsgMsrStart.iMsgType = ENUM_MSG_TYPE.MTHREADSTATUS;
|
|
|
+ MsgMsrStart.STMThreadStu.iMsrStatu =OTS_MSR_THREAD_STATUS.INPROCESS;
|
|
|
+
|
|
|
+ SendMessageToMeasureApp(MsgMsrStart);
|
|
|
+ // connect hardware
|
|
|
+ if (!m_SemController.Connect())
|
|
|
+ {
|
|
|
+ // failed to connect hardware
|
|
|
+
|
|
|
+ SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+ ThreadOver();
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ COTSSample pSampleHole = CreateHoleSample(a_pMeasureArea);
|
|
|
+
|
|
|
+
|
|
|
+ // create a sample measure object for the sample
|
|
|
+ CSmplMeasure pSmplMeasure = new CSmplMeasureCleanliness(m_strWorkingFolder,pSampleHole);
|
|
|
+
|
|
|
+
|
|
|
+ // set measure thread
|
|
|
+ pSmplMeasure.SetMsrThread(this);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement starts
|
|
|
+ // set working folder string
|
|
|
+ pSmplMeasure.SetSample(pSampleHole);
|
|
|
+ pSmplMeasure.SetWorkingFolder(m_strWorkingFolder);
|
|
|
+
|
|
|
+ // do measure
|
|
|
+ pSmplMeasure.DoHolePreview(a_nHoleID);
|
|
|
+
|
|
|
+ // check if measurement is successful
|
|
|
+ if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.STOPPED)
|
|
|
+ {
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+ // measurement stopped
|
|
|
+ SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement stopped
|
|
|
+ ST_MSTMsg MsgSmpStop = new ST_MSTMsg();
|
|
|
+
|
|
|
+ MsgSmpStop.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpStop.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.STOPPED;
|
|
|
+
|
|
|
+ SendMessageToMeasureApp(MsgSmpStop);
|
|
|
+
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ else if (pSampleHole.GetMsrStatus().GetStatus() == OTS_MSR_SAMPLE_STATUS.FAILED)
|
|
|
+ {
|
|
|
+ // measurement failed
|
|
|
+ SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.FAILED);
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement failed
|
|
|
+ ST_MSTMsg MsgSmpFailed = new ST_MSTMsg();
|
|
|
+
|
|
|
+ MsgSmpFailed.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpFailed.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.FAILED;
|
|
|
+
|
|
|
+ SendMessageToMeasureApp(MsgSmpFailed);
|
|
|
+ ThreadOver();
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ // update thread measure status class, let the main thread know that this sample measurement successes
|
|
|
+ ST_MSTMsg MsgSmpSuccess = new ST_MSTMsg();
|
|
|
+
|
|
|
+ MsgSmpSuccess.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpSuccess.STMSampleStu.iMsrSampleStatu = OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ SendMessageToMeasureApp(MsgSmpSuccess);
|
|
|
+
|
|
|
+ // measurement completed
|
|
|
+ SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS.COMPLETED);
|
|
|
+ // record end time
|
|
|
+ m_ThreadStatus.ComputeTime(OTS_THREAD_TIME_TYPE.STOPPED);
|
|
|
+
|
|
|
+ ThreadOver();
|
|
|
+ }
|
|
|
+
|
|
|
+ public COTSSample CreateHoleSample(CDomain a_pMsrArea)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ COTSSample pHoleSample = new COTSSample();
|
|
|
+
|
|
|
+ pHoleSample.SetMsrArea(a_pMsrArea);
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // get min magnification
|
|
|
+ CSEMStageData pSEMStageData = m_pProjData.GetSEMStageData();
|
|
|
+ double dMinMag = pSEMStageData.GetMinMag();
|
|
|
+ // get scan field size 100
|
|
|
+ int nScanFieldSize100 = pSEMStageData.GetScanFieldSize100();
|
|
|
+ // get working distance
|
|
|
+ double dWorkingDistance = 0.0;
|
|
|
+ if (!GetSEMWorkingDistanceFromHW(ref dWorkingDistance))
|
|
|
+ {
|
|
|
+
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ CSEMDataMsr poSEMDataMsr = new CSEMDataMsr();
|
|
|
+ poSEMDataMsr.SetScanFieldSize100(nScanFieldSize100);
|
|
|
+ poSEMDataMsr.SetWorkingDistance(dWorkingDistance);
|
|
|
+ poSEMDataMsr.SetMagnification(dMinMag);
|
|
|
+
|
|
|
+ pHoleSample.SetSEMDataMsr(poSEMDataMsr);
|
|
|
+
|
|
|
+ // Set image scan param
|
|
|
+ COTSImgScanPrm poImageScanParam = new COTSImgScanPrm();
|
|
|
+ poImageScanParam.SetStopMode(OTS_MEASURE_STOP_MODE.CoverMode);
|
|
|
+ poImageScanParam.SetStartImageMode(OTS_GET_IMAGE_MODE.FROM_CENTER);
|
|
|
+ poImageScanParam.SetScanImageSpeed(OTS_IMAGE_SCANSPEED_OPTIONS.low);
|
|
|
+ //poImageScanParam.SetImagePixelSize(OTS_FIVE_TIES_OPTIONS.TIE1);
|
|
|
+
|
|
|
+ CSampleParam poMsrParams = pHoleSample.GetMsrParams();
|
|
|
+ poImageScanParam.SetImageResulotion(m_listMeasurableSamples[0].GetMsrParams().GetImageScanParam().GetImageResulotion());//由于各样品分辨率应该一致,故此处没有读取选取的特定样品孔样品
|
|
|
+ poMsrParams.SetImageScanParam(poImageScanParam);
|
|
|
+ pHoleSample.SetMsrParams(poMsrParams);
|
|
|
+
|
|
|
+ return pHoleSample;
|
|
|
+ }
|
|
|
+
|
|
|
+ public bool GetSEMWorkingDistanceFromHW(ref double a_dWorkingDistance)
|
|
|
+ {
|
|
|
+
|
|
|
+ m_SemController.GetWorkingDistance(ref a_dWorkingDistance);
|
|
|
+
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ // measure status
|
|
|
+ public void SetMsrLoopStatus(otsdataconst.OTS_MSR_THREAD_STATUS a_nMsrLoopStatus)
|
|
|
+ {
|
|
|
+ //if (a_nMsrLoopStatus >= otsdataconst.OTS_MSR_THREAD_STATUS.MIN && a_nMsrLoopStatus <= otsdataconst.OTS_MSR_THREAD_STATUS.MAX)
|
|
|
+ //{
|
|
|
+ m_ThreadStatus.SetStatus( a_nMsrLoopStatus);
|
|
|
+ //}
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+}
|