浏览代码

添加DoMeasure方法等。

sunyi 5 年之前
父节点
当前提交
9c74209a8a

+ 74 - 48
OTS/OTSModelSharp/Measure/GetBSEPic/MsrThreadStatus.cs

@@ -84,54 +84,80 @@ namespace OTSIncAMeasureApp.OTSMesureControl
 
         //BOOL operator ==(const CMsrThreadStatus&);					// ==operator
 
-     //   public void Serialize(bool isStoring,string XMLAdr)
-     //   {
-		   // XMLSerialization.xInt xnStatus=new XMLSerialization.xInt();
-     //       XMLSerialization.xTime_t xtimeStart=new XMLSerialization.xTime_t();
-     //       XMLSerialization.xOleDateTimeSpan xtimeUsed=new XMLSerialization.xOleDateTimeSpan();
-     //       XMLSerialization.xTime_t xtimeEnd=new XMLSerialization.xTime_t();
-     //       XMLSerialization.Collection<string> xSamples=new XMLSerialization.Collection<string>();
-     //       XMLSerialization.Slo slo=new XMLSerialization.Slo();
-
-     //       //slo.Register("CompletedFields", &xnStatus);
-		   // //slo.Register("timeStart", &xtimeStart);
-		   // //slo.Register("timeUsed", &xtimeUsed);
-		   // //slo.Register("timeEnd", &xtimeEnd);
-
-		   // if (isStoring)
-		   //{
-     //         xnStatus.AssignValue(int.Parse(m_nStatus.ToString())) ;
-     //         xtimeStart.AssignValue(m_timeStart);
-			  //xtimeUsed.AssignValue(m_timeUsed);
-			  //xtimeEnd.AssignValue(m_timeEnd);
-			  //xSamples.Clear();
-
-			  //foreach (var pSample in m_listCpldSamples)
-			  //{
-				 //xSamples.addItem(pSample);
-			  //}
-
-     //         slo.Serialize(true, classDoc, rootNode);
-		   //}
-		   //else
-		   //{
-     //           XmlDocument xml = new XmlDocument();
-     //           xml.Load(XMLAdr);
-
-     //           XmlNode root = xml.SelectSingleNode("XMLData");
-
-     //           m_nStatus = (OTS_MSR_THREAD_STATUS)int.Parse(root.Attributes["CompletedFields"].Value);
-     //           m_timeStart = Convert.ToDateTime(root.Attributes["timeStart"].Value);
-     //           m_timeUsed = TimeSpan.Parse(root.Attributes["timeUsed"].Value);
-     //           m_timeEnd = Convert.ToDateTime(root.Attributes["timeEnd"].Value);
-     //           m_listCpldSamples.Clear();
-
-     //           for (int i = 0; i<xSamples.size ();i++)
-			  // {
-				 // m_listCpldSamples.Add(xSamples.getItem (i));     //shared_ptr xSamples无用了?是否删除?
-     //           }
-		   // }
-	    //}
+        //   public void Serialize(bool isStoring,string XMLAdr)
+        //   {
+        // XMLSerialization.xInt xnStatus=new XMLSerialization.xInt();
+        //       XMLSerialization.xTime_t xtimeStart=new XMLSerialization.xTime_t();
+        //       XMLSerialization.xOleDateTimeSpan xtimeUsed=new XMLSerialization.xOleDateTimeSpan();
+        //       XMLSerialization.xTime_t xtimeEnd=new XMLSerialization.xTime_t();
+        //       XMLSerialization.Collection<string> xSamples=new XMLSerialization.Collection<string>();
+        //       XMLSerialization.Slo slo=new XMLSerialization.Slo();
+
+        //       //slo.Register("CompletedFields", &xnStatus);
+        // //slo.Register("timeStart", &xtimeStart);
+        // //slo.Register("timeUsed", &xtimeUsed);
+        // //slo.Register("timeEnd", &xtimeEnd);
+
+        // if (isStoring)
+        //{
+        //         xnStatus.AssignValue(int.Parse(m_nStatus.ToString())) ;
+        //         xtimeStart.AssignValue(m_timeStart);
+        //xtimeUsed.AssignValue(m_timeUsed);
+        //xtimeEnd.AssignValue(m_timeEnd);
+        //xSamples.Clear();
+
+        //foreach (var pSample in m_listCpldSamples)
+        //{
+        //xSamples.addItem(pSample);
+        //}
+
+        //         slo.Serialize(true, classDoc, rootNode);
+        //}
+        //else
+        //{
+        //           XmlDocument xml = new XmlDocument();
+        //           xml.Load(XMLAdr);
+
+        //           XmlNode root = xml.SelectSingleNode("XMLData");
+
+        //           m_nStatus = (OTS_MSR_THREAD_STATUS)int.Parse(root.Attributes["CompletedFields"].Value);
+        //           m_timeStart = Convert.ToDateTime(root.Attributes["timeStart"].Value);
+        //           m_timeUsed = TimeSpan.Parse(root.Attributes["timeUsed"].Value);
+        //           m_timeEnd = Convert.ToDateTime(root.Attributes["timeEnd"].Value);
+        //           m_listCpldSamples.Clear();
+
+        //           for (int i = 0; i<xSamples.size ();i++)
+        // {
+        // m_listCpldSamples.Add(xSamples.getItem (i));     //shared_ptr xSamples无用了?是否删除?
+        //           }
+        // }
+        //}
+
+        public bool Equals(CMsrThreadStatus a_oSource)          // CBSEImg& operator=(const CBSEImg&);        // =operator
+        {
+
+            // return FASLE, if the two center list are in different size
+            int nSize = m_listCpldSamples.Count;
+            if (nSize != a_oSource.m_listCpldSamples.Count)
+            {
+                return false;
+            }
+
+            // return FALSE if any of the center are different
+            for (int i = 0; i < nSize; ++i)
+            {
+                if (m_listCpldSamples[i].Equals(a_oSource.m_listCpldSamples[i]))
+                {
+                    return false;
+                }
+            }
+
+            return m_nStatus == a_oSource.m_nStatus &&
+                m_timeStart == a_oSource.m_timeStart &&
+                m_timeUsed == a_oSource.m_timeUsed &&
+                m_timeStart == a_oSource.m_timeStart;
+                
+        }
         // status
         public OTS_MSR_THREAD_STATUS GetStatus()
         {

+ 2 - 0
OTS/OTSModelSharp/Measure/GetBSEPic/OTSFieldMgr.cs

@@ -59,7 +59,9 @@ namespace OTSModelSharp
 
         double m_dArea;
 
+        // CFieldMgr command target
 
+      
 
         //-------------public-----------------
 

+ 720 - 93
OTS/OTSModelSharp/Measure/GetBSEPic/SmplMeasure.cs

@@ -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;
+        }
     }
 }

+ 14 - 14
OTS/OTSModelSharp/OTSDataType/COTSFieldData.cs

@@ -21,11 +21,11 @@ namespace OTSDataType
 
         List<COTSParticle> m_listParticles = new List<COTSParticle>();
 
-        List<COTSParticle> m_listBigParticles = new List<COTSParticle>();
+       List< List<COTSParticle>> m_listBigParticles = new List<List<COTSParticle>>();
 
-        long Height;
+        public long Height;
 
-        long Width;
+        public long Width;
         // particle list
 
         public COTSFieldData()
@@ -144,7 +144,7 @@ namespace OTSDataType
         }
 
         // particle list
-       public List< COTSParticle> GetBigParticleList()
+       public List<List< COTSParticle>> GetBigParticleList()
         {
             return m_listBigParticles;
         }
@@ -173,12 +173,12 @@ namespace OTSDataType
             foreach (var p in m_listBigParticles)
             {
                
-                var segs = p.GetFeature().GetSegmentsList();//COTSSegment
+                var segs = p[0].GetFeature().GetSegmentsList();//COTSSegment
                 foreach (var seg in segs)
                 {
                     if (seg.GetHeight() == 0)
                     {
-                        parts.Add(p);
+                        parts.Add(p[0]);
                         break;
                     }
                 }
@@ -186,12 +186,12 @@ namespace OTSDataType
             return parts;
         }
 
-        public List< COTSParticle > GetBottomBorderedBigParticles()
+        public List< List< COTSParticle >> GetBottomBorderedBigParticles()
         {
-            List<COTSParticle> parts = new List<COTSParticle>();
+           List< List<COTSParticle>> parts = new List<List<COTSParticle>>();
             foreach (var p in m_listBigParticles)
             {
-                var segs = p.GetFeature().GetSegmentsList();
+                var segs = p[0].GetFeature().GetSegmentsList();
                 foreach (var seg in segs)
                 {
                     if (seg.GetHeight() == this.Height - 1)//the lowest height is 767(height-1),cause starting from 0.
@@ -210,12 +210,12 @@ namespace OTSDataType
             List<COTSParticle> parts = new List<COTSParticle>();
             foreach (var p in m_listBigParticles)
             {
-                var segs = p.GetFeature().GetSegmentsList();
+                var segs = p[0].GetFeature().GetSegmentsList();
                 foreach (var seg in segs)
                 {
                     if (seg.GetStart() == 0)
                     {
-                        parts.Add(p);
+                        parts.Add(p[0]);
                         break;
                     }
 
@@ -224,12 +224,12 @@ namespace OTSDataType
             return parts;
         }
 
-        public  List <COTSParticle> GetRightBorderedBigParticles()
+        public List< List <COTSParticle>> GetRightBorderedBigParticles()
         {
-            List<COTSParticle> parts = new List<COTSParticle>();
+           List< List<COTSParticle>> parts = new List< List<COTSParticle>>();
             foreach (var p in m_listBigParticles)
             {
-                var segs = p.GetFeature().GetSegmentsList();
+                var segs = p[0].GetFeature().GetSegmentsList();
                 foreach (var seg in segs)
                 {
                     if (seg.GetStart() + seg.GetLength() == this.Width)

+ 3 - 3
OTS/OTSModelSharp/OTSDataType/OTSParticle.cs

@@ -615,13 +615,13 @@ namespace OTSDataType
         	UP = 4
         }
 
-        public bool IsConnected(COTSParticle a_p, int fldwidth, int fldheight, int direction)
+        public bool IsConnected(List<COTSParticle> a_p, int fldwidth, int fldheight, int direction)
         {
             //decide if two on boundary particles are connected.
             SORTING_DIRECTION di = (SORTING_DIRECTION)direction;
             foreach (var s in m_pFeature.GetSegmentsList())
             {
-                foreach (var a_seg in a_p.GetFeature().GetSegmentsList())
+                foreach (var a_seg in a_p[direction].GetFeature().GetSegmentsList())
                 {
                     if (di == SORTING_DIRECTION.LEFT || di == SORTING_DIRECTION.RIGHT)
                     {
@@ -669,7 +669,7 @@ namespace OTSDataType
 
         }
 
-        public COTSParticle headerParticle; //used to merge particles ,if this particle has been merged then this pointer will point to the first particle of these merged particles else it's NULL.
+        public List<COTSParticle> headerParticle; //used to merge particles ,if this particle has been merged then this pointer will point to the first particle of these merged particles else it's NULL.
 
         // cleanup
         //protected void Cleanup()

+ 1 - 0
OTS/OTSModelSharp/OTSModelSharp.csproj

@@ -89,6 +89,7 @@
     <Compile Include="ARACrypt.cs" />
     <Compile Include="COTSEDSBrucker.cs" />
     <Compile Include="COTSHardwareMgr.cs" />
+    <Compile Include="COTSScanBase.cs" />
     <Compile Include="CProjMgr.cs" />
     <Compile Include="CSmallParticleInfo.cs" />
     <Compile Include="CStdioFile.cs" />