|
|
@@ -12,29 +12,32 @@ using System.Diagnostics;
|
|
|
using System.Drawing;
|
|
|
using System.Threading;
|
|
|
using OTSModelSharp.MeasureControl;
|
|
|
+using System.Runtime.InteropServices;
|
|
|
|
|
|
namespace OTSModelSharp
|
|
|
{
|
|
|
-
|
|
|
+
|
|
|
using CHoleBSEImgsList = List<CHoleBSEImg>;
|
|
|
- // public enum OTS_MSR_TIME_TYPE
|
|
|
- // {
|
|
|
- // MIN = 0,
|
|
|
- // START = 1,
|
|
|
- // STOPPED = 2,
|
|
|
- // COMPLT = 3,
|
|
|
- // MAX = 3
|
|
|
- //}
|
|
|
+ // public enum OTS_MSR_TIME_TYPE
|
|
|
+ // {
|
|
|
+ // MIN = 0,
|
|
|
+ // START = 1,
|
|
|
+ // STOPPED = 2,
|
|
|
+ // COMPLT = 3,
|
|
|
+ // MAX = 3
|
|
|
+ //}
|
|
|
struct CSize
|
|
|
{
|
|
|
- public CSize(int x, int y)
|
|
|
+ public CSize(int x, int y)
|
|
|
{
|
|
|
cx = x;
|
|
|
cy = y;
|
|
|
}
|
|
|
- public int cx;
|
|
|
- public int cy;
|
|
|
+ public int cx;
|
|
|
+ public int cy;
|
|
|
}
|
|
|
+
|
|
|
+
|
|
|
class SmplMeasure
|
|
|
{
|
|
|
protected static NLog.Logger loger = null;
|
|
|
@@ -85,6 +88,10 @@ namespace OTSModelSharp
|
|
|
protected IMeasureHardware m_HardwareMgr;
|
|
|
protected IClassifyEngine m_ClassifyEngine;
|
|
|
protected Queue<COTSFieldMgr> fieldQueue;
|
|
|
+
|
|
|
+ CFieldMgr FieldMgr = new CFieldMgr();
|
|
|
+
|
|
|
+ COTSFieldMgr oTSFieldMgr = new COTSFieldMgr();
|
|
|
public SmplMeasure()
|
|
|
{
|
|
|
if (loger == null)
|
|
|
@@ -92,12 +99,38 @@ namespace OTSModelSharp
|
|
|
loger = NLog.LogManager.GetCurrentClassLogger();
|
|
|
|
|
|
}
|
|
|
+ Init();
|
|
|
+ }
|
|
|
+
|
|
|
+ // initialization
|
|
|
+ void Init()
|
|
|
+ {
|
|
|
+ m_pMsrThread = null;
|
|
|
+ m_strWorkingFolder = "";
|
|
|
|
|
|
}
|
|
|
|
|
|
- public void SetSample(COTSSample a_pSample)
|
|
|
+
|
|
|
+
|
|
|
+ public SmplMeasure(String a_strWorkingFolder, COTSSample a_pSample)
|
|
|
+ {
|
|
|
+ m_pMsrThread = null;
|
|
|
+ SetSample(a_pSample);
|
|
|
+ SetWorkingFolder(a_strWorkingFolder);
|
|
|
+ m_pSmplMsrResultFileMgr = new CSmplMsrResultFileMgr(m_strWorkingFolder);
|
|
|
+
|
|
|
+ if (!m_pSmplMsrResultFileMgr.Init(m_pSample))
|
|
|
+ {// failed to initialize measure result file
|
|
|
+ loger.Error("DoMeasure: initialize measure result file.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ // sample
|
|
|
+ public COTSSample GetSample() { return m_pSample; }
|
|
|
+ public void SetSample(COTSSample a_pSample)
|
|
|
{
|
|
|
-
|
|
|
+
|
|
|
m_pSample = a_pSample;
|
|
|
|
|
|
}
|
|
|
@@ -109,6 +142,8 @@ namespace OTSModelSharp
|
|
|
m_HardwareMgr = mt.GetMeasureHardWare();
|
|
|
}
|
|
|
|
|
|
+ public MsrThread GetMsrThread() { return m_pMsrThread; }
|
|
|
+
|
|
|
bool SetSEMDataMrs()
|
|
|
{
|
|
|
var pSEMDataMsr = m_pSample.GetSEMDataMsr();
|
|
|
@@ -275,23 +310,25 @@ namespace OTSModelSharp
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- public void SetWorkingFolder(String a_strWorkingFolder)
|
|
|
+ public void SetWorkingFolder(String a_strWorkingFolder)
|
|
|
{
|
|
|
// add "\\" at the string end if it is not "\\"
|
|
|
- if (a_strWorkingFolder.PadRight(1)!="\\")
|
|
|
+ if (a_strWorkingFolder.PadRight(1) != "\\")
|
|
|
{
|
|
|
a_strWorkingFolder += "\\";
|
|
|
}
|
|
|
|
|
|
m_strWorkingFolder = a_strWorkingFolder + m_pSample.GetName() + "\\";
|
|
|
}
|
|
|
+
|
|
|
+ public String GetWorkingFolder() { return m_strWorkingFolder; }
|
|
|
bool CalculateUnMeasuredFieldsCenters(out List<System.Drawing.Point> a_listFieldCenter)
|
|
|
{
|
|
|
Debug.Assert(m_pSample == null);
|
|
|
|
|
|
// sample measure parameters
|
|
|
CMsrParams pMsrParam = m_pSample.GetMsrParams();
|
|
|
- COTSImgScanPrm poImageScanParam = pMsrParam.GetImageScanParam();
|
|
|
+ COTSImgScanPrm poImageScanParam = pMsrParam.GetImageScanParam();
|
|
|
CSEMDataMsr poSEMDataMsr = m_pSample.GetSEMDataMsr();
|
|
|
CMsrSampleStatus pStatus = m_pSample.GetMsrStatus();
|
|
|
|
|
|
@@ -322,7 +359,7 @@ namespace OTSModelSharp
|
|
|
return m_pMsrThread.IsMeasureStopped();
|
|
|
}
|
|
|
|
|
|
- bool IsSampleOver(COTSImgScanPrm a_pScanParam, int a_nTotalFields)
|
|
|
+ bool IsSampleOver(COTSImgScanPrm a_pScanParam, int a_nTotalFields)
|
|
|
{
|
|
|
Debug.Assert(a_pScanParam == null);
|
|
|
|
|
|
@@ -470,7 +507,7 @@ namespace OTSModelSharp
|
|
|
sm.ResetScan();
|
|
|
}
|
|
|
}
|
|
|
- public void DoMeasureForOneSample()
|
|
|
+ public void DoMeasureForOneSample()
|
|
|
{
|
|
|
// let the main thread to know that this sample measurement starts
|
|
|
var pStatus = m_pSample.GetMsrStatus();
|
|
|
@@ -481,12 +518,12 @@ namespace OTSModelSharp
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
|
|
|
|
|
|
// let main App know that the sample begin to measure
|
|
|
- ST_MSTMsg MsgSmpStart=new ST_MSTMsg();
|
|
|
+ ST_MSTMsg MsgSmpStart = new ST_MSTMsg();
|
|
|
//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));
|
|
|
- MsgSmpStart.STMSampleStu.cSampleName=m_pSample.GetName();
|
|
|
+ // memset(MsgSmpStart.STMSampleStu.cSampleName, 0, sizeof(MsgSmpStart.STMSampleStu.cSampleName));
|
|
|
+ MsgSmpStart.STMSampleStu.cSampleName = m_pSample.GetName();
|
|
|
|
|
|
m_pMsrThread.SendMessageToMeasureApp(MsgSmpStart);
|
|
|
|
|
|
@@ -524,25 +561,25 @@ namespace OTSModelSharp
|
|
|
var autoReset = new AutoResetSEMControl(this);//when this method exit ,the SetSEMExternalOff and ResetScan will be called automatically.
|
|
|
// record SEM working condition
|
|
|
var pSEMDataGnr = new CSEMDataGnr();
|
|
|
- m_HardwareMgr.GetSEMController().GetSEMDataGnr(out pSEMDataGnr);
|
|
|
-
|
|
|
-
|
|
|
+ m_HardwareMgr.GetSEMController().GetSEMDataGnr(out pSEMDataGnr);
|
|
|
+
|
|
|
+
|
|
|
m_pSmplMsrResultFileMgr.SetSEMGnr(pSEMDataGnr);
|
|
|
|
|
|
// record SEM data
|
|
|
COTSProjMgrFile pProjMgrFile = m_pMsrThread.GetProjMgrFile();
|
|
|
- Debug.Assert(pProjMgrFile==null);
|
|
|
-
|
|
|
+ Debug.Assert(pProjMgrFile == null);
|
|
|
+
|
|
|
|
|
|
CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData();
|
|
|
- Debug.Assert(pSEMStageData==null);
|
|
|
+ Debug.Assert(pSEMStageData == null);
|
|
|
|
|
|
m_pSmplMsrResultFileMgr.SetSEMStageData(pSEMStageData);
|
|
|
|
|
|
// record stage
|
|
|
CStage pStage = pProjMgrFile.GetStage();
|
|
|
- Debug.Assert(pStage==null);
|
|
|
-
|
|
|
+ Debug.Assert(pStage == null);
|
|
|
+
|
|
|
m_pSmplMsrResultFileMgr.SetSEMStage(pStage);
|
|
|
|
|
|
//-----save the static measure result file data into xml file and the dynamic data of every field will be saved into sqlite database
|
|
|
@@ -569,7 +606,7 @@ namespace OTSModelSharp
|
|
|
int nNewFieldId = 0;
|
|
|
int numOfAllFields = pStatus.GetCompletedFields() + umMeasuredlistFieldCenter.Count;//
|
|
|
int completedFields = pStatus.GetCompletedFields();
|
|
|
- for ( int i = 0; i < (int)umMeasuredlistFieldCenter.Count; ++i)
|
|
|
+ for (int i = 0; i < (int)umMeasuredlistFieldCenter.Count; ++i)
|
|
|
{// check and break if stop button is clicked
|
|
|
if (IsAborted())
|
|
|
{// measure stopped
|
|
|
@@ -585,10 +622,10 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
// check if sample measurement completes
|
|
|
- COTSImgScanPrm pScanParam = m_pSample.GetMsrParams().GetImageScanParam();
|
|
|
+ COTSImgScanPrm pScanParam = m_pSample.GetMsrParams().GetImageScanParam();
|
|
|
int nTotalFieldSize = (int)umMeasuredlistFieldCenter.Count;
|
|
|
- Debug.Assert(pScanParam==null);
|
|
|
-
|
|
|
+ Debug.Assert(pScanParam == null);
|
|
|
+
|
|
|
|
|
|
if (IsSampleOver(pScanParam, nTotalFieldSize))
|
|
|
{
|
|
|
@@ -602,7 +639,7 @@ namespace OTSModelSharp
|
|
|
// 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=new ST_MSTMsg();
|
|
|
+ ST_MSTMsg MsgFieldStart = new ST_MSTMsg();
|
|
|
MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
|
|
|
MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD;
|
|
|
MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre;
|
|
|
@@ -632,16 +669,16 @@ namespace OTSModelSharp
|
|
|
pNewFieldData.SetFieldFileFolder(m_pSmplMsrResultFileMgr.GetFieldFileSubFolderStr());
|
|
|
|
|
|
// image process
|
|
|
-
|
|
|
- ImageProcess(pNewFieldData, pBSEIamge);
|
|
|
-
|
|
|
+
|
|
|
+ ImageProcess(pNewFieldData, pBSEIamge);
|
|
|
+
|
|
|
|
|
|
|
|
|
// is the field data empty
|
|
|
if (!pNewFieldData.IsEmpty())
|
|
|
{
|
|
|
- Debug.Assert(m_pSmplMsrResultFileMgr==null);
|
|
|
-
|
|
|
+ Debug.Assert(m_pSmplMsrResultFileMgr == null);
|
|
|
+
|
|
|
// add the field into the field
|
|
|
if (!m_pSmplMsrResultFileMgr.AddAField(pNewFieldData))
|
|
|
{
|
|
|
@@ -660,15 +697,15 @@ namespace OTSModelSharp
|
|
|
pStatus.SetCompletedFields(pStatus.GetCompletedFields() + 1);
|
|
|
|
|
|
// completed fieldCenter
|
|
|
- List<System.Drawing.Point> listCpltedCenter = pStatus.GetCompletedFieldsCenter();
|
|
|
+ List<System.Drawing.Point> listCpltedCenter = pStatus.GetCompletedFieldsCenter();
|
|
|
listCpltedCenter.Add(poiFieldCentre);
|
|
|
|
|
|
//Field Data
|
|
|
// record end time
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
- ST_MSTMsg MsgFieldEnd=new ST_MSTMsg();
|
|
|
- // memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg));
|
|
|
- MsgFieldEnd.iMsgType =ENUM_MSG_TYPE.MSAMPLERESULT;
|
|
|
+ ST_MSTMsg MsgFieldEnd = new ST_MSTMsg();
|
|
|
+ // 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;
|
|
|
@@ -680,27 +717,27 @@ namespace OTSModelSharp
|
|
|
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
}
|
|
|
- while (fieldQueue.Count > 0)//wait untill all the field data has been saved.
|
|
|
- {
|
|
|
- Thread.Sleep(100);
|
|
|
- }
|
|
|
- //calculate measure time
|
|
|
+ while (fieldQueue.Count > 0)//wait untill all the field data has been saved.
|
|
|
+ {
|
|
|
+ Thread.Sleep(100);
|
|
|
+ }
|
|
|
+ //calculate measure time
|
|
|
|
|
|
- pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
|
|
|
- pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
|
|
|
+ pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
|
|
|
|
|
|
- // let main thread to know that this sample measurement completes
|
|
|
- ST_MSTMsg MsgSmplEnd=new ST_MSTMsg();
|
|
|
- MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
- MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int) OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
- MsgSmplEnd.STMSampleStu.cSampleName= m_pSample.GetName();
|
|
|
- m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd);
|
|
|
- }
|
|
|
+ // let main thread to know that this sample measurement completes
|
|
|
+ ST_MSTMsg MsgSmplEnd = new ST_MSTMsg();
|
|
|
+ MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
+ MsgSmplEnd.STMSampleStu.cSampleName = m_pSample.GetName();
|
|
|
+ m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd);
|
|
|
+ }
|
|
|
|
|
|
public void DoHolePreview(int a_nHoleID)
|
|
|
{
|
|
|
- Debug.Assert(m_pSample==null);
|
|
|
+ Debug.Assert(m_pSample == null);
|
|
|
|
|
|
// let the main thread to know that this sample measurement starts
|
|
|
CMsrSampleStatus pStatus = m_pSample.GetMsrStatus();
|
|
|
@@ -710,12 +747,12 @@ namespace OTSModelSharp
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.START);
|
|
|
|
|
|
// let main App know that the sample begin to measure
|
|
|
- ST_MSTMsg MsgSmpStart=new ST_MSTMsg();
|
|
|
- // memset(&MsgSmpStart, 0, sizeof(ST_MSTMsg));
|
|
|
+ ST_MSTMsg MsgSmpStart = new ST_MSTMsg();
|
|
|
+ // 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));
|
|
|
- MsgSmpStart.STMSampleStu.cSampleName=m_pSample.GetName();
|
|
|
+ MsgSmpStart.STMSampleStu.cSampleName = m_pSample.GetName();
|
|
|
|
|
|
|
|
|
// get SEM controller to set magnification and working distance
|
|
|
@@ -764,8 +801,8 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
// calculate field centers
|
|
|
- List<System.Drawing.Point> listFieldCenter=new List<System.Drawing.Point>();
|
|
|
- // listFieldCenter.clear();
|
|
|
+ List<System.Drawing.Point> listFieldCenter = new List<System.Drawing.Point>();
|
|
|
+ // listFieldCenter.clear();
|
|
|
if (!CalculateUnMeasuredFieldsCenters(out listFieldCenter))
|
|
|
{// failed to calculate field centers
|
|
|
loger.Error("DoHolePreview: failed to calculate field centers.");
|
|
|
@@ -777,7 +814,7 @@ namespace OTSModelSharp
|
|
|
|
|
|
// go through each field
|
|
|
int nNewFieldId = 0;
|
|
|
- for ( int i = 0; i < listFieldCenter.Count; ++i)
|
|
|
+ for (int i = 0; i < listFieldCenter.Count; ++i)
|
|
|
{// check and break if stop button is clicked
|
|
|
if (IsAborted())
|
|
|
{// measure stopped
|
|
|
@@ -789,10 +826,10 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
// check if sample measurement completes
|
|
|
- COTSImgScanPrm pScanParam = m_pSample.GetMsrParams().GetImageScanParam();
|
|
|
+ COTSImgScanPrm pScanParam = m_pSample.GetMsrParams().GetImageScanParam();
|
|
|
int nTotalFieldSize = listFieldCenter.Count;
|
|
|
- Debug.Assert(pScanParam==null);
|
|
|
-
|
|
|
+ Debug.Assert(pScanParam == null);
|
|
|
+
|
|
|
|
|
|
if (IsSampleOver(pScanParam, nTotalFieldSize))
|
|
|
{
|
|
|
@@ -804,18 +841,18 @@ namespace OTSModelSharp
|
|
|
// get a field center
|
|
|
System.Drawing.Point poiFieldCentre = listFieldCenter[i];
|
|
|
|
|
|
- // LogInfoTrace(__FILE__, __LINE__, _T("C++ Position Message 1: field %d begin."), i);
|
|
|
+ // LogInfoTrace(__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=new ST_MSTMsg();
|
|
|
+ ST_MSTMsg MsgFieldStart = new ST_MSTMsg();
|
|
|
//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);
|
|
|
+ // LogInfoTrace(__FILE__, __LINE__, _T("Message :DoHolePreview: field %d measure begin. message type is %d"), i, MsgFieldStart.iMsgType);
|
|
|
|
|
|
m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart);
|
|
|
|
|
|
@@ -832,7 +869,7 @@ namespace OTSModelSharp
|
|
|
|
|
|
// take BSE image for the fields
|
|
|
CBSEImg pBSEIamge = AcquireABSEImage();
|
|
|
- if (pBSEIamge==null)
|
|
|
+ if (pBSEIamge == null)
|
|
|
{
|
|
|
// failed to acquire a BSE image
|
|
|
loger.Error("DoHolePreview: failed to acquire a BSE image.");
|
|
|
@@ -844,8 +881,8 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
//BSEData
|
|
|
- ST_MSTMsg MsgFieldBSE=new ST_MSTMsg();
|
|
|
- // memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg));
|
|
|
+ ST_MSTMsg MsgFieldBSE = new ST_MSTMsg();
|
|
|
+ // memset(&MsgFieldBSE, 0, sizeof(ST_MSTMsg));
|
|
|
MsgFieldBSE.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
|
|
|
MsgFieldBSE.STMSampleRetData.iRetDataType = MSAMPLE_RET.BSE_DATA;
|
|
|
MsgFieldBSE.STMSampleRetData.BSEData.pos = poiFieldCentre;
|
|
|
@@ -855,9 +892,9 @@ namespace OTSModelSharp
|
|
|
byte[] pImgData = pBSEIamge.GetImageDataPointer();
|
|
|
MsgFieldBSE.STMSampleRetData.BSEData.lpBSEData = pImgData;
|
|
|
|
|
|
- // LogInfoTrace(__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("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);
|
|
|
+ // LogInfoTrace(__FILE__, __LINE__, _T("Message : ImageProcess: send BSE data. message type is %d"), MsgFieldBSE.iMsgType);
|
|
|
|
|
|
m_pMsrThread.SendMessageToMeasureApp(MsgFieldBSE);
|
|
|
|
|
|
@@ -873,24 +910,24 @@ namespace OTSModelSharp
|
|
|
}
|
|
|
|
|
|
//save the result to project file
|
|
|
- CHoleBSEImg pHoleBSEImg =new CHoleBSEImg();
|
|
|
+ CHoleBSEImg pHoleBSEImg = new CHoleBSEImg();
|
|
|
pHoleBSEImg.SetHoleID(a_nHoleID);
|
|
|
pHoleBSEImg.SetPosition(poiFieldCentre);
|
|
|
Rectangle oImageRect = pBSEIamge.GetImageRect();
|
|
|
long nImageSize = pBSEIamge.GetHeight() * pBSEIamge.GetWidth();
|
|
|
pHoleBSEImg.SetImageRect(oImageRect);
|
|
|
- pHoleBSEImg.SetImageData( pBSEIamge.GetImageDataPointer());
|
|
|
+ pHoleBSEImg.SetImageData(pBSEIamge.GetImageDataPointer());
|
|
|
|
|
|
m_listHoleBSEImg.Add(pHoleBSEImg);
|
|
|
|
|
|
COTSProjMgrFile pProjMgrFile = m_pMsrThread.GetProjMgrFile();
|
|
|
- pProjMgrFile.SetHoleBESImgList(m_listHoleBSEImg,false);
|
|
|
+ pProjMgrFile.SetHoleBESImgList(m_listHoleBSEImg, false);
|
|
|
|
|
|
// prepare for the next
|
|
|
++nNewFieldId;
|
|
|
pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
|
|
|
- ST_MSTMsg MsgFieldEnd=new ST_MSTMsg();
|
|
|
+ ST_MSTMsg MsgFieldEnd = new ST_MSTMsg();
|
|
|
//memset(&MsgFieldEnd, 0, sizeof(ST_MSTMsg));
|
|
|
MsgFieldEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
|
|
|
MsgFieldEnd.STMSampleRetData.iRetDataType = MSAMPLE_RET.FIELD_DATA;
|
|
|
@@ -900,7 +937,7 @@ namespace OTSModelSharp
|
|
|
MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos = poiFieldCentre;
|
|
|
//MsgFieldEnd.STMSampleRetData.SFieldData.Fieldpos.y = poiFieldCentre.y;
|
|
|
|
|
|
- // LogInfoTrace(__FILE__, __LINE__, _T("Message: DoHolePreview: field %d measure end. message type is %d"), i, MsgFieldEnd.iMsgType);
|
|
|
+ // LogInfoTrace(__FILE__, __LINE__, _T("Message: DoHolePreview: field %d measure end. message type is %d"), i, MsgFieldEnd.iMsgType);
|
|
|
m_pMsrThread.SendMessageToMeasureApp(MsgFieldEnd);
|
|
|
|
|
|
}
|
|
|
@@ -910,11 +947,11 @@ namespace OTSModelSharp
|
|
|
pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.SUCCESSED);
|
|
|
|
|
|
// let main thread to know that this sample measurement completes
|
|
|
- ST_MSTMsg MsgSmplEnd=new ST_MSTMsg();
|
|
|
- // memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg));
|
|
|
+ ST_MSTMsg MsgSmplEnd = new ST_MSTMsg();
|
|
|
+ // memset(&MsgSmplEnd, 0, sizeof(ST_MSTMsg));
|
|
|
MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
- MsgSmplEnd.STMSampleStu.iMeasureSampleStatus =(int) OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
- MsgSmplEnd.STMSampleStu.cSampleName= m_pSample.GetName();
|
|
|
+ MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
+ MsgSmplEnd.STMSampleStu.cSampleName = m_pSample.GetName();
|
|
|
|
|
|
//LogInfoTrace(__FILE__, __LINE__, _T("Message : DoHolePreview: sample %s end. message type is %d"), m_pSample->GetName(), MsgSmplEnd.iMsgType);
|
|
|
|
|
|
@@ -941,12 +978,12 @@ namespace OTSModelSharp
|
|
|
|
|
|
bool SetPrjFileSave()
|
|
|
{
|
|
|
- Debug.Assert(m_pMsrThread==null);
|
|
|
-
|
|
|
+ Debug.Assert(m_pMsrThread == null);
|
|
|
+
|
|
|
|
|
|
COTSProjMgrFile pProjMgr = m_pMsrThread.GetProjMgrFile();
|
|
|
- Debug.Assert(pProjMgr==null);
|
|
|
-
|
|
|
+ Debug.Assert(pProjMgr == null);
|
|
|
+
|
|
|
|
|
|
pProjMgr.SetModify(true);
|
|
|
|
|
|
@@ -959,12 +996,12 @@ namespace OTSModelSharp
|
|
|
bool RecordSEMCondition(CSEMDataGnr a_pSEMDataGnr)
|
|
|
{
|
|
|
// safety check
|
|
|
- Debug.Assert(a_pSEMDataGnr==null);
|
|
|
-
|
|
|
+ Debug.Assert(a_pSEMDataGnr == null);
|
|
|
+
|
|
|
|
|
|
// get SEM controller
|
|
|
- ISemController pSEMCotroller =m_HardwareMgr.GetSEMController();
|
|
|
- Debug.Assert (pSEMCotroller==null);
|
|
|
+ ISemController pSEMCotroller = m_HardwareMgr.GetSEMController();
|
|
|
+ Debug.Assert(pSEMCotroller == null);
|
|
|
|
|
|
|
|
|
// get SEM condition (general)
|
|
|
@@ -977,5 +1014,595 @@ namespace OTSModelSharp
|
|
|
// ok, return TRUE
|
|
|
return true;
|
|
|
}
|
|
|
+
|
|
|
+ // get pixel size
|
|
|
+ public bool GetPixelSize(double a_dPixelSize)
|
|
|
+ {
|
|
|
+
|
|
|
+ a_dPixelSize = m_pSample.CalculatePixelSize();
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // measurement
|
|
|
+ public void DoMeasureOneSample()
|
|
|
+ {
|
|
|
+
|
|
|
+ // let the main thread to know that this sample measurement starts
|
|
|
+ CMsrSampleStatus 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 = new ST_MSTMsg();
|
|
|
+
|
|
|
+ byte[] yourArray = new byte[Convert.ToInt32(MsgSmpStart)];
|
|
|
+ Array.Clear(yourArray, 0, yourArray.Length);
|
|
|
+ MsgSmpStart.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmpStart.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS.INPROCESS;
|
|
|
+ byte[] ArrayTwo = new byte[Convert.ToInt32(MsgSmpStart.STMSampleStu.cSampleName)];
|
|
|
+ Array.Clear(ArrayTwo, 0, Convert.ToInt32(MsgSmpStart.STMSampleStu.cSampleName));
|
|
|
+ int[] SampleName = new int[Convert.ToInt32(MsgSmpStart.STMSampleStu.cSampleName)];
|
|
|
+ Marshal.Copy(SampleName, Convert.ToInt32(m_pSample.GetName()), (IntPtr)Convert.ToInt32(m_pSample.GetName()), 0);
|
|
|
+
|
|
|
+
|
|
|
+ m_pMsrThread.SendMessageToMeasureApp(MsgSmpStart);
|
|
|
+
|
|
|
+ // get SEM controller to set magnification and working distance
|
|
|
+ if (!SetSEMDataMrs())
|
|
|
+ {
|
|
|
+ loger.Error("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())
|
|
|
+ {
|
|
|
+ loger.Error("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())
|
|
|
+ {
|
|
|
+ loger.Error("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
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // record SEM working condition
|
|
|
+ CSEMDataGnr pSEMDataGnr = m_pMsrThread.GetSEMDataGnr();
|
|
|
+
|
|
|
+ m_pSmplMsrResultFileMgr.SetSEMGnr(pSEMDataGnr);
|
|
|
+
|
|
|
+ // record SEM data
|
|
|
+ COTSProjMgrFile pProjMgrFile = m_pMsrThread.GetProjMgrFile();
|
|
|
+
|
|
|
+
|
|
|
+ CSEMStageData pSEMStageData = pProjMgrFile.GetSEMStageData();
|
|
|
+
|
|
|
+ m_pSmplMsrResultFileMgr.SetSEMStageData(pSEMStageData);
|
|
|
+
|
|
|
+ // record stage
|
|
|
+ CStage pStage = pProjMgrFile.GetStage();
|
|
|
+
|
|
|
+ m_pSmplMsrResultFileMgr.SetSEMStage(pStage);
|
|
|
+ // calculate field centers
|
|
|
+ List<Point> umMeasuredlistFieldCenter = new List<Point>();
|
|
|
+ //umMeasuredlistFieldCenter.clear();
|
|
|
+ if (!CalculateUnMeasuredFieldsCenters(out umMeasuredlistFieldCenter))
|
|
|
+ {// failed to calculate field centers
|
|
|
+ loger.Error("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
|
|
|
+ String strPathName = m_pSmplMsrResultFileMgr.GetPathName();
|
|
|
+ if (!m_pSmplMsrResultFileMgr.Save(strPathName))
|
|
|
+ {// failed to call measure result file Save method
|
|
|
+ loger.Error("DoMeasure: failed to call measure result file Save method.");
|
|
|
+ pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
|
|
|
+ pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ //------
|
|
|
+
|
|
|
+ int nNewFieldId = 0;
|
|
|
+ int numOfAllFields = pStatus.GetCompletedFields() + umMeasuredlistFieldCenter.Count;//
|
|
|
+ int completedFields = pStatus.GetCompletedFields();
|
|
|
+ for (int i = 0; i < (int)umMeasuredlistFieldCenter.Count; ++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.Count > 0)
|
|
|
+ {
|
|
|
+ Thread.Sleep(100);
|
|
|
+
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // check if sample measurement completes
|
|
|
+ COTSImgScanPrm pScanParam = m_pSample.GetMsrParams().GetImageScanParam();
|
|
|
+ //int nTotalFieldSize = (int)umMeasuredlistFieldCenter.size();
|
|
|
+
|
|
|
+
|
|
|
+ if (IsSampleOver(pScanParam, numOfAllFields))
|
|
|
+ {
|
|
|
+ pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ // get a field center
|
|
|
+ Point 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 = new ST_MSTMsg();
|
|
|
+ byte[] yourArrayTwo = new byte[Convert.ToInt32(MsgFieldStart)];
|
|
|
+ Array.Clear(yourArrayTwo, 0, yourArrayTwo.Length);
|
|
|
+ MsgFieldStart.iMsgType = ENUM_MSG_TYPE.MSAMPLERESULT;
|
|
|
+ MsgFieldStart.STMSampleRetData.iRetDataType = MSAMPLE_RET.START_MSR_FIELD;
|
|
|
+ MsgFieldStart.STMSampleRetData.SMsrField.Fieldpos = poiFieldCentre;
|
|
|
+ m_pMsrThread.SendMessageToMeasureApp(MsgFieldStart);
|
|
|
+
|
|
|
+ // move SEM to the field center
|
|
|
+ if (!MoveSEMToPoint(poiFieldCentre))
|
|
|
+ {// failed to move SEM to the position
|
|
|
+ loger.Error("DoMeasure: 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
|
|
|
+ CBSEImg pBSEIamge = AcquireABSEImage();
|
|
|
+ if (pBSEIamge != null)
|
|
|
+ {// failed to acquire a BSE image
|
|
|
+ loger.Error("DoMeasure: failed to acquire a BSE image.");
|
|
|
+ pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
|
|
|
+ // record end time
|
|
|
+ pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // get a new field id
|
|
|
+ nNewFieldId = m_pSmplMsrResultFileMgr.GetIdForANewField(nNewFieldId);
|
|
|
+
|
|
|
+ // create a field
|
|
|
+ COTSFieldData pNewFieldData = 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
|
|
|
+ // loger.Error("DoMeasure: image process failed.");
|
|
|
+ // pStatus.SetStatus(OTS_MSR_SAMPLE_STATUS.FAILED);
|
|
|
+ // // record end time
|
|
|
+ // pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ // return;
|
|
|
+ //}
|
|
|
+
|
|
|
+
|
|
|
+ // is the field data empty
|
|
|
+ if (!pNewFieldData.IsEmpty())
|
|
|
+ {
|
|
|
+
|
|
|
+ // add the field into the field
|
|
|
+ if (!m_pSmplMsrResultFileMgr.AddAField(pNewFieldData))
|
|
|
+ {
|
|
|
+ // failed to add the field into the file
|
|
|
+
|
|
|
+ loger.Error("SaveAField: failed to add the field into the file.");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // prepare for the next
|
|
|
+ ++nNewFieldId;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // completed fields
|
|
|
+ pStatus.SetCompletedFields(pStatus.GetCompletedFields() + 1);
|
|
|
+
|
|
|
+ // completed fieldCenter
|
|
|
+ List<Point> listCpltedCenter = pStatus.GetCompletedFieldsCenter();
|
|
|
+ listCpltedCenter.Add(poiFieldCentre);
|
|
|
+
|
|
|
+ //Field Data
|
|
|
+ // record end time
|
|
|
+ pStatus.ComputeTime(OTS_MSR_TIME_TYPE.STOPPED);
|
|
|
+ ST_MSTMsg MsgFieldEnd = new ST_MSTMsg();
|
|
|
+ byte[] yourArrays = new byte[Convert.ToInt32(MsgFieldEnd)];
|
|
|
+ Array.Clear(yourArrays, 0, yourArrays.Length);
|
|
|
+ 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().Count;
|
|
|
+ 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.Count > 0)//wait untill all the field data has been saved.
|
|
|
+ {
|
|
|
+ Thread.Sleep(100);
|
|
|
+ }
|
|
|
+
|
|
|
+ //process the particle which span more than one field or extend to other field.
|
|
|
+ List<COTSParticle> mergedParts = new List<COTSParticle>();
|
|
|
+ mergedParts.Clear();
|
|
|
+ MergeBigBoundaryParticles(mergedParts);
|
|
|
+ double pixelSize = 0;
|
|
|
+
|
|
|
+ this.GetPixelSize(pixelSize);
|
|
|
+
|
|
|
+ oTSFieldMgr.CalMergedParticleImageProp(mergedParts, pixelSize);
|
|
|
+
|
|
|
+ oTSFieldMgr.ClassifyMergedParticles(mergedParts, m_strWorkingFolder);
|
|
|
+
|
|
|
+ String folderStr = m_pSmplMsrResultFileMgr.GetWorkingFolderStr();
|
|
|
+
|
|
|
+ oTSFieldMgr.SaveMergedParticles(mergedParts, folderStr);
|
|
|
+
|
|
|
+
|
|
|
+ //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 = new ST_MSTMsg();
|
|
|
+ byte[] yourArrayThree = new byte[Convert.ToInt32(MsgSmplEnd)];
|
|
|
+ Array.Clear(yourArrayThree, 0, yourArrayThree.Length);
|
|
|
+ MsgSmplEnd.iMsgType = ENUM_MSG_TYPE.MSAMPLESTATUS;
|
|
|
+ MsgSmplEnd.STMSampleStu.iMeasureSampleStatus = (int)OTS_MSR_SAMPLE_STATUS.SUCCESSED;
|
|
|
+ int[] SampleNameTwo = new int[Convert.ToInt32(MsgSmplEnd.STMSampleStu.cSampleName)];
|
|
|
+ Marshal.Copy(SampleNameTwo, Convert.ToInt32(m_pSample.GetName()), (IntPtr)Convert.ToInt32(m_pSample.GetName()),0);
|
|
|
+ m_pMsrThread.SendMessageToMeasureApp(MsgSmplEnd);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ struct EleAreaPercentage
|
|
|
+ {
|
|
|
+ EleAreaPercentage(double p, CElementChemistry e)
|
|
|
+ {
|
|
|
+ areaPercentage = p;
|
|
|
+ eleData = e;
|
|
|
+ }
|
|
|
+ double areaPercentage;
|
|
|
+ CElementChemistry eleData;
|
|
|
+ };
|
|
|
+ public bool MergeBigBoundaryParticles(List<COTSParticle> mergedParts)
|
|
|
+ {
|
|
|
+ List<COTSSegment> boarderSegs;
|
|
|
+ var allFields = m_pSmplMsrResultFileMgr.GetSmplMsrResultFile().GetFieldData();
|
|
|
+ double pixelSize = 0;
|
|
|
+ this.GetPixelSize(pixelSize);
|
|
|
+ var FldMgr = new CFieldMgr();
|
|
|
+ FldMgr.SetSEMDataMsr(this.GetSample().GetSEMDataMsr());
|
|
|
+
|
|
|
+ Dictionary<List<COTSParticle>, List<COTSParticle>> mapMergeParticles = new Dictionary<List<COTSParticle>, List<COTSParticle>>();//hold up all the boundary connected particles. the pair's first is also the member of these particles.
|
|
|
+ Dictionary<COTSParticle, List<COTSSegment>> mapMergedSegments;//hold up all the segment's corresponding clone in the connected particles.
|
|
|
+
|
|
|
+ foreach (var centerfld in allFields)
|
|
|
+ {
|
|
|
+ // find neighbor field on the left.
|
|
|
+ var leftFld = FldMgr.FindNeighborField(allFields, centerfld, CFieldMgr.SORTING_DIRECTION.LEFT);
|
|
|
+ if (leftFld != null)
|
|
|
+ {
|
|
|
+ var leftParts = centerfld.GetLeftBorderedBigParticles();
|
|
|
+ var rightParts = leftFld.GetRightBorderedBigParticles();
|
|
|
+
|
|
|
+ foreach (var leftp in leftParts)
|
|
|
+ {
|
|
|
+ foreach (var rightp in rightParts)
|
|
|
+ {
|
|
|
+ if (leftp.IsConnected(rightp, Convert.ToInt32(centerfld.Width), Convert.ToInt32(centerfld.Height), Convert.ToInt32(CFieldMgr.SORTING_DIRECTION.LEFT)))
|
|
|
+ {
|
|
|
+ if (leftp.headerParticle != null)
|
|
|
+ {
|
|
|
+ if (rightp.headerParticle == null)
|
|
|
+ {
|
|
|
+ rightp.headerParticle = leftp.headerParticle;
|
|
|
+ mapMergeParticles[leftp.headerParticle].Add(rightp);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (rightp.headerParticle != null)
|
|
|
+ {
|
|
|
+ leftp.headerParticle = rightp;
|
|
|
+
|
|
|
+ mapMergeParticles[rightp].push_back(leftp);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ leftp.headerParticle = leftp;
|
|
|
+ rightp.headerParticle = leftp;
|
|
|
+ mapMergeParticles[leftp].Add(rightp);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ //find neighbor field on the upward
|
|
|
+ var upFld = FldMgr.FindNeighborField(allFields, centerfld, CFieldMgr.SORTING_DIRECTION.UP);
|
|
|
+ if (upFld != null)
|
|
|
+ {
|
|
|
+ var upParts = centerfld.GetTopBorderedBigParticles();
|
|
|
+ var downParts = upFld.GetBottomBorderedBigParticles();
|
|
|
+
|
|
|
+ foreach (var upprt in upParts)
|
|
|
+ {
|
|
|
+ foreach (var downprt in downParts)
|
|
|
+ {
|
|
|
+ if (upprt.IsConnected(downprt, Convert.ToInt32(centerfld.Width), Convert.ToInt32(centerfld.Height), Convert.ToInt32(CFieldMgr.SORTING_DIRECTION.UP)))
|
|
|
+ {
|
|
|
+
|
|
|
+ if (upprt.headerParticle != null)
|
|
|
+ {
|
|
|
+ if (downprt[0].headerParticle == null)
|
|
|
+ {
|
|
|
+ downprt[0].headerParticle = upprt.headerParticle;
|
|
|
+ mapMergeParticles[upprt.headerParticle].Add(downprt[0]);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (downprt[0].headerParticle != null)
|
|
|
+ {
|
|
|
+ upprt.headerParticle = downprt[0].headerParticle;
|
|
|
+ mapMergeParticles[downprt].Add(upprt);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ upprt.headerParticle = upprt;
|
|
|
+ downprt.headerParticle = upprt;
|
|
|
+ mapMergeParticles[upprt].Add(downprt);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ //find neighbor field on the downward.
|
|
|
+ var downFld = FldMgr.FindNeighborField(allFields, centerfld, CFieldMgr.SORTING_DIRECTION.DOWN);
|
|
|
+ if (downFld != null)
|
|
|
+ {
|
|
|
+ var downParts = centerfld.GetBottomBorderedBigParticles();
|
|
|
+ var upParts = downFld.GetTopBorderedBigParticles();
|
|
|
+
|
|
|
+ foreach (var downprt in downParts)
|
|
|
+ {
|
|
|
+ foreach (var upprt in upParts)
|
|
|
+ {
|
|
|
+ if (downprt.IsConnected(upprt, Convert.ToInt32(centerfld.Width), Convert.ToInt32(centerfld.Height), Convert.ToInt32(CFieldMgr.SORTING_DIRECTION.DOWN)))
|
|
|
+ {
|
|
|
+
|
|
|
+ if (downprt.headerParticle != null)
|
|
|
+ {
|
|
|
+ if (upprt.headerParticle == null)
|
|
|
+ {
|
|
|
+ upprt.headerParticle = downprt.headerParticle;
|
|
|
+ mapMergeParticles[downprt.headerParticle].Add(upprt);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (upprt.headerParticle != null)
|
|
|
+ {
|
|
|
+ downprt.headerParticle = upprt.headerParticle;
|
|
|
+ mapMergeParticles[upprt.headerParticle].Add(downprt);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ downprt.headerParticle = downprt;
|
|
|
+ upprt.headerParticle = downprt;
|
|
|
+ mapMergeParticles[downprt].push_back(upprt);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ //find neighbor field on the right.
|
|
|
+ var rightFld = FldMgr.FindNeighborField(allFields, centerfld, CFieldMgr.SORTING_DIRECTION.RIGHT);
|
|
|
+ if (rightFld != null)
|
|
|
+ {
|
|
|
+ var rightParts = centerfld.GetRightBorderedBigParticles();
|
|
|
+ var leftParts = rightFld.GetLeftBorderedBigParticles();
|
|
|
+
|
|
|
+ foreach (var rightprt in rightParts)
|
|
|
+ {
|
|
|
+ foreach (var leftprt in leftParts)
|
|
|
+ {
|
|
|
+ if (rightprt.IsConnected(leftprt, Convert.ToInt32(centerfld.Width), Convert.ToInt32(centerfld.Height), Convert.ToInt32(CFieldMgr.SORTING_DIRECTION.RIGHT)))
|
|
|
+ {
|
|
|
+
|
|
|
+ if (rightprt.headerParticle != null)
|
|
|
+ {
|
|
|
+ if (leftprt.headerParticle == null)
|
|
|
+ {
|
|
|
+ leftprt.headerParticle = rightprt.headerParticle;
|
|
|
+ mapMergeParticles[rightprt.headerParticle].Add(leftprt);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (leftprt.headerParticle != null)
|
|
|
+ {
|
|
|
+ rightprt.headerParticle = leftprt.headerParticle;
|
|
|
+ mapMergeParticles[leftprt.headerParticle].Add(rightprt[0]);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ rightprt.headerParticle = rightprt;
|
|
|
+ leftprt.headerParticle = rightprt;
|
|
|
+ mapMergeParticles[rightprt].Add(leftprt);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var pair in mapMergeParticles)
|
|
|
+ {
|
|
|
+
|
|
|
+
|
|
|
+ var newPart = new COTSParticle();
|
|
|
+ List<COTSSegment> newSegs = new List<COTSSegment>();
|
|
|
+ var p = pair.First();
|
|
|
+
|
|
|
+ //firstly,we sum up all the merged particles's area and get the represent string.
|
|
|
+ List<string> partsStr = p.GetFieldId() + ":" + p->GetAnalysisId();
|
|
|
+ double allPartArea = p.GetArea();//Get the first particle's area.
|
|
|
+
|
|
|
+
|
|
|
+ foreach (var other in pair.second)// Get the total area of all these particles for the use of ele calcu.
|
|
|
+ {
|
|
|
+ partsStr += "," + other->GetFieldId() + ":" + other->GetAnalysisId();//Get the subparticles string such as "1:1,2:1" etc.
|
|
|
+ allPartArea += other->GetArea();//Get other particle's area
|
|
|
+
|
|
|
+ }
|
|
|
+ // calculate all the new segment's position.
|
|
|
+ List<COTSParticle> allSubParts = new List<COTSParticle>();
|
|
|
+ allSubParts.Add(p);
|
|
|
+ foreach (var other in pair.second)// Get the total area of all these particles for the use of ele calcu.
|
|
|
+ {
|
|
|
+ allSubParts.Add(other.get());
|
|
|
+ }
|
|
|
+ foreach (var subp in allSubParts)
|
|
|
+ {
|
|
|
+ int fid = subp.GetFieldId();
|
|
|
+ Point myFldPos = new Point();
|
|
|
+ foreach (var f in allFields)//find this particle's filed.
|
|
|
+ {
|
|
|
+ if (f.GetId() == fid)
|
|
|
+ {
|
|
|
+ myFldPos = f.GetPosition();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ int fldWidth = Convert.ToInt32(allFields[0].Width);
|
|
|
+ int fldHeight = Convert.ToInt32(allFields[0].Height);
|
|
|
+ Point fldLeftUpPos = new Point(Convert.ToInt32(myFldPos.X + fldWidth / 2 * pixelSize), Convert.ToInt32(myFldPos.Y + fldHeight / 2 * pixelSize));
|
|
|
+ foreach (var s in subp.GetFeature().GetSegmentsList())
|
|
|
+ {
|
|
|
+ COTSSegment newseg = new COTSSegment();
|
|
|
+
|
|
|
+ newseg.SetStart((long)(s.GetStart() * pixelSize + fldLeftUpPos.X));
|
|
|
+ newseg.SetHeight((long)(0 - s.GetHeight() * pixelSize) + fldLeftUpPos.Y);//the coordinate system of segment in a field is different with the OTS coordinate system.OTS system's y axis is upward positive ,yet the field is downward positive.
|
|
|
+ newseg.SetLength(s.GetLength());
|
|
|
+ newSegs.Add(newseg);
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ COTSFeature newFeature = new COTSFeature();
|
|
|
+ newFeature.SetSegmentsList(newSegs, true);
|
|
|
+ newPart.SetFeature(newFeature);
|
|
|
+ newPart.CalCoverRect();
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ //second, we get all the element data and their area percentage .
|
|
|
+ Dictionary<string, List<EleAreaPercentage>> mapEleData = new Dictionary<string, List<EleAreaPercentage>>();
|
|
|
+
|
|
|
+ CPosXray pXray1 = p.GetXrayInfo();
|
|
|
+ foreach (var ele in pXray1.GetElementQuantifyData())
|
|
|
+ {
|
|
|
+ mapEleData[ele.GetName()].Add(EleAreaPercentage(p.GetArea() / allPartArea, ele));
|
|
|
+ }
|
|
|
+
|
|
|
+ foreach (var other in pair.second)
|
|
|
+ {
|
|
|
+ var otherXray = other.GetXrayInfo();
|
|
|
+ foreach (var eledata in otherXray->GetElementQuantifyData())
|
|
|
+ {
|
|
|
+ mapEleData[eledata.GetName().GetBuffer()].Add(EleAreaPercentage(other.GetArea() / allPartArea, eledata));
|
|
|
+
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // third,we calculate all the element's new percentage data and get a new element chemistry list.
|
|
|
+
|
|
|
+ List<CElementChemistry> newCheList = new List<CElementChemistry>();
|
|
|
+ foreach (var eledata in mapEleData)
|
|
|
+ {
|
|
|
+ CElementChemistry newEleche = new CElementChemistry();
|
|
|
+ newEleche.SetName(eledata.first);
|
|
|
+ double newPercentage = 0;
|
|
|
+ foreach (var d in eledata.second)
|
|
|
+ {
|
|
|
+ newPercentage += d.areaPercentage;
|
|
|
+ }
|
|
|
+ newEleche.SetPercentage(newPercentage);
|
|
|
+ newCheList.Add(newEleche);
|
|
|
+ }
|
|
|
+
|
|
|
+ CPosXray xray = new CPosXray();
|
|
|
+ xray.SetElementQuantifyData(newCheList);
|
|
|
+ newPart.SetXrayInfo(xray);
|
|
|
+ newPart.SetSubParticles(partsStr[0]);
|
|
|
+ newPart.SetArea(allPartArea);
|
|
|
+ newPart.SetTagId(mergedParts.Count);
|
|
|
+ newPart.SetAnalysisId(mergedParts.Count);
|
|
|
+ List<string> name = p.TypeName();
|
|
|
+ newPart.TypeName(name[0]);
|
|
|
+ newPart.TypeColor(p.TypeColor());
|
|
|
+ mergedParts.Add(newPart);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|
|
|
}
|