using OTSCLRINTERFACE; using OTSMeasureApp._0_OTSModel.OTSDataType; using OTSModelSharp; using OTSModelSharp.ServiceCenter; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Xml; namespace OTSDataType { public class COTSField : ISlo { public COTSField leftField = null; public COTSField upField = null; public COTSField downField = null; public COTSField rightField = null; public List particleImages = new List(); protected NLog.Logger log; // ID int m_nID; int measureSequence; private bool m_enable=true; // position (from field center manager) protected System.Drawing.PointF m_otsPos; protected CBSEImgClr m_pBSEImg; protected double m_pixelSize; protected CImageHandler m_ImagePro; protected List m_listAllParticles = new List();//hold up all the particles abstracted from bse image; protected List m_listAnalysisParticles = new List();// according to xraylimit constraint,pick out the first big particles. protected List m_listXrayParticles = new List();//hold up all the particles that needing the xray data. private int imgheight; private int imgwidth; private COTSRect m_otsRect; private COTSSample m_sample; public COTSField() { log = NLog.LogManager.GetCurrentClassLogger(); Init(); }//only using in xmlserialization public int ImgHeight { get => imgheight; set => imgheight = value; } public int ImgWidth { get => imgwidth; set => imgwidth = value; } public COTSSample Sample { get => m_sample; set => m_sample = value; } public bool Enable { get => m_enable; set => m_enable = value; } internal COTSRect GetOTSRect() { return m_otsRect; } internal void SetOTSRect(COTSRect value) { m_otsRect = value; } public int GetMeasureSequence() { return measureSequence; } public void SetMeasureSequence(int value) { measureSequence = value; } public List strKeyName; public bool GetIsMeasureComplete() { return isMeasureComplete; } public void SetIsMeasureComplete(bool value) { isMeasureComplete = value; } private bool isMeasureComplete; public PointF GetSemPos() { return m_semPos; } public void SetSemPos(PointF value) { m_semPos = value; } private PointF m_semPos; public List GetAllParticles() { return m_listAllParticles; } public List GetListAnalysisParticles() { return m_listAnalysisParticles; } public List GetListXrayParticles() { m_listXrayParticles.Clear(); foreach (var p in m_listAnalysisParticles) { if (p.IsXrayParticle()) { m_listXrayParticles.Add(p); } } return m_listXrayParticles; } public void SetListAnalysisParticles(List value) { m_listAnalysisParticles = value; } public COTSField(PointF centerPoint, double a_dPixelSize) { log = NLog.LogManager.GetCurrentClassLogger(); Init(); m_otsPos = centerPoint; m_pixelSize = a_dPixelSize; } public double GetPixelSize() { return m_pixelSize; } public void SetPixelSize(double size) { m_pixelSize = size; } // initialization void Init() { // initialization m_nID = -1; m_otsPos = new System.Drawing.Point(0, 0); m_listAllParticles.Clear(); m_enable = true; } public COTSField(COTSField a_poSource) { // can't copy itself if (a_poSource == this) { return; } Duplicate(a_poSource); } public CBSEImgClr GetBSEImage() { return m_pBSEImg; } public Bitmap GetAnalysisParticleBlackColoredImage() { CImageHandler imghandler = new CImageHandler(); List Parts = GetAllParticles(); Bitmap img = new Bitmap(this.ImgWidth, this.ImgHeight); var imgparam = m_sample.GetMsrParams().GetImageProcessParam(); var pixelsize = m_sample.CalculatePixelSize(); imghandler.GetImageWithBlackColoredParts(Parts,imgparam,pixelsize, ref img); return img; } public Bitmap GetAnalysisParticleSTDColoredImage() { CImageHandler imghandler = new CImageHandler(); List Parts = GetListAnalysisParticles(); Bitmap img = new Bitmap(this.ImgWidth, this.ImgHeight); var imgparam = m_sample.GetMsrParams().GetImageProcessParam(); var pixelsize = m_sample.CalculatePixelSize(); imghandler.GetImageWithSTDColoredParts(Parts, imgparam, pixelsize, ref img); return img; } public void SetBSEImage(CBSEImgClr a_pBSEImg) { if (a_pBSEImg == null) { // invalid BSE image. log.Error("SetBSEImage: invalid BSE image."); return; } m_pBSEImg = a_pBSEImg; imgwidth = a_pBSEImg.GetWidth(); imgheight = a_pBSEImg.GetHeight(); } public void GetOriginalParticles(CSampleParam pMsrParam, double pixelsize) { COTSImageProcParam pImgProcessParam = pMsrParam.GetImageProcessParam(); // remove BES image background RemoveImgBGAndGetParticles(pImgProcessParam, pixelsize); var specialPartsparam = pMsrParam.GetSpecialGrayRangeParam(); if (specialPartsparam != null && specialPartsparam.GetIsToRun()) { List ranges = specialPartsparam.GetSpecialGreyRanges(); foreach (var grayRange in ranges) { CIntRangeClr range = new CIntRangeClr(grayRange.range.GetStart(), grayRange.range.GetEnd()); CDoubleRangeClr diaRange = new CDoubleRangeClr(grayRange.diameterRange.GetStart(), grayRange.diameterRange.GetEnd()); GetPartsBySpecialGray(range, diaRange, pixelsize, grayRange.ifCollectXray); } } log.Info("Find all particle num:" + GetAllParticles().Count); return; } private void RemoveImgBGAndGetParticles(COTSImageProcParam a_pImageProcessParam, double a_pixelSize) { if (m_pBSEImg == null) return; CImageHandler imghandler = new CImageHandler(); List allParts = new List(); imghandler.RemoveBGAndGetParts(this, a_pImageProcessParam, ref allParts); m_listAllParticles = allParts; return; } class particleCompOnArea : IComparer { public int Compare(COTSParticleClr x, COTSParticleClr y) { return y.GetActualArea().CompareTo(x.GetActualArea());//descending sort } } public void FilterParticles(COTSXRayParam pXRayParam) { log.Info("filter particle according to xraylimit and outermost border"); m_listAllParticles.Sort(new particleCompOnArea()); var listXray1 = new List(); if (m_listAllParticles.Count > pXRayParam.GetXrayLimit()) { for (var i = 0; i < pXRayParam.GetXrayLimit(); i++) { var part = m_listAllParticles[i]; int l=0, r=0, t=0, b=0; part.GetOTSRect(ref l, ref t,ref r, ref b); COTSRect otsrec = new COTSRect(l, t, r, b); PointF p1 = otsrec.GetCenterPoint(); if (m_sample.IsThisPointInMeasureArea(new Point((int)p1.X, (int)p1.Y))) { listXray1.Add(m_listAllParticles[i]); } } } else { foreach (var p in m_listAllParticles) { var part = p; int l = 0, r = 0, t = 0, b = 0; part.GetOTSRect(ref l, ref t, ref r, ref b); COTSRect otsrec = new COTSRect(l, t, r, b); PointF p1 = otsrec.GetCenterPoint(); if (m_sample.IsThisPointInMeasureArea(new Point((int)p1.X, (int)p1.Y))) { listXray1.Add(p); } } } SetListAnalysisParticles(listXray1); log.Info("Xray Analysis particles:" + listXray1.Count); } public void SelectParticlesAccordingImgProp(COTSImageProcParam a_pImageProcessParam) { var selconditiondic = a_pImageProcessParam.GetParticleSelConditionDic(); var listselparts = new List(); var excludeparts = new List(); if (selconditiondic.ContainsKey("dmax")) { log.Info("Select particles according to dmax"); var rng = selconditiondic["dmax"]; foreach (var p in GetListAnalysisParticles()) { if (p.GetDMAX() < rng.GetStart() || p.GetDMAX() >= rng.GetEnd()) { excludeparts.Add(p); } else { //log.Info("dmax=" + p.GetDMAX().ToString("F2")); } } } if (selconditiondic.ContainsKey("dmin")) { log.Info("Select particles according to dmin"); var rng = selconditiondic["dmin"]; foreach (var p in GetListAnalysisParticles()) { if (p.GetDMIN() < rng.GetStart() || p.GetDMIN() >= rng.GetEnd()) { if (!excludeparts.Contains(p)) { excludeparts.Add(p); } else { //log.Info("dmin=" + p.GetDMIN().ToString("F2")); } } } } if (selconditiondic.ContainsKey("orientation")) { log.Info("Select particles according to orientation"); var rng = selconditiondic["orientation"]; foreach (var p in GetListAnalysisParticles()) { if (p.GetORIENTATION() < rng.GetStart() || p.GetORIENTATION() >= rng.GetEnd()) { if (!excludeparts.Contains(p)) { excludeparts.Add(p); } else { //log.Info("orientation=" + p.GetORIENTATION().ToString("F2")); } } } } if (selconditiondic.ContainsKey("aspect")) { log.Info("Select particles according to aspect"); var rng = selconditiondic["aspect"]; foreach (var p in GetListAnalysisParticles()) { double aspect = p.GetDMAX() / p.GetDMIN(); if (aspect < rng.GetStart() || aspect >= rng.GetEnd()) { if (!excludeparts.Contains(p)) { excludeparts.Add(p); } else { //log.Info("aspect=" + aspect.ToString("F2")); } } } } if (selconditiondic.ContainsKey("ferret")) { log.Info("Select particles according to ferret"); var rng = selconditiondic["ferret"]; foreach (var p in GetListAnalysisParticles()) { double dferet = p.GetFeretDiameter(); if (dferet < rng.GetStart() || dferet >= rng.GetEnd()) { if (!excludeparts.Contains(p)) { excludeparts.Add(p); } else { //log.Info("ferret=" + dferet.ToString("F2")); } } } } foreach (var p in GetListAnalysisParticles()) { if (!excludeparts.Contains(p)) { listselparts.Add(p); } } SetListAnalysisParticles(listselparts); log.Info("Analysis particles:" + listselparts.Count); } public void RemoveDuplicateOverlapParticles(int overlap) { List finalparts = new List(); List duplicateparts = new List(); //find left side duplicate particles var leftparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); if (leftField != null && leftField.measureSequence < this.measureSequence) { var rightsideparts = leftField.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); if (leftField.upField != null && leftField.upField.measureSequence < this.measureSequence)//include the left up corner parts { var leftupParts = leftField.upField.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); rightsideparts.AddRange(leftupParts); } if (leftField.downField != null && leftField.downField.measureSequence < this.measureSequence)//include the left down corner parts { var leftdownParts = leftField.downField.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); rightsideparts.AddRange(leftdownParts); } log.Info("left side particles num:" + leftparts.Count.ToString()); foreach (var p in leftparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); foreach (var p1 in rightsideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove left side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); duplicateparts.Add(p); break; } } } } } //find up side duplicate particles var upparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.UP, overlap); if (upField != null && upField.measureSequence < this.measureSequence) { var othersideparts = upField.GetSideParticlesByOverlap(SORTING_DIRECTION.DOWN, overlap); log.Info("up side particles num:" + upparts.Count.ToString()); foreach (var p in upparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove upside duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); duplicateparts.Add(p); break; } } } } } //find right side duplicate particles var rightparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.RIGHT, overlap); if (rightField != null && rightField.measureSequence < this.measureSequence) { log.Info("right side particles num:" + rightparts.Count.ToString()); var othersideparts = rightField.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); if (rightField.upField != null && rightField.upField.measureSequence < this.measureSequence)// right up corner parts { var rightupParts = rightField.upField.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); othersideparts.AddRange(rightupParts); } if (rightField.downField != null && leftField.downField.measureSequence < this.measureSequence)// rightdown corner parts { var rightdownParts = leftField.downField.GetSideParticlesByOverlap(SORTING_DIRECTION.LEFT, overlap); othersideparts.AddRange(rightdownParts); } foreach (var p in rightparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove right side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); duplicateparts.Add(p); break; } } } } } //find down side duplicate particles var downparts = this.GetSideParticlesByOverlap(SORTING_DIRECTION.DOWN, overlap); if (downField != null && downField.measureSequence < this.measureSequence) { log.Info("down side particles num:" + downparts.Count.ToString()); var othersideparts = downField.GetSideParticlesByOverlap(SORTING_DIRECTION.UP, overlap); foreach (var p in downparts) { int pleft = 0, pright = 0, ptop = 0, pbottom = 0; p.GetOTSRect(ref pleft, ref ptop, ref pright, ref pbottom); COTSRect prec = new COTSRect(pleft, ptop, pright, pbottom); PointF pcenter = prec.GetCenterPoint(); foreach (var p1 in othersideparts) { int p1left = 0, p1right = 0, p1top = 0, p1bottom = 0; p1.GetOTSRect(ref p1left, ref p1top, ref p1right, ref p1bottom); COTSRect p1rec = new COTSRect(p1left, p1top, p1right, p1bottom); PointF p1Center = p1rec.GetCenterPoint(); if (Math.Abs(pcenter.X - p1Center.X) < 2 * overlap && Math.Abs(pcenter.Y - p1Center.Y) < 2 * overlap) { var sim = p.CalculateSimilarity(p1); if (sim > 0.95) { log.Warn("remove down side duplicate particle,similarity:" + sim.ToString("F3")); log.Warn("P1:" + p.GetImgPortraitString()); log.Warn("P2:" + p1.GetImgPortraitString()); duplicateparts.Add(p); break; } } } } } foreach (var p in leftparts) { if (duplicateparts.Contains(p)) { continue; } if (!finalparts.Contains(p)) { finalparts.Add(p); } } foreach (var p in upparts) { if (duplicateparts.Contains(p)) { continue; } if (!finalparts.Contains(p)) { finalparts.Add(p); } } foreach (var p in rightparts) { if (duplicateparts.Contains(p)) { continue; } if (!finalparts.Contains(p)) { finalparts.Add(p); } } foreach (var p in downparts) { if (duplicateparts.Contains(p)) { continue; } if (!finalparts.Contains(p)) { finalparts.Add(p); } } foreach (var p in this.GetSideParticlesByOverlap(SORTING_DIRECTION.CENTER, overlap)) { if (!finalparts.Contains(p)) { finalparts.Add(p); } } this.SetListAnalysisParticles(finalparts); log.Info("removing duplicate particles result:" + finalparts.Count); } private List GetSideParticlesByOverlap(SORTING_DIRECTION direction, int overlap) { List sideparts = new List(); var borderedparts = this.GetBorderedParticles(); if (direction == SORTING_DIRECTION.LEFT) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if (Math.Abs(right - this.GetOTSRect().GetTopLeft().X) < 2 * overlap) { if (!borderedparts.Contains(p) || Math.Abs(left - right) > 2 * overlap)//not on the border or it's a big particle { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.RIGHT) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if (Math.Abs(this.GetOTSRect().GetBottomRight().X - left) < 2 * overlap) { if (!borderedparts.Contains(p) || Math.Abs(left - right) > 2 * overlap)//not on the border or is a big part { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.UP) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if (Math.Abs(this.GetOTSRect().GetTopLeft().Y - bottom) < 2 * overlap) { if (!borderedparts.Contains(p) || Math.Abs(top - bottom) > 2 * overlap)//not on the border { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.DOWN) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); if (Math.Abs(top - this.GetOTSRect().GetBottomRight().Y) < 2 * overlap) { if (!borderedparts.Contains(p) || Math.Abs(top - bottom) > 2 * overlap)//not on the border { sideparts.Add(p); } } } } if (direction == SORTING_DIRECTION.CENTER) { foreach (var p in this.GetListAnalysisParticles()) { int left = 0, top = 0, right = 0, bottom = 0; p.GetOTSRect(ref left, ref top, ref right, ref bottom); var fldrec = this.GetOTSRect(); int fldleft = (int)fldrec.GetTopLeft().X; int fldright = (int)fldrec.GetBottomRight().X; int fldtop = (int)fldrec.GetTopLeft().Y; int fldbottom = (int)fldrec.GetBottomRight().Y; if ((Math.Abs(top - fldtop) > 2 * overlap) && (Math.Abs(fldbottom - bottom) > 2 * overlap) && (Math.Abs(left - fldleft) > 2 * overlap) && (Math.Abs(fldright - right) > 2 * overlap)) { sideparts.Add(p); } } } return sideparts; } public void GetPartsBySpecialGray(CIntRangeClr grayRange, CDoubleRangeClr diameterRange, double pixelSize, bool ifXray) { if (m_pBSEImg == null) return; CImageHandler imghandler = new CImageHandler(); List specialParts = new List(); imghandler.GetParticlesBySpecialGray(m_pBSEImg, grayRange, diameterRange, pixelSize, ref specialParts); foreach (var p in specialParts) { p.SetIsXrayParticle(ifXray); m_listAllParticles.Add(p); } return; } public bool CalParticleImageProp(List particles) { m_ImagePro = new CImageHandler(); foreach (COTSParticleClr part in particles) { m_ImagePro.CalParticleImageProp(part, m_pixelSize); } return true; } public void CalculateParticleAbsolutPos(CSEMStageData pCSEMStageData) { foreach (var p in GetListAnalysisParticles()) { PointF semP = new PointF(); ; Point semPos = new Point(); pCSEMStageData.ConvertOTSToSEMCoord(GetOTSPosition(), ref semP); semPos.X = (int)semP.X; semPos.Y = (int)semP.Y; p.SetSEMPos(semPos); } } public void InitParticles(COTSImageProcParam a_pImageProcessParam) { // get area range CDoubleRange oAreaRange = a_pImageProcessParam.GetIncAreaRange(); double rMin = oAreaRange.GetStart() / 2.0; double rMax = oAreaRange.GetEnd() / 2.0; int nTagId = 0; foreach (COTSParticleClr pParticle in m_listAnalysisParticles)//m_listAllParticles memorize all the particles . { pParticle.SetParticleId(nTagId);//give all the conforming particles a unified sequence no. pParticle.SetFieldId(GetId()); pParticle.SetType((int)otsdataconst.OTS_PARTICLE_TYPE.NO_ANALYSIS_X_RAY); pParticle.SetTypeName("Not Identified"); pParticle.SetAnalysisId(nTagId); // the same as the tagId no use now. nTagId++; } log.Info("Total analysis Particles: (>" + rMin.ToString("f2") + "): " + "<" + rMax.ToString("f2") + "): " + m_listAnalysisParticles.Count); } public bool CreateXrayList(List a_listParticles) { foreach (COTSParticleClr pPart in a_listParticles) { System.Drawing.Point poi = (System.Drawing.Point)pPart.GetXRayPos(); CPosXrayClr pPosXray = new CPosXrayClr(); pPosXray.SetPosition(poi); pPosXray.SetPartTagId(pPart.GetParticleId()); pPosXray.SetIndex(pPart.GetAnalysisId()); pPosXray.SetScanFieldId(pPart.GetFieldId()); pPart.SetXray(pPosXray); } return true; } public void ClearAllMeausredData() { m_listAllParticles.Clear(); m_listAnalysisParticles.Clear(); m_listXrayParticles.Clear(); m_pBSEImg = null; } public bool PositionEquals(COTSField a_oSource) { if (a_oSource.m_otsPos == this.m_otsPos) { return true; } else { return false; } } // ID public int GetId() { return m_nID; } public void SetId(int a_nID) { m_nID = a_nID; } // position (from field center manager) public System.Drawing.PointF GetOTSPosition() { return m_otsPos; } public void SetOTSPosition(System.Drawing.PointF a_poiPos) { m_otsPos = a_poiPos; } public List GetTopBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList();//COTSSegment foreach (var seg in segs) { if (seg.GetHeight() == 0) { parts.Add(p); break; } } } return parts; } public List GetBottomBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetHeight() == this.ImgHeight - 1)//the lowest height is 767(height-1),cause starting from 0. { parts.Add(p); break; } } } return parts; } public List GetBorderedParticles() { List parts = new List(); var leftparts = this.GetLeftBorderedParticles(); var rightp = this.GetRightBorderedParticles(); var topp = this.GetTopBorderedParticles(); var bottomp = this.GetBottomBorderedParticles(); foreach (var p in leftparts) { if (!parts.Contains(p)) { parts.Add(p); } } foreach (var p in rightp)// { if (!parts.Contains(p)) { parts.Add(p); } } foreach (var p in topp) { if (!parts.Contains(p))//there may be some particles connect to both the left and top. { parts.Add(p); } } foreach (var p in bottomp) { if (!parts.Contains(p)) { parts.Add(p); } } return parts; } public List GetLeftBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetStart() == 0) { parts.Add(p); break; } } } return parts; } public List GetRightBorderedParticles() { List parts = new List(); foreach (var p in m_listAnalysisParticles) { var segs = p.GetFeature().GetSegmentsList(); foreach (var seg in segs) { if (seg.GetStart() + seg.GetLength() == this.ImgWidth) { parts.Add(p); break; } } } return parts; } // is empty public bool IsEmpty() { return m_listAllParticles.Count == 0; } void Duplicate(COTSField a_oSource) { m_nID = a_oSource.m_nID; m_otsPos = a_oSource.m_otsPos; // copy data over foreach (var pParticle in a_oSource.m_listAllParticles) { m_listAllParticles.Add(pParticle); } } public override void Serialize(bool isStoring, XmlDocument classDoc, XmlNode rootNode) { xPoint xPos = new xPoint(); xBool xenable = new xBool(); Slo slo = new Slo(); slo.Register("OTSPosition", xPos); slo.Register("Enable", xenable); if (isStoring) { xPos.AssignValue(new System.Drawing.Point((int)m_otsPos.X, (int)m_otsPos.Y)); xenable.AssignValue(this.Enable); slo.Serialize(true, classDoc, rootNode); } else { slo.Serialize(false, classDoc, rootNode); m_otsPos = xPos.value(); this.Enable=xenable.value(); } } } }