using OpenCvSharp; using OTSCLRINTERFACE; using OTSCommon.Model; using OTSIncAReportApp.DataOperation.DataAccess; using OTSIncAReportGraph.Controls; using OTSModelSharp.DTLBase; using OTSModelSharp.ServiceCenter; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.IO; using System.Linq; using System.Runtime.Serialization.Formatters.Binary; using Point = System.Drawing.Point; namespace OTSIncAReportGraph.OTSIncAReportGraphFuncation { public class OTSImageDisHelp { #region 枚举定义 #endregion #region 定义变量 public ResultFile resultFile = null; public ParticleSegmentation m_ParticleSegmentation; public Point OTSLeftBottomPoint; public Point OTSRightUpPoint; public RectangleF m_originalBackRect; public double m_pixelSize; private List fieldCenterList; NLog.Logger log; //电镜设置对象 public ServiceInterface.HardwareController m_cfun = null; #endregion #region 构造函数 public OTSImageDisHelp( ResultFile result) { resultFile = result; m_cfun = ServiceInterface.HardwareController.GetSemController(); List fieldlist = resultFile.List_OTSField; int fieldwidth; SizeF s = GetFieldImageSize(); fieldwidth = (int)s.Width; fieldCenterList = new List(); for (int i = 0; i < fieldlist.Count(); i++) { Point ls_point = new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY }; fieldCenterList.Add(ls_point); } SizeF physicalfiledsize = GetPhysicalFieldWidthAndHeight(); m_pixelSize = Convert.ToDouble(physicalfiledsize.Width) / Convert.ToDouble(fieldwidth); OTSLeftBottomPoint = GetOTSCoordLeftBottomPoint(fieldCenterList, (int)physicalfiledsize.Width, (int)physicalfiledsize.Height); OTSRightUpPoint = GetOTSCoordRightUpPoint(fieldCenterList, (int)physicalfiledsize.Width, (int)physicalfiledsize.Height); m_originalBackRect = new RectangleF(0, 0, (float)((OTSRightUpPoint.X - OTSLeftBottomPoint.X)/m_pixelSize), (float)((OTSRightUpPoint.Y - OTSLeftBottomPoint.Y)/m_pixelSize)); log = NLog.LogManager.GetCurrentClassLogger(); } #endregion #region 封装自定义方法 private Point GetOTSCoordLeftBottomPoint(List allFldPos,int fieldwidth,int fieldheight) { //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the smallest point. //找出最小的x,y用来做偏移运算 int i_offset_x = 1000000000; int i_offset_y = 1000000000; //先取出最小的x,y for (int i = 0; i < allFldPos.Count; i++) { if (i_offset_x > allFldPos[i].X) { i_offset_x = allFldPos[i].X; } if (i_offset_y > allFldPos[i].Y) { i_offset_y = allFldPos[i].Y; } } return new Point(i_offset_x-fieldwidth/2, i_offset_y-fieldheight/2);//the field pos is the center point position. } private Point GetOTSCoordRightUpPoint(List allFldPos, int fieldwidth, int fieldheight) { //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the biggest point. //找出最小的x,y用来做偏移运算 int i_offset_x = -1000000000; int i_offset_y = -1000000000; //先取出最小的x,y for (int i = 0; i < allFldPos.Count; i++) { if (i_offset_x < allFldPos[i].X) { i_offset_x = allFldPos[i].X; } if (i_offset_y < allFldPos[i].Y) { i_offset_y = allFldPos[i].Y; } } return new Point(i_offset_x + fieldwidth / 2, i_offset_y + fieldheight / 2);//the field pos is the center point position. } public Point ConvertOTSCoordToScreenCoord( Point currenFldOTSPos)// { var OTSPoint=new Point(currenFldOTSPos.X - OTSLeftBottomPoint.X, currenFldOTSPos.Y - OTSLeftBottomPoint.Y); int screenHeight = (int)m_originalBackRect.Height + (0 - (int)(Convert.ToDouble(OTSPoint.Y) / m_pixelSize));//because the screen coordinate is downward rightward positive,so we need to translate the Y coordinate of the OTS system which is upward rightward positive. var screenPoint = new Point((int)(Convert.ToDouble(OTSPoint.X)/m_pixelSize), (int)(screenHeight)); //var curP = new Point((int)(screenPoint.X + m_wholeBackRect.X), (int)(screenPoint.Y + m_wholeBackRect.Y)); var curP = new Point((int)(screenPoint.X + m_originalBackRect.X), (int)(screenPoint.Y + m_originalBackRect.Y)); return curP; } public SizeF GetPhysicalFieldWidthAndHeight() { SizeF ret_rect = new SizeF(0, 0); int width = resultFile.GetImageWidth(); int height = resultFile.GetImageHeight(); double retioOfHeightWidth =(double) height; retioOfHeightWidth /= width; //string scanfeldsize = resultFile.GetScanFieldSizeX(); double d_scanFieldSize_width = resultFile.GetScanFieldSizeX(); double d_scanFieldSize_height = 0; if (d_scanFieldSize_width != 0) d_scanFieldSize_height = d_scanFieldSize_width * retioOfHeightWidth; ret_rect.Width = (int)d_scanFieldSize_width; ret_rect.Height = (int)d_scanFieldSize_height; return ret_rect; } public SizeF GetFieldImageSize() { SizeF s = new SizeF(); int width = resultFile.GetImageWidth(); int height = resultFile.GetImageHeight(); s.Width = width; s.Height = height; return s; } #endregion #region 电镜操作相关方法 /// /// 连接电镜,分布图使用 /// public bool ConnectToIpcSvr() { //和电镜建立通讯连接 return m_cfun.Connect(); } /// /// 移动电镜到指定的X,Y坐标上,R坐标使用原先的值进行移动 /// /// /// public void MoveSemToPointXY(double in_PositionX, double in_PositionY) { log.Trace("Begin MoveSemToPointXY:(" +in_PositionX.ToString()+","+in_PositionY.ToString()+")"); //首先获取电镜当前的位置,并记录原R值 double ls_PositionX = 0; double ls_PositionY = 0; double ls_PositionR = 0; if (m_cfun.Connect()) { m_cfun.GetSemPositionXY(ref ls_PositionX, ref ls_PositionY, ref ls_PositionR); } else { log.Error("Failed to GetSemPositionXY"); return; } if (m_cfun.Connect()) { m_cfun.MoveSEMToPoint(new Point((int)in_PositionX, (int)in_PositionY), ls_PositionR); } } #endregion #region //--------------------------------------颗粒分布图相关部份--------------------------------------------------------------------- /// /// 传入颗粒的tagid和fieldid,来获取该颗粒下对应的xray数据 /// /// /// /// /// public void GetXrayByParticleTagIDAndFieldID_ForDrawDistrbutionImageAndBSE(int in_clr_tagid, int in_clr_fieldid, out uint[] Search_xray, out uint[] Analysis_xray, out int xray_id, out List list_celementchemistryclr) { Search_xray = new uint[2000]; Analysis_xray = new uint[2000]; xray_id = 0; list_celementchemistryclr = new List(); //防止为空校验判断 if (resultFile.List_OTSField == null) return; Particle particle = resultFile.List_OTSField.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid); var tmpPart = new ParticleData(resultFile.FilePath).GetParticleXrayDataByFidAndPid(Convert.ToString(particle.FieldId), Convert.ToString(particle.XrayId)); if (tmpPart != null) { particle.XRayData = tmpPart.XRayData; if (particle.XrayId > -1) { for (int i = 0; i < 2000; i++) { Analysis_xray[i] = BitConverter.ToUInt32(particle.XRayData, i * 4); } Search_xray = Analysis_xray; xray_id = particle.XrayId; list_celementchemistryclr = particle.ElementList; } } } /// /// 传入所有的物理field坐标点,和单个物理field的宽高,返回所有field的左上角位置,和整个field组成的rect大小 /// /// /// /// /// public Rectangle GetWlRectTopLeftAndRect(List in_list_point, int in_width, int in_height) { //分别获取整个rect的xy最小值和最大值 int i_rect_x_min = 100000000; int i_rect_y_min = 100000000; int i_rect_x_max = -100000000; int i_rect_y_max = -100000000; for (int i = 0; i < in_list_point.Count; i++) { if (i_rect_x_min > in_list_point[i].X) i_rect_x_min = in_list_point[i].X; if (i_rect_y_min > in_list_point[i].Y) i_rect_y_min = in_list_point[i].Y; if (i_rect_x_max < in_list_point[i].X) i_rect_x_max = in_list_point[i].X; if (i_rect_y_max < in_list_point[i].Y) i_rect_y_max = in_list_point[i].Y; } Rectangle ret_rect = new Rectangle(i_rect_x_min, i_rect_y_min, i_rect_x_max - i_rect_x_min, i_rect_y_max - i_rect_y_min); return ret_rect; } /// /// 根据Field的ID,来获取Field列表中对应FIeld的OTS 坐标 /// /// /// public Point GetOTSPointByFieldID(List in_list_dfield, int in_fieldid) { Point ret_point = new Point(0, 0); for (int i = 0; i < in_list_dfield.Count; i++) { //这里TagID先代表的是底层返回的ID if (in_list_dfield[i].FieldID == in_fieldid.ToString()) { ret_point = new Point(Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.X), Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.Y)); } } return ret_point; } /// /// 将OTS坐标转换为Sem 坐标 /// /// /// public Point ChangeOTSToSemCoord(Point POTSCoord) { //first if m_semstagedata is null to get stage inforation //Convert.ToDouble(((Dictionary)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]); //after obtaining stage info,calc stage point data Point ret_SEM_point = new Point(); // get center point, um long xStart = resultFile.GetXAxisStart(); long xEnd = resultFile.GetXAxisEnd(); long xCenter = (xStart + xEnd) / 2; //long yStart = Convert.ToInt64(((Dictionary)((Dictionary)((Dictionary)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["start"]); //long yEnd = Convert.ToInt64(((Dictionary)((Dictionary)((Dictionary)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["end"]); int yStart = resultFile.GetYAxisStart(); long yEnd = resultFile.GetYAxisEnd(); long yCenter = (yStart + yEnd) / 2; // delte = SEM - OTSa long deltex = xCenter - 0; long deltey = yCenter - 0; OTS_X_AXIS_DIRECTION xdir = resultFile.GetXAxisDirEnum(); OTS_Y_AXIS_DIRECTION ydir = resultFile.GetYAxisDirEnum(); if (xdir == OTS_X_AXIS_DIRECTION.LEFT_TOWARD) { ret_SEM_point.X = -1 * (POTSCoord.X - Convert.ToInt32(deltex)); } else if (xdir == OTS_X_AXIS_DIRECTION.RIGHT_TOWARD) { ret_SEM_point.X = POTSCoord.X + Convert.ToInt32(deltex); } if (ydir == OTS_Y_AXIS_DIRECTION.UP_TOWARD) { ret_SEM_point.Y = POTSCoord.Y + Convert.ToInt32(deltey); } else if (ydir == OTS_Y_AXIS_DIRECTION.DOWN_TOWARD) { ret_SEM_point.Y = -1 * (POTSCoord.Y - Convert.ToInt32(deltey)); } return ret_SEM_point; } #endregion /// /// 判断该点是否在多边形的范围内 /// /// /// /// public bool WhetherInRange(DisplayParticle Part, Point WhetherPoint) { var rect = Part.GetShowRect(); if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom)) { var itm = Part; PointF[] inPoints = itm.GetGPath().PathPoints; bool b_inrange; GraphicsPath myGraphicsPath = new GraphicsPath(); Region myRegion = new Region(); myGraphicsPath.Reset(); myGraphicsPath.AddPolygon(inPoints); myRegion.MakeEmpty(); myRegion.Union(myGraphicsPath); //返回判断点是否在多边形里 b_inrange = myRegion.IsVisible(WhetherPoint); return b_inrange; } else { return false; } } public bool WhetherInRange(RectangleF rec,PointF[] inPoints, Point WhetherPoint) { var rect = rec; if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom)) { bool b_inrange; GraphicsPath myGraphicsPath = new GraphicsPath(); Region myRegion = new Region(); myGraphicsPath.Reset(); myGraphicsPath.AddPolygon(inPoints); myRegion.MakeEmpty(); myRegion.Union(myGraphicsPath); //返回判断点是否在多边形里 b_inrange = myRegion.IsVisible(WhetherPoint); return b_inrange; } else { return false; } } /// /// 判断该点是否在多边形的范围内的float版本重载 /// /// /// /// public bool WhetherInRange(DisplayParticle Part,PointF WhetherPoint) { var rect = Part.GetShowRect(); if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom)) { var itm = Part; PointF[] inPoints = itm.GetGPath().PathPoints; bool b_inrange ; GraphicsPath myGraphicsPath = new GraphicsPath(); Region myRegion = new Region(); myGraphicsPath.Reset(); myGraphicsPath.AddPolygon(inPoints); myRegion.MakeEmpty(); myRegion.Union(myGraphicsPath); //返回判断点是否在多边形里 b_inrange = myRegion.IsVisible(WhetherPoint); return b_inrange; } else { return false; } } public bool WhetherInRange(DisplayField field, PointF WhetherPoint) { var rect = field.GetShowRect(); if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom)) { return true; } else { return false; } } #region 颗粒分割功能方法 /// /// 获取线段与矩形的两个交点 /// /// /// /// /// /// public bool GetInterBetweenLinesAndRect(Point line1S, Point line1E, RectangleF rectangle, ref List pointList) { try { PointF pointF = new PointF(-1, -1); Rect rect = new Rect(); rect.X = m_ParticleSegmentation.ParticleData.RectLeft; rect.Y = m_ParticleSegmentation.ParticleData.RectTop; rect.Width = m_ParticleSegmentation.ParticleData.RectWidth; rect.Height = m_ParticleSegmentation.ParticleData.RectHeight; float border = 0; if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Right, rectangle.Top), ref pointF)) { border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left); pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y)); } if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Left, rectangle.Bottom), new PointF(rectangle.Right, rectangle.Bottom), ref pointF)) { border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left); pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y + rect.Height)); } if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Left, rectangle.Bottom), ref pointF)) { border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top); pointList.Add(new Point(rect.X, (int)(rect.Y + rect.Height * border))); } if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Right, rectangle.Top), new PointF(rectangle.Right, rectangle.Bottom), ref pointF)) { border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top); pointList.Add(new Point(rect.X + rect.Width, (int)(rect.Y + rect.Height * border))); } if (pointList.Count == 2) { return true; } else { return false; } } catch (Exception ex) { log.Trace("(GetSplitPartFun)" + ex); return false; } } /// /// 获取分离颗粒方法 /// /// /// /// public bool GetSplitPartFun(Point startPoint, Point endPoint, float m_pixelSize) { try { CImageHandler m_ImagePro = new CImageHandler(); Particle particle1 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData); Particle particle2 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData); //Dictionary sampleMembers = ((Dictionary)((Dictionary)resultFile.ResultInfo["Sample"])["Members"]); //Dictionary imageScanParam = (Dictionary)((Dictionary)((Dictionary)sampleMembers["MsrParams"])["Members"])["ImageScanParam"]; //string ImageResolution = imageScanParam["ImageResolution"].ToString(); int width = resultFile.GetImageWidth(); int height = resultFile.GetImageHeight(); using (Mat mat = new Mat(height, width, MatType.CV_8UC1, Scalar.Black))//黑色底图 using (Mat labelMat = new Mat()) using (Mat stats = new Mat()) using (Mat centroids = new Mat()) using (Mat matBse = new Mat(resultFile.List_OTSField[particle1.FieldId].FieldImageName, ImreadModes.Grayscale)) { foreach (Segment segment in m_ParticleSegmentation.ParticleData.SegmentList) { Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias); } //寻找坐标点 List points1 = new List(); List points2 = new List(); List aveGray1 = new List(); List aveGray2 = new List(); for (int k = 0; k < mat.Height; k++) { for (int j = 0; j < mat.Width; j++) { if (mat.Get(k, j) != 0) { int side = (startPoint.X - j) * (endPoint.Y - k) - (startPoint.Y - k) * (endPoint.X - j); if (side >= 0)//区分像素位置 { points1.Add(new Point(j, k)); aveGray1.Add(matBse.Get(k, j)); } else { points2.Add(new Point(j, k)); aveGray2.Add(matBse.Get(k, j)); } } } } //处理Segment List SegmentClrList1 = new List(); List SegmentClrList2 = new List(); List SegmentList1 = new List(); List SegmentList2 = new List(); GetSegment(points1, m_ParticleSegmentation.ParticleData, SegmentClrList1, ref SegmentList1); GetSegment(points2, m_ParticleSegmentation.ParticleData, SegmentClrList2, ref SegmentList2); //颗粒一 Cv2.Threshold(mat, mat, 0, 0, ThresholdTypes.Binary); foreach (Segment segment in SegmentList1) { Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias); } Cv2.ConnectedComponentsWithStats(mat, labelMat, stats, centroids, PixelConnectivity.Connectivity8); CopyToPart(particle1, SegmentList1, SegmentClrList1, aveGray1, stats, centroids, m_pixelSize); //颗粒二 Cv2.Threshold(mat, mat, 0, 0, ThresholdTypes.Binary); foreach (Segment segment in SegmentList2) { Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias); } Cv2.ConnectedComponentsWithStats(mat, labelMat, stats, centroids, PixelConnectivity.Connectivity8); CopyToPart(particle2, SegmentList2, SegmentClrList2, aveGray2, stats, centroids, m_pixelSize); if (!SaveToDb(particle1, particle2)) { log.Trace("(GetSplitPartFun) SaveToDb Faild"); return false; } } return true; } catch (Exception ex) { log.Trace("(GetSplitPartFun)" + ex); return false; } } /// /// 拷贝颗粒数据 /// /// /// /// /// /// /// /// private void CopyToPart(Particle particle, List segments, List SegmentClrList, List aveGray, Mat stats, Mat centroids, double dPixelSize) { CImageHandler m_ImagePro = new CImageHandler(); COTSParticleClr part = new COTSParticleClr(); part.SetActualArea(stats.At(1, 4) * dPixelSize * dPixelSize); part.SetParticleRect(new Rectangle(stats.At(1, 0), stats.At(1, 1), stats.At(1, 2), stats.At(1, 3))); part.GetFeature().SetSegmentsList(SegmentClrList, false); m_ImagePro.CalParticleImageProp(part, dPixelSize); particle.SegmentList = segments; particle.SegmentNum = segments.Count; particle.AveGray = (int)aveGray.Average(); particle.RectLeft = stats.At(1, 0); particle.RectTop = stats.At(1, 1); particle.RectWidth = stats.At(1, 2); particle.RectHeight = stats.At(1, 3); particle.Area = stats.At(1, 4) * dPixelSize * dPixelSize; particle.PosX = (int)centroids.At(1, 0); particle.PosY = (int)centroids.At(1, 1); particle.DFERET = part.GetFeretDiameter(); particle.DMAX = part.GetDMAX(); particle.DMIN = part.GetDMIN(); particle.DPERP = part.GetDMPERP(); particle.PERIMETER = part.GetDPRIMETER(); particle.ORIENTATION = part.GetORIENTATION(); particle.DINSCR = part.GetDINSCR(); particle.DMEAN = part.GetDMEAN(); particle.DELONG = part.GetDELONG(); } /// /// 保存数据库 /// /// /// /// public bool SaveToDb(Particle particle1, Particle particle2) { //初始化 SQLiteHelper sQLiteHelper = new SQLiteHelper(resultFile.FilePath + "\\FIELD_FILES\\Inclusion.db"); sQLiteHelper.GetDBConnection(); sQLiteHelper.BeginTransaction(); //修改Segment表 if (particle1.SegmentList.Count == 0 || particle2.SegmentList.Count == 0) { return false; } int SegmentCount = sQLiteHelper.ExecuteNewPartIdForTransaction() + 1; if (!sQLiteHelper.ExecuteSegmentForTransaction(particle1, particle2, SegmentCount))//修改Segment表 { return false; } if (!sQLiteHelper.ExecuteXrayForTransaction(particle1, particle2, SegmentCount))//修改XRayData和PoxXrayInfo表 { return false; } if (!sQLiteHelper.ExecuteIncAForTransaction(particle1, particle2, SegmentCount))//修改IncAData表 { return false; } sQLiteHelper.CommitTransaction(); return true; } /// /// 线段与矩形是否相交 /// /// /// /// /// /// /// /// /// /// public bool isLineIntersectRectangle(float linePointX1, float linePointY1, float linePointX2, float linePointY2, float rectangleLeftTopX, float rectangleLeftTopY, float rectangleRightBottomX, float rectangleRightBottomY) { float lineHeight = linePointY1 - linePointY2; float lineWidth = linePointX2 - linePointX1; // 计算叉乘 float c = linePointX1 * linePointY2 - linePointX2 * linePointY1; if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0) || (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0) || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0) || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0)) { if (rectangleLeftTopX > rectangleRightBottomX) { float temp = rectangleLeftTopX; rectangleLeftTopX = rectangleRightBottomX; rectangleRightBottomX = temp; } if (rectangleLeftTopY < rectangleRightBottomY) { float temp1 = rectangleLeftTopY; rectangleLeftTopY = rectangleRightBottomY; rectangleRightBottomY = temp1; } if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX) || (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX) || (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY) || (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY)) { return false; } else { return true; } } else { return false; } } /// /// 求一个线段与另一个线段的交点 /// /// /// /// /// /// /// -1:不存在交点;1:存在一个交点;2:存在无穷多个交点(重合或部分重合) public bool GetInterBetweenTwoLines(PointF line1S, PointF line1E, PointF line2S, PointF line2E, ref PointF interPoint) { int status = -1; // 判断两条直线各自的矩形包围盒的X与Y的值范围 float line1Xmin = line1S.X < line1E.X ? line1S.X : line1E.X, line1Xmax = line1S.X > line1E.X ? line1S.X : line1E.X, line1Ymin = line1S.Y < line1E.Y ? line1S.Y : line1E.Y, line1Ymax = line1S.Y > line1E.Y ? line1S.Y : line1E.Y, line2Xmin = line2S.X < line2E.X ? line2S.X : line2E.X, line2Xmax = line2S.X > line2E.X ? line2S.X : line2E.X, line2Ymin = line2S.Y < line2E.Y ? line2S.Y : line2E.Y, line2Ymax = line2S.Y > line2E.Y ? line2S.Y : line2E.Y; if (line1S.X - line1E.X == 0) { // 两条线都垂直于X轴 if (line2S.X - line2E.X == 0) { if (line1S.X != line2S.X) status = -1; else if ((line1Ymin > line2Ymax) || (line1Ymax < line2Ymin)) status = -1; else if (line1Ymin == line2Ymax) { interPoint = new PointF(line1S.X, line1Ymin); status = 1; } else if (line1Ymax == line2Ymin) { interPoint = new PointF(line1S.X, line1Ymax); status = 1; } else status = 2; } // line1垂直于X轴,line2不垂直于X轴 else { float slope = (line2S.Y - line2E.Y) / (line2S.X - line2E.X); float offset = line2S.Y - slope * line2S.X; float newX = line1S.X, newY = slope * newX + offset; if (newX >= line2Xmin && newX <= line2Xmax && newY >= line1Ymin && newY <= line1Ymax && newY >= line2Ymin && newY <= line2Ymax) { interPoint = new PointF(newX, newY); status = 1; } } } else { // line1不垂直于X轴,line2垂直于X轴 if (line2S.X - line2E.X == 0) { float slope = (line1S.Y - line1E.Y) / (line1S.X - line1E.X); float offset = line1S.Y - slope * line1S.X; float newX = line2S.X, newY = slope * newX + offset; if (newX >= line1Xmin && newX <= line1Xmax && newY >= line1Ymin && newY <= line1Ymax && newY >= line2Ymin && newY <= line2Ymax) { interPoint = new PointF(newX, newY); status = 1; } } // line1和line2都不垂直于X轴 else { float slope1 = (line1S.Y - line1E.Y) / (line1S.X - line1E.X); float offset1 = line1S.Y - slope1 * line1S.X; float slope2 = (line2S.Y - line2E.Y) / (line2S.X - line2E.X); float offset2 = line2S.Y - slope2 * line2S.X; // 如果两条直线平行 if (slope1 == slope2) { if (offset1 != offset2) status = -1; else if (line1Xmax == line2Xmin) { interPoint = new PointF(line1Xmax, line1Xmax * slope1 + offset1); status = 1; } else if (line1Xmin == line2Xmax) { interPoint = new PointF(line1Xmin, line1Xmin * slope1 + offset1); status = 1; } else if (line1Xmax < line2Xmin || line1Xmin > line2Xmax) status = -1; else status = 2; } else { float newX = (offset2 - offset1) / (slope1 - slope2), newY = newX * slope1 + offset1; if (newX >= line1Xmin && newX <= line1Xmax && newX >= line2Xmin && newX <= line2Xmax) { interPoint = new PointF(newX, newY); status = 1; } } } } if (status == 1) { return true; } else { return false; } } /// /// 获取Segment信息 /// /// /// /// public void GetSegment(List points, Particle ParticleData, List SegmentClrList, ref List SegmentList) { List segmentStart = new List(); List segmentHeight = new List(); List segmentLength = new List(); FindSegment(points, ref segmentStart, ref segmentHeight, ref segmentLength); for (int i = 0; i < segmentLength.Count; i++) { COTSSegmentClr seg = new COTSSegmentClr(); seg.SetStart(segmentStart[i]); seg.SetHeight(segmentHeight[i]); seg.SetLength(segmentLength[i]); SegmentClrList.Add(seg); Segment segment = new Segment(); segment.Start = segmentStart[i]; segment.Height = segmentHeight[i]; segment.Length = segmentLength[i]; segment.SegmentNum = segmentLength.Count; segment.SegmentId = i; segment.FieldId = ParticleData.FieldId; segment.XRayId = ParticleData.XrayId; segment.ParticleId = ParticleData.ParticleId; SegmentList.Add(segment); } } /// /// 寻找segment方法 /// public void FindSegment(List point_list_final, ref List segmentStart, ref List segmentHeight, ref List segmentLength) { int flag = 0; point_list_final.Sort(my_sort);//排序 for (int k = 0; k < point_list_final.Count(); k++) { if (k == 0 && k != point_list_final.Count() - 1)//第一个颗粒 { flag++; segmentStart.Add(point_list_final[k].X); segmentHeight.Add(point_list_final[k].Y); } else if (k == 0 && k == point_list_final.Count() - 1)//只有一个颗粒 { segmentStart.Add(point_list_final[k].X); segmentHeight.Add(point_list_final[k].Y); segmentLength.Add(1); } else if (k == point_list_final.Count() - 1)//最后一个颗粒 { flag++; segmentLength.Add(flag); } else if (point_list_final[k].Y == point_list_final[k - 1].Y && point_list_final[k].X == point_list_final[k - 1].X + 1)//同行连续 { flag++; } else if (point_list_final[k].Y == point_list_final[k - 1].Y && point_list_final[k].X != point_list_final[k - 1].X + 1)//同行隔断 { segmentLength.Add(flag); flag = 1; segmentStart.Add(point_list_final[k].X); segmentHeight.Add(point_list_final[k].Y); } else if (point_list_final[k].Y != point_list_final[k - 1].Y)//不同行 { segmentLength.Add(flag); flag = 1; segmentStart.Add(point_list_final[k].X); segmentHeight.Add(point_list_final[k].Y); } } } /// /// 排序方法 /// /// /// /// private int my_sort(Point p1, Point p2) { return p1.Y == p2.Y ? p1.X.CompareTo(p2.X) : p1.Y.CompareTo(p2.Y); //升序排序 } public object CloneObject(object obj) { using (MemoryStream stream = new MemoryStream()) { BinaryFormatter formatter = new BinaryFormatter(); stream.Position = 0; formatter.Serialize(stream, obj); stream.Position = 0; return formatter.Deserialize(stream); } } #endregion } }