OTSImageDisHelp.cs 47 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133
  1. using OpenCvSharp;
  2. using OTSCLRINTERFACE;
  3. using OTSCommon.Model;
  4. using OTSIncAReportApp.DataOperation.DataAccess;
  5. using OTSIncAReportApp.SysMgrTools;
  6. using OTSIncAReportGraph.Class;
  7. using OTSIncAReportGraph.Controls;
  8. using OTSModelSharp.DTLBase;
  9. using OTSModelSharp.ServiceInterface;
  10. using System;
  11. using System.Collections;
  12. using System.Collections.Generic;
  13. using System.Data;
  14. using System.Diagnostics;
  15. using System.Drawing;
  16. using System.Drawing.Drawing2D;
  17. using System.IO;
  18. using System.Linq;
  19. using System.Runtime.Serialization.Formatters.Binary;
  20. using Point = System.Drawing.Point;
  21. namespace OTSIncAReportGraph.OTSIncAReportGraphFuncation
  22. {
  23. public class OTSImageDisHelp
  24. {
  25. #region 枚举定义
  26. /// <summary>
  27. /// 样品台X轴方向
  28. /// </summary>
  29. enum OTS_X_AXIS_DIRECTION
  30. {
  31. LEFT_TOWARD = 0,
  32. RIGHT_TOWARD = 1
  33. }
  34. /// <summary>
  35. /// 样品台Y轴方向
  36. /// </summary>
  37. enum OTS_Y_AXIS_DIRECTION
  38. {
  39. UP_TOWARD = 0,
  40. DOWN_TOWARD = 1
  41. }
  42. #endregion
  43. #region 定义变量
  44. private ResultFile resultFile = null;
  45. public ParticleSegmentation m_ParticleSegmentation;
  46. //记录field列表的原值
  47. public List<DisplayField> m_original_list_dfield = null;
  48. //记录原值,颗粒和线段
  49. public List<BaseObject> m_original_list_baseobject = null;
  50. NLog.Logger log;
  51. //field的数量
  52. public int m_field_count = 0;
  53. //particle的数量
  54. public int m_particle_count = 0;
  55. //加载使用的时间
  56. public string m_time_str = "";
  57. //加载使用时间计算时间段2
  58. public string m_time_str2 = "";
  59. //电镜设置对象
  60. public ServiceInterface.HardwareController m_cfun = null;
  61. //是否已经连接到了电镜
  62. public bool m_SEMConnectionState = false;
  63. //连接到电镜的ID号
  64. public int m_SEM_ID = 0;
  65. #endregion
  66. #region 构造函数
  67. public OTSImageDisHelp( ResultFile result)
  68. {
  69. m_original_list_dfield = new List<DisplayField>();
  70. m_original_list_baseobject = new List<BaseObject>();
  71. resultFile = result;
  72. m_cfun = ServiceInterface.HardwareController.GetSemController();
  73. log = NLog.LogManager.GetCurrentClassLogger();
  74. }
  75. #endregion
  76. #region 封装自定义方法
  77. public Point GetOTSCoordLeftBottomPoint(List<Point> allFldPos)
  78. {
  79. //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the smallest point.
  80. //找出最小的x,y用来做偏移运算
  81. int i_offset_x = 1000000000;
  82. int i_offset_y = 1000000000;
  83. //先取出最小的x,y
  84. for (int i = 0; i < allFldPos.Count; i++)
  85. {
  86. if (i_offset_x > allFldPos[i].X)
  87. {
  88. i_offset_x = allFldPos[i].X;
  89. }
  90. if (i_offset_y > allFldPos[i].Y)
  91. {
  92. i_offset_y = allFldPos[i].Y;
  93. }
  94. }
  95. return new Point(i_offset_x, i_offset_y);
  96. }
  97. public Point ConvertOTSCoordinateToScreenCoord(Point otsleftBottomPoint,double pixelSize, Point currenFldPos,RectangleF wholeImageRec,RectangleF singleImgRec)//
  98. {
  99. var OTSPoint=new Point(currenFldPos.X - otsleftBottomPoint.X, currenFldPos.Y - otsleftBottomPoint.Y);
  100. double screenHeight = wholeImageRec.Height + (0 - (int)(Convert.ToDouble(OTSPoint.Y) / 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.
  101. screenHeight = screenHeight - singleImgRec.Height;
  102. var screenPoint = new Point((int)(Convert.ToDouble(OTSPoint.X)/pixelSize), (int)screenHeight);
  103. return screenPoint;
  104. }
  105. public Rectangle ConvertAndGetMaxRect(List<Point> inPoints, int in_width, int in_height)
  106. {
  107. //首先要能确定下来,单个物理坐标的宽和高--------------------------------
  108. int i_wl_width = 0;
  109. int i_wl_height = 0;
  110. RectangleF ls_r = GetPhysicalFieldWidthAndHeight(inPoints,in_width,in_height);
  111. i_wl_width = (int)ls_r.Width;
  112. i_wl_height = (int)ls_r.Height;
  113. //-----------------------------------------------------------------------------
  114. int point_x_min = 10000000;
  115. int point_x_max = -10000000;
  116. int point_y_min = 10000000;
  117. int point_y_max = -10000000;
  118. for (int i = 0; i < inPoints.Count(); i++)
  119. {
  120. Point ls_point = inPoints[i];
  121. //取出正数最大x
  122. if (ls_point.X > point_x_max)
  123. point_x_max = ls_point.X;
  124. if (ls_point.Y > point_y_max)
  125. point_y_max = ls_point.Y;
  126. if (ls_point.X < point_x_min)
  127. point_x_min = ls_point.X;
  128. if (ls_point.Y < point_y_min)
  129. point_y_min = ls_point.Y;
  130. }
  131. //然后分别用最大值+abs(最小值),就是x,和y轴的总长值
  132. point_x_max = point_x_max - point_x_min;
  133. point_y_max = point_y_max - point_y_min;
  134. //该算法有个问题,就是不能直观的得到整个范围的大小,要除以倍数再补1能补充缺少的一个field视域**********
  135. point_x_max = ((point_x_max / i_wl_width) + 1) * i_wl_width;
  136. point_y_max = ((point_y_max / i_wl_height) + 1) * i_wl_height;
  137. //将物理宽高,变换成分辨率宽高
  138. if (i_wl_width != 0) point_x_max = (point_x_max / i_wl_width) * in_width; else point_x_max = 0;
  139. if (i_wl_height != 0) point_y_max = (point_y_max / i_wl_height) * in_height; else point_y_max = 0;
  140. Rectangle ret_rectangle = new Rectangle(0, 0, 0, 0);
  141. //判断一下防止出错,只有在有数据的情况下,进行赋值才行
  142. if (inPoints.Count > 0)
  143. {
  144. ret_rectangle = new Rectangle(0, 0, point_x_max, point_y_max);
  145. }
  146. //这样返回是物理坐标的总大小,应该返回像素坐标大小才对
  147. return ret_rectangle;
  148. }
  149. /// <summary>
  150. /// 计算单个field的物理大小 传入field的list,还有测量结果管理类对象,在无法计算出单field的物理大小的情况下,到这里取再计算得出
  151. /// </summary>
  152. /// <returns></returns>
  153. public RectangleF GetPhysicalFieldWidthAndHeight(List<Point> points,int imageWidth,int imageHeight)
  154. {
  155. int width_max = -10000000;
  156. int height_max = -10000000;
  157. int width_max2 = -10000000;
  158. int height_max2 = -10000000;
  159. //先找出最大的值,
  160. for (int i = 0; i < points.Count(); i++)
  161. {
  162. if (width_max < points[i].X)
  163. width_max = points[i].X;
  164. if (height_max < points[i].Y)
  165. height_max = points[i].Y;
  166. }
  167. //再找出第二大的值
  168. for (int i = 0; i < points.Count(); i++)
  169. {
  170. if (width_max2 < points[i].X && width_max != points[i].X)
  171. width_max2 = points[i].X;
  172. if (height_max2 < points[i].Y && height_max != points[i].Y)
  173. height_max2 = points[i].Y;
  174. }
  175. //需要针对第二大的值,获取时进行判断,感觉这里应该如果并未找到第二大的值的情况下,赋于0值,便于以后进行计算
  176. if (width_max2 == -10000000)
  177. width_max2 = width_max;
  178. if (height_max2 == -10000000)
  179. height_max2 = height_max;
  180. RectangleF ret_rect = new RectangleF(0, 0, width_max - width_max2, height_max - height_max2);
  181. //如果最后计算出的宽高有0则重新到测量数据中获取---------------------------------------
  182. if (ret_rect.Width == 0 || ret_rect.Height == 0)
  183. {
  184. //到参数中去取单个宽
  185. double d_scanFieldSize_width = Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  186. //然后再用单个宽去计算出高是多少
  187. double d_scanFieldSize_height = 0;
  188. if (d_scanFieldSize_width != 0)
  189. d_scanFieldSize_height = (d_scanFieldSize_width / Convert.ToDouble(imageWidth)) * imageHeight;
  190. ret_rect.Width = (int)d_scanFieldSize_width;
  191. ret_rect.Height = (int)d_scanFieldSize_height;
  192. }
  193. ///-----------because all the fields 's height/width=0.75 so here we make an enforce. gsp add at 2019/10/31
  194. ///sometimes the gbfields are not conform to this for the cuting and merging operation.
  195. //if (ret_rect.Height / ret_rect.Width != 0.75f)
  196. //{
  197. // ret_rect = new Rectangle(ret_rect.X, ret_rect.Y, ret_rect.Width, (int)(ret_rect.Width * 0.75f));
  198. //}
  199. return ret_rect;
  200. }
  201. #endregion
  202. #region 电镜操作相关方法
  203. /// <summary>
  204. /// 连接电镜,分布图使用
  205. /// </summary>
  206. public void ConnectToSEM()
  207. {
  208. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM");
  209. if (!m_SEMConnectionState)
  210. {
  211. //和电镜建立通讯连接
  212. m_SEMConnectionState = m_cfun.Connect();
  213. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM" + ":--" + m_SEMConnectionState + "---");
  214. }
  215. else
  216. {
  217. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + ":allready connected, state:" + m_SEMConnectionState);
  218. //断开电镜连接
  219. }
  220. }
  221. public void DisConnectSEM()
  222. {
  223. m_SEMConnectionState = false;
  224. m_cfun.DisConnect();
  225. }
  226. /// <summary>
  227. /// 移动电镜到指定的X,Y坐标上,R坐标使用原先的值进行移动
  228. /// </summary>
  229. /// <param name="PositionX"></param>
  230. /// <param name="PositionY"></param>
  231. public void MoveSemToPointXY(double in_PositionX, double in_PositionY)
  232. {
  233. log.Trace("Begin MoveSemToPointXY:(" +in_PositionX.ToString()+","+in_PositionY.ToString()+")");
  234. //首先获取电镜当前的位置,并记录原R值
  235. double ls_PositionX = 0;
  236. double ls_PositionY = 0;
  237. double ls_PositionR = 0;
  238. if (m_SEMConnectionState)
  239. {
  240. m_cfun.GetSemPositionXY(ref ls_PositionX, ref ls_PositionY, ref ls_PositionR);
  241. }
  242. else
  243. {
  244. log.Error("Failed to GetSemPositionXY");
  245. return;
  246. }
  247. if (m_SEMConnectionState)
  248. {
  249. m_cfun.MoveSEMToPoint(new Point((int)in_PositionX, (int)in_PositionY), ls_PositionR);
  250. }
  251. }
  252. #endregion
  253. #region //--------------------------------------颗粒分布图相关部份---------------------------------------------------------------------
  254. /// <summary>
  255. /// 传入颗粒的tagid和fieldid,来获取该颗粒下对应的xray数据
  256. /// </summary>
  257. /// <param name="in_clr_tagid"></param>
  258. /// <param name="in_clr_fieldid"></param>
  259. /// <param name="Search_xray"></param>
  260. /// <param name="Analysis_xray"></param>
  261. 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<Element> list_celementchemistryclr)
  262. {
  263. Search_xray = new uint[2000];
  264. Analysis_xray = new uint[2000];
  265. xray_id = 0;
  266. list_celementchemistryclr = new List<Element>();
  267. //防止为空校验判断
  268. if (resultFile.List_OTSField == null)
  269. return;
  270. Particle particle = resultFile.List_OTSField.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid);
  271. var tmpPart = new ParticleData(resultFile.FilePath).GetParticleXrayDataByFidAndPid(Convert.ToString(particle.FieldId), Convert.ToString(particle.XrayId));
  272. if (tmpPart != null)
  273. {
  274. particle.XRayData = tmpPart.XRayData;
  275. if (particle.XrayId > -1)
  276. {
  277. for (int i = 0; i < 2000; i++)
  278. {
  279. Analysis_xray[i] = BitConverter.ToUInt32(particle.XRayData, i * 4);
  280. }
  281. Search_xray = Analysis_xray;
  282. xray_id = particle.XrayId;
  283. list_celementchemistryclr = particle.ElementList;
  284. }
  285. }
  286. }
  287. public bool DeleteParticlesFromLibrary(int in_clr_tagid, int in_clr_fieldid)
  288. {
  289. bool DoesItExist = false;
  290. for (int i=1;i<201;i++)
  291. {
  292. if (System.IO.Directory.Exists(resultFile.FilePath + "\\FIELD_FILES\\Backups"+i.ToString()))
  293. {
  294. DoesItExist = true;
  295. break;
  296. }
  297. }
  298. if (!DoesItExist)
  299. {
  300. //备份数据库
  301. BackupDatabase();
  302. }
  303. DoesItExist = false;
  304. //防止为空校验判断
  305. if (resultFile.List_OTSField == null)
  306. return false;
  307. Particle particle = resultFile.List_OTSField.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid);
  308. if (new ParticleData(resultFile.FilePath).DeleteFromData(Convert.ToString(particle.FieldId), Convert.ToString(particle.XrayId)))
  309. {
  310. return true;
  311. }else
  312. {
  313. return false;
  314. }
  315. }
  316. public bool BackupDatabase()
  317. {
  318. //创建备份数据库文件夹
  319. string sourcePath = resultFile.FilePath + "\\FIELD_FILES\\Inclusion.db";//源文件路径
  320. string sourceName = "Inclusion.db";//源文件名称
  321. string folderPath = resultFile.FilePath + "\\FIELD_FILES\\Backups";//目标文件夹
  322. string Fields = "";
  323. for (int i = 1; i < 201; i++)
  324. {
  325. if (System.IO.Directory.Exists(folderPath + i.ToString()))
  326. {
  327. Fields = folderPath + i.ToString();
  328. break;
  329. }
  330. else
  331. {
  332. System.IO.Directory.CreateDirectory(folderPath + i.ToString());
  333. Fields = folderPath + i.ToString();
  334. break;
  335. }
  336. }
  337. if (Fields == "")
  338. {
  339. return false;
  340. }
  341. //复制数据库文件
  342. string targetPath = Path.Combine(Fields, sourceName);
  343. FileInfo file = new FileInfo(sourcePath);
  344. if (file.Exists)
  345. {
  346. file.CopyTo(targetPath, true);
  347. }
  348. return true;
  349. }
  350. /// <summary>
  351. /// 传入所有的物理field坐标点,和单个物理field的宽高,返回所有field的左上角位置,和整个field组成的rect大小
  352. /// </summary>
  353. /// <param name="in_list_point"></param>
  354. /// <param name="in_width"></param>
  355. /// <param name="in_height"></param>
  356. /// <returns></returns>
  357. public Rectangle GetWlRectTopLeftAndRect(List<Point> in_list_point, int in_width, int in_height)
  358. {
  359. //分别获取整个rect的xy最小值和最大值
  360. int i_rect_x_min = 100000000;
  361. int i_rect_y_min = 100000000;
  362. int i_rect_x_max = -100000000;
  363. int i_rect_y_max = -100000000;
  364. for (int i = 0; i < in_list_point.Count; i++)
  365. {
  366. if (i_rect_x_min > in_list_point[i].X)
  367. i_rect_x_min = in_list_point[i].X;
  368. if (i_rect_y_min > in_list_point[i].Y)
  369. i_rect_y_min = in_list_point[i].Y;
  370. if (i_rect_x_max < in_list_point[i].X)
  371. i_rect_x_max = in_list_point[i].X;
  372. if (i_rect_y_max < in_list_point[i].Y)
  373. i_rect_y_max = in_list_point[i].Y;
  374. }
  375. Rectangle ret_rect = new Rectangle(i_rect_x_min, i_rect_y_min,
  376. i_rect_x_max - i_rect_x_min, i_rect_y_max - i_rect_y_min);
  377. return ret_rect;
  378. }
  379. /// <summary>
  380. /// 根据Field的ID,来获取Field列表中对应FIeld的OTS 坐标
  381. /// </summary>
  382. /// <param name="in_fieldid"></param>
  383. /// <returns></returns>
  384. public Point GetOTSPointByFieldID(List<DisplayField> in_list_dfield, int in_fieldid)
  385. {
  386. Point ret_point = new Point(0, 0);
  387. for (int i = 0; i < in_list_dfield.Count; i++)
  388. {
  389. //这里TagID先代表的是底层返回的ID
  390. if (in_list_dfield[i].FieldID == in_fieldid.ToString())
  391. {
  392. ret_point = new Point(Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.X), Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.Y));
  393. }
  394. }
  395. return ret_point;
  396. }
  397. /// <summary>
  398. /// 将OTS坐标转换为Sem 坐标
  399. /// </summary>
  400. /// <param name="POTSCoord"></param>
  401. /// <returns></returns>
  402. public Point ChangeOTSToSemCoord(Point POTSCoord)
  403. {
  404. //first if m_semstagedata is null to get stage inforation
  405. Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  406. //after obtaining stage info,calc stage point data
  407. Point ret_SEM_point = new Point();
  408. // get center point, um
  409. long xStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["start"]);
  410. long xEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["end"]);
  411. long xCenter = (xStart + xEnd) / 2;
  412. long yStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["start"]);
  413. long yEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["end"]);
  414. long yCenter = (yStart + yEnd) / 2;
  415. // delte = SEM - OTSa
  416. long deltex = xCenter - 0;
  417. long deltey = yCenter - 0;
  418. int xdir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["xAxisDir"]);
  419. int ydir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["yAxisDir"]);
  420. if (xdir == (int)OTS_X_AXIS_DIRECTION.LEFT_TOWARD)
  421. {
  422. ret_SEM_point.X = -1 * (POTSCoord.X - Convert.ToInt32(deltex));
  423. }
  424. else if (xdir == (int)OTS_X_AXIS_DIRECTION.RIGHT_TOWARD)
  425. {
  426. ret_SEM_point.X = POTSCoord.X + Convert.ToInt32(deltex);
  427. }
  428. if (ydir == (int)OTS_Y_AXIS_DIRECTION.UP_TOWARD)
  429. {
  430. ret_SEM_point.Y = POTSCoord.Y + Convert.ToInt32(deltey);
  431. }
  432. else if (ydir == (int)OTS_Y_AXIS_DIRECTION.DOWN_TOWARD)
  433. {
  434. ret_SEM_point.Y = -1 * (POTSCoord.Y - Convert.ToInt32(deltey));
  435. }
  436. return ret_SEM_point;
  437. }
  438. #endregion
  439. /// <summary>
  440. /// 判断该点是否在多边形的范围内
  441. /// </summary>
  442. /// <param name="inPoints"></param>
  443. /// <param name="WhetherPoint"></param>
  444. /// <returns></returns>
  445. public bool WhetherInRange(DisplayParticle Part,/*PointF[] inPoints,*/ Point WhetherPoint)
  446. {
  447. var rect = Part.Rect;
  448. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  449. {
  450. var itm = (BaseObject)Part;
  451. itm.GPath = Part.GetRegionFromDSegments();
  452. PointF[] inPoints = itm.GPath.PathPoints;
  453. bool b_inrange = false;
  454. GraphicsPath myGraphicsPath = new GraphicsPath();
  455. Region myRegion = new Region();
  456. myGraphicsPath.Reset();
  457. myGraphicsPath.AddPolygon(inPoints);
  458. myRegion.MakeEmpty();
  459. myRegion.Union(myGraphicsPath);
  460. //返回判断点是否在多边形里
  461. b_inrange = myRegion.IsVisible(WhetherPoint);
  462. return b_inrange;
  463. }
  464. else
  465. {
  466. return false;
  467. }
  468. }
  469. public bool WhetherInRange(RectangleF rec,PointF[] inPoints, Point WhetherPoint)
  470. {
  471. var rect = rec;
  472. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  473. {
  474. //var itm = (BaseObject)Part;
  475. //PointF[] inPoints = itm.GPath.PathPoints;
  476. bool b_inrange = false;
  477. GraphicsPath myGraphicsPath = new GraphicsPath();
  478. Region myRegion = new Region();
  479. myGraphicsPath.Reset();
  480. myGraphicsPath.AddPolygon(inPoints);
  481. myRegion.MakeEmpty();
  482. myRegion.Union(myGraphicsPath);
  483. //返回判断点是否在多边形里
  484. b_inrange = myRegion.IsVisible(WhetherPoint);
  485. return b_inrange;
  486. }
  487. else
  488. {
  489. return false;
  490. }
  491. }
  492. /// <summary>
  493. /// 判断该点是否在多边形的范围内的float版本重载
  494. /// </summary>
  495. /// <param name="inPoints"></param>
  496. /// <param name="WhetherPoint"></param>
  497. /// <returns></returns>
  498. public bool WhetherInRange(DisplayParticle Part,/* PointF[] inPoints, */PointF WhetherPoint)
  499. {
  500. var rect = Part.Rect;
  501. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  502. {
  503. var itm = (BaseObject)Part;
  504. PointF[] inPoints = itm.GPath.PathPoints;
  505. bool b_inrange = false;
  506. GraphicsPath myGraphicsPath = new GraphicsPath();
  507. Region myRegion = new Region();
  508. myGraphicsPath.Reset();
  509. myGraphicsPath.AddPolygon(inPoints);
  510. myRegion.MakeEmpty();
  511. myRegion.Union(myGraphicsPath);
  512. //返回判断点是否在多边形里
  513. b_inrange = myRegion.IsVisible(WhetherPoint);
  514. return b_inrange;
  515. }
  516. else
  517. {
  518. return false;
  519. }
  520. }
  521. #region 颗粒分割功能方法
  522. /// <summary>
  523. /// 获取线段与矩形的两个交点
  524. /// </summary>
  525. /// <param name="line1S"></param>
  526. /// <param name="line1E"></param>
  527. /// <param name="rectangle"></param>
  528. /// <param name="pointList"></param>
  529. /// <returns></returns>
  530. public bool GetInterBetweenLinesAndRect(Point line1S, Point line1E, RectangleF rectangle, ref List<Point> pointList)
  531. {
  532. try
  533. {
  534. PointF pointF = new PointF(-1, -1);
  535. Rect rect = new Rect();
  536. rect.X = m_ParticleSegmentation.ParticleData.RectLeft;
  537. rect.Y = m_ParticleSegmentation.ParticleData.RectTop;
  538. rect.Width = m_ParticleSegmentation.ParticleData.RectWidth;
  539. rect.Height = m_ParticleSegmentation.ParticleData.RectHeight;
  540. float border = 0;
  541. if (GetInterBetweenTwoLines(line1S, line1E, new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Right, rectangle.Top), ref pointF))
  542. {
  543. border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left);
  544. pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y));
  545. }
  546. if (GetInterBetweenTwoLines(line1S, line1E,
  547. new PointF(rectangle.Left, rectangle.Bottom), new PointF(rectangle.Right, rectangle.Bottom), ref pointF))
  548. {
  549. border = (pointF.X - rectangle.Left) / (rectangle.Right - rectangle.Left);
  550. pointList.Add(new Point((int)(rect.X + rect.Width * border), rect.Y + rect.Height));
  551. }
  552. if (GetInterBetweenTwoLines(line1S, line1E,
  553. new PointF(rectangle.Left, rectangle.Top), new PointF(rectangle.Left, rectangle.Bottom), ref pointF))
  554. {
  555. border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top);
  556. pointList.Add(new Point(rect.X, (int)(rect.Y + rect.Height * border)));
  557. }
  558. if (GetInterBetweenTwoLines(line1S, line1E,
  559. new PointF(rectangle.Right, rectangle.Top), new PointF(rectangle.Right, rectangle.Bottom), ref pointF))
  560. {
  561. border = (pointF.Y - rectangle.Top) / (rectangle.Bottom - rectangle.Top);
  562. pointList.Add(new Point(rect.X + rect.Width, (int)(rect.Y + rect.Height * border)));
  563. }
  564. if (pointList.Count == 2)
  565. {
  566. return true;
  567. }
  568. else
  569. {
  570. return false;
  571. }
  572. }
  573. catch (Exception ex)
  574. {
  575. log.Trace("(GetSplitPartFun)" + ex);
  576. return false;
  577. }
  578. }
  579. public bool GetSplitPartFun(Point startPoint, Point endPoint)
  580. {
  581. try
  582. {
  583. Particle particle1 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData);
  584. Particle particle2 = (Particle)CloneObject(m_ParticleSegmentation.ParticleData);
  585. Dictionary<string, object> sampleMembers = ((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["Sample"])["Members"]);
  586. Dictionary<string, object> imageScanParam = (Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)sampleMembers["MsrParams"])["Members"])["ImageScanParam"];
  587. double d_scanFieldSize_width = Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  588. string ImageResolution = imageScanParam["ImageResolution"].ToString();
  589. int width = int.Parse(ImageResolution.Split('_')[1]);
  590. int height = int.Parse(ImageResolution.Split('_')[2]);
  591. double dPixelSize = d_scanFieldSize_width / width;
  592. Mat mat = new Mat(height, width, MatType.CV_8UC1, Scalar.Black);//黑色底图
  593. Mat matBse = new Mat(resultFile.List_OTSField[particle1.FieldId].FieldImage, ImreadModes.Grayscale);//原图
  594. foreach (Segment segment in m_ParticleSegmentation.ParticleData.SegmentList)
  595. {
  596. Cv2.Line(mat, new OpenCvSharp.Point(segment.Start, segment.Height), new OpenCvSharp.Point(segment.Start + segment.Length, segment.Height), Scalar.White, 1, LineTypes.AntiAlias);
  597. }
  598. Cv2.Line(mat, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y, Scalar.Black, 2, LineTypes.AntiAlias);
  599. Mat labelMat = new Mat();
  600. Mat stats = new Mat();//点的信息
  601. Mat centroids = new Mat();//质心的信息
  602. int nonenum = Cv2.ConnectedComponentsWithStats(mat, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
  603. //暂时只分割成两个颗粒
  604. if (nonenum != 3)
  605. {
  606. log.Trace("(GetSplitPartFun) More than two particle");
  607. return false;
  608. }
  609. //寻找坐标点
  610. List<Point> points1 = new List<Point>();
  611. List<Point> points2 = new List<Point>();
  612. List<int> aveGray1 = new List<int>();
  613. List<int> aveGray2 = new List<int>();
  614. for (int k = 0; k < labelMat.Height; k++)
  615. {
  616. for (int j = 0; j < labelMat.Width; j++)
  617. {
  618. int no = labelMat.Get<int>(k, j);
  619. if (no == 1)
  620. {
  621. points1.Add(new Point(j, k));
  622. aveGray1.Add(matBse.Get<byte>(k, j));
  623. }
  624. else if (no == 2)
  625. {
  626. points2.Add(new Point(j, k));
  627. aveGray2.Add(matBse.Get<byte>(k, j));
  628. }
  629. }
  630. }
  631. mat.Dispose();
  632. matBse.Dispose();
  633. //处理Segment
  634. List<COTSSegmentClr> SegmentClrList1 = new List<COTSSegmentClr>();
  635. List<COTSSegmentClr> SegmentClrList2 = new List<COTSSegmentClr>();
  636. List<Segment> SegmentList1 = new List<Segment>();
  637. List<Segment> SegmentList2 = new List<Segment>();
  638. GetSegment(points1, SegmentClrList1, ref SegmentList1);
  639. GetSegment(points2, SegmentClrList2, ref SegmentList2);
  640. CImageHandler m_ImagePro = new CImageHandler();
  641. COTSParticleClr part1 = new COTSParticleClr();
  642. part1.SetArea(stats.At<int>(1, 4) * dPixelSize * dPixelSize);
  643. part1.SetParticleRect(new Rectangle(stats.At<int>(1, 0), stats.At<int>(1, 1), stats.At<int>(1, 2), stats.At<int>(1, 3)));
  644. part1.GetFeature().SetSegmentsList(SegmentClrList1, false);
  645. m_ImagePro.CalParticleImageProp(part1, dPixelSize);
  646. COTSParticleClr part2 = new COTSParticleClr();
  647. part2.SetArea(stats.At<int>(2, 4) * dPixelSize * dPixelSize);
  648. part2.SetParticleRect(new Rectangle(stats.At<int>(2, 0), stats.At<int>(2, 1), stats.At<int>(2, 2), stats.At<int>(2, 3)));
  649. part2.GetFeature().SetSegmentsList(SegmentClrList2, false);
  650. m_ImagePro.CalParticleImageProp(part2, dPixelSize);
  651. particle1.SegmentList = SegmentList1;
  652. particle1.SegmentNum = SegmentList1.Count;
  653. particle1.AveGray = (int)aveGray1.Average();
  654. particle1.RectLeft = stats.At<int>(1, 0);
  655. particle1.RectTop = stats.At<int>(1, 1);
  656. particle1.RectWidth = stats.At<int>(1, 2);
  657. particle1.RectHeight = stats.At<int>(1, 3);
  658. particle1.Area = stats.At<int>(1, 4) * dPixelSize * dPixelSize;
  659. particle1.PosX = (int)centroids.At<double>(1, 0);
  660. particle1.PosY = (int)centroids.At<double>(1, 1);
  661. particle1.DFERET = part1.GetFeretDiameter();
  662. particle1.DMAX = part1.GetDMAX();
  663. particle1.DMIN = part1.GetDMIN();
  664. particle1.DPERP = part1.GetDMPERP();
  665. particle1.PERIMETER = part1.GetDPRIMETER();
  666. particle1.ORIENTATION = part1.GetORIENTATION();
  667. particle1.DINSCR = part1.GetDINSCR();
  668. particle1.DMEAN = part1.GetDMEAN();
  669. particle1.DELONG = part1.GetDELONG();
  670. particle2.SegmentList = SegmentList2;
  671. particle2.SegmentNum = SegmentList2.Count;
  672. particle2.AveGray = (int)aveGray2.Average();
  673. particle2.RectLeft = stats.At<int>(2, 0);
  674. particle2.RectTop = stats.At<int>(2, 1);
  675. particle2.RectWidth = stats.At<int>(2, 2);
  676. particle2.RectHeight = stats.At<int>(2, 3);
  677. particle2.Area = stats.At<int>(2, 4) * dPixelSize * dPixelSize;
  678. particle2.PosX = (int)centroids.At<double>(2, 0);
  679. particle2.PosY = (int)centroids.At<double>(2, 1);
  680. particle2.DFERET = part2.GetFeretDiameter();
  681. particle2.DMAX = part2.GetDMAX();
  682. particle2.DMIN = part2.GetDMIN();
  683. particle2.DPERP = part2.GetDMPERP();
  684. particle2.PERIMETER = part2.GetDPRIMETER();
  685. particle2.ORIENTATION = part2.GetORIENTATION();
  686. particle2.DINSCR = part2.GetDINSCR();
  687. particle2.DMEAN = part2.GetDMEAN();
  688. particle2.DELONG = part2.GetDELONG();
  689. if (!SaveToDb(particle1, particle2))
  690. {
  691. log.Trace("(GetSplitPartFun) SaveToDb Faild");
  692. return false;
  693. }
  694. return true;
  695. }
  696. catch (Exception ex)
  697. {
  698. log.Trace("(GetSplitPartFun)" + ex);
  699. return false;
  700. }
  701. }
  702. /// <summary>
  703. /// 保存数据库
  704. /// </summary>
  705. /// <param name="particle1"></param>
  706. /// <param name="particle2"></param>
  707. /// <returns></returns>
  708. public bool SaveToDb(Particle particle1, Particle particle2)
  709. {
  710. //初始化
  711. SQLiteHelper sQLiteHelper = new SQLiteHelper(resultFile.FilePath + "\\FIELD_FILES\\Inclusion.db");
  712. sQLiteHelper.GetDBConnection();
  713. sQLiteHelper.BeginTransaction();
  714. //修改Segment表
  715. if (particle1.SegmentList.Count == 0 || particle2.SegmentList.Count == 0)
  716. {
  717. return false;
  718. }
  719. int SegmentCount = sQLiteHelper.ExecuteNewPartIdForTransaction() + 1;
  720. if (!sQLiteHelper.ExecuteSegmentForTransaction(particle1, particle2, SegmentCount))//修改Segment表
  721. {
  722. return false;
  723. }
  724. if (!sQLiteHelper.ExecuteXrayForTransaction(particle1, particle2, SegmentCount))//修改XRayData和PoxXrayInfo表
  725. {
  726. return false;
  727. }
  728. if (!sQLiteHelper.ExecuteIncAForTransaction(particle1, particle2, SegmentCount))//修改IncAData表
  729. {
  730. return false;
  731. }
  732. sQLiteHelper.CommitTransaction();
  733. return true;
  734. }
  735. /// <summary>
  736. /// 线段与矩形是否相交
  737. /// </summary>
  738. /// <param name="linePointX1"></param>
  739. /// <param name="linePointY1"></param>
  740. /// <param name="linePointX2"></param>
  741. /// <param name="linePointY2"></param>
  742. /// <param name="rectangleLeftTopX"></param>
  743. /// <param name="rectangleLeftTopY"></param>
  744. /// <param name="rectangleRightBottomX"></param>
  745. /// <param name="rectangleRightBottomY"></param>
  746. /// <returns></returns>
  747. public bool isLineIntersectRectangle(float linePointX1,
  748. float linePointY1,
  749. float linePointX2,
  750. float linePointY2,
  751. float rectangleLeftTopX,
  752. float rectangleLeftTopY,
  753. float rectangleRightBottomX,
  754. float rectangleRightBottomY)
  755. {
  756. float lineHeight = linePointY1 - linePointY2;
  757. float lineWidth = linePointX2 - linePointX1; // 计算叉乘
  758. float c = linePointX1 * linePointY2 - linePointX2 * linePointY1;
  759. if ((lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c <= 0)
  760. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleLeftTopY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleRightBottomY + c >= 0)
  761. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c >= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c <= 0)
  762. || (lineHeight * rectangleLeftTopX + lineWidth * rectangleRightBottomY + c <= 0 && lineHeight * rectangleRightBottomX + lineWidth * rectangleLeftTopY + c >= 0))
  763. {
  764. if (rectangleLeftTopX > rectangleRightBottomX)
  765. {
  766. float temp = rectangleLeftTopX;
  767. rectangleLeftTopX = rectangleRightBottomX;
  768. rectangleRightBottomX = temp;
  769. }
  770. if (rectangleLeftTopY < rectangleRightBottomY)
  771. {
  772. float temp1 = rectangleLeftTopY;
  773. rectangleLeftTopY = rectangleRightBottomY;
  774. rectangleRightBottomY = temp1;
  775. }
  776. if ((linePointX1 < rectangleLeftTopX && linePointX2 < rectangleLeftTopX)
  777. || (linePointX1 > rectangleRightBottomX && linePointX2 > rectangleRightBottomX)
  778. || (linePointY1 > rectangleLeftTopY && linePointY2 > rectangleLeftTopY)
  779. || (linePointY1 < rectangleRightBottomY && linePointY2 < rectangleRightBottomY))
  780. {
  781. return false;
  782. }
  783. else
  784. {
  785. return true;
  786. }
  787. }
  788. else
  789. {
  790. return false;
  791. }
  792. }
  793. /// <summary>
  794. /// 求一个线段与另一个线段的交点
  795. /// </summary>
  796. /// <param name="line1S"></param>
  797. /// <param name="line1E"></param>
  798. /// <param name="line2S"></param>
  799. /// <param name="line2E"></param>
  800. /// <param name="interPoint"></param>
  801. /// <returns>-1:不存在交点;1:存在一个交点;2:存在无穷多个交点(重合或部分重合)</returns>
  802. public bool GetInterBetweenTwoLines(PointF line1S, PointF line1E,
  803. PointF line2S, PointF line2E, ref PointF interPoint)
  804. {
  805. int status = -1;
  806. // 判断两条直线各自的矩形包围盒的X与Y的值范围
  807. float line1Xmin = line1S.X < line1E.X ? line1S.X : line1E.X,
  808. line1Xmax = line1S.X > line1E.X ? line1S.X : line1E.X,
  809. line1Ymin = line1S.Y < line1E.Y ? line1S.Y : line1E.Y,
  810. line1Ymax = line1S.Y > line1E.Y ? line1S.Y : line1E.Y,
  811. line2Xmin = line2S.X < line2E.X ? line2S.X : line2E.X,
  812. line2Xmax = line2S.X > line2E.X ? line2S.X : line2E.X,
  813. line2Ymin = line2S.Y < line2E.Y ? line2S.Y : line2E.Y,
  814. line2Ymax = line2S.Y > line2E.Y ? line2S.Y : line2E.Y;
  815. if (line1S.X - line1E.X == 0)
  816. {
  817. // 两条线都垂直于X轴
  818. if (line2S.X - line2E.X == 0)
  819. {
  820. if (line1S.X != line2S.X) status = -1;
  821. else if ((line1Ymin > line2Ymax) || (line1Ymax < line2Ymin)) status = -1;
  822. else if (line1Ymin == line2Ymax)
  823. {
  824. interPoint = new PointF(line1S.X, line1Ymin); status = 1;
  825. }
  826. else if (line1Ymax == line2Ymin)
  827. {
  828. interPoint = new PointF(line1S.X, line1Ymax); status = 1;
  829. }
  830. else status = 2;
  831. }
  832. // line1垂直于X轴,line2不垂直于X轴
  833. else
  834. {
  835. float slope = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
  836. float offset = line2S.Y - slope * line2S.X;
  837. float newX = line1S.X, newY = slope * newX + offset;
  838. if (newX >= line2Xmin && newX <= line2Xmax && newY >= line1Ymin && newY <= line1Ymax
  839. && newY >= line2Ymin && newY <= line2Ymax)
  840. {
  841. interPoint = new PointF(newX, newY); status = 1;
  842. }
  843. }
  844. }
  845. else
  846. {
  847. // line1不垂直于X轴,line2垂直于X轴
  848. if (line2S.X - line2E.X == 0)
  849. {
  850. float slope = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
  851. float offset = line1S.Y - slope * line1S.X;
  852. float newX = line2S.X, newY = slope * newX + offset;
  853. if (newX >= line1Xmin && newX <= line1Xmax && newY >= line1Ymin && newY <= line1Ymax
  854. && newY >= line2Ymin && newY <= line2Ymax)
  855. {
  856. interPoint = new PointF(newX, newY); status = 1;
  857. }
  858. }
  859. // line1和line2都不垂直于X轴
  860. else
  861. {
  862. float slope1 = (line1S.Y - line1E.Y) / (line1S.X - line1E.X);
  863. float offset1 = line1S.Y - slope1 * line1S.X;
  864. float slope2 = (line2S.Y - line2E.Y) / (line2S.X - line2E.X);
  865. float offset2 = line2S.Y - slope2 * line2S.X;
  866. // 如果两条直线平行
  867. if (slope1 == slope2)
  868. {
  869. if (offset1 != offset2) status = -1;
  870. else if (line1Xmax == line2Xmin)
  871. {
  872. interPoint = new PointF(line1Xmax, line1Xmax * slope1 + offset1); status = 1;
  873. }
  874. else if (line1Xmin == line2Xmax)
  875. {
  876. interPoint = new PointF(line1Xmin, line1Xmin * slope1 + offset1); status = 1;
  877. }
  878. else if (line1Xmax < line2Xmin || line1Xmin > line2Xmax) status = -1;
  879. else status = 2;
  880. }
  881. else
  882. {
  883. float newX = (offset2 - offset1) / (slope1 - slope2), newY = newX * slope1 + offset1;
  884. if (newX >= line1Xmin && newX <= line1Xmax && newX >= line2Xmin && newX <= line2Xmax)
  885. {
  886. interPoint = new PointF(newX, newY); status = 1;
  887. }
  888. }
  889. }
  890. }
  891. if (status == 1)
  892. {
  893. return true;
  894. }
  895. else
  896. {
  897. return false;
  898. }
  899. }
  900. /// <summary>
  901. /// 获取Segment信息
  902. /// </summary>
  903. /// <param name="points"></param>
  904. /// <param name="SegmentClrList"></param>
  905. /// <param name="SegmentList"></param>
  906. public void GetSegment(List<Point> points, List<COTSSegmentClr> SegmentClrList, ref List<Segment> SegmentList)
  907. {
  908. List<int> segmentStart = new List<int>();
  909. List<int> segmentHeight = new List<int>();
  910. List<int> segmentLength = new List<int>();
  911. FindSegment(points, ref segmentStart, ref segmentHeight, ref segmentLength);
  912. for (int i = 0; i < segmentLength.Count; i++)
  913. {
  914. COTSSegmentClr seg = new COTSSegmentClr();
  915. seg.SetStart(segmentStart[i]);
  916. seg.SetHeight(segmentHeight[i]);
  917. seg.SetLength(segmentLength[i]);
  918. SegmentClrList.Add(seg);
  919. Segment segment = new Segment();
  920. segment.Start = segmentStart[i];
  921. segment.Height = segmentHeight[i];
  922. segment.Length = segmentLength[i];
  923. segment.SegmentNum = segmentLength.Count;
  924. segment.SegmentId = i;
  925. segment.FieldId = m_ParticleSegmentation.ParticleData.FieldId;
  926. segment.XRayId = m_ParticleSegmentation.ParticleData.XrayId;
  927. segment.ParticleId = m_ParticleSegmentation.ParticleData.ParticleId;
  928. SegmentList.Add(segment);
  929. }
  930. }
  931. /// <summary>
  932. /// 寻找segment方法
  933. /// </summary>
  934. public void FindSegment(List<Point> point_list_final, ref List<int> segmentStart, ref List<int> segmentHeight, ref List<int> segmentLength)
  935. {
  936. int flag = 0;
  937. point_list_final.Sort(my_sort);//排序
  938. for (int k = 0; k < point_list_final.Count(); k++)
  939. {
  940. if (k == 0 && k != point_list_final.Count() - 1)//第一个颗粒
  941. {
  942. flag++;
  943. segmentStart.Add(point_list_final[k].X);
  944. segmentHeight.Add(point_list_final[k].Y);
  945. }
  946. else if (k == 0 && k == point_list_final.Count() - 1)//只有一个颗粒
  947. {
  948. segmentStart.Add(point_list_final[k].X);
  949. segmentHeight.Add(point_list_final[k].Y);
  950. segmentLength.Add(1);
  951. }
  952. else if (k == point_list_final.Count() - 1)//最后一个颗粒
  953. {
  954. flag++;
  955. segmentLength.Add(flag);
  956. }
  957. 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)//同行连续
  958. {
  959. flag++;
  960. }
  961. 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)//同行隔断
  962. {
  963. segmentLength.Add(flag);
  964. flag = 1;
  965. segmentStart.Add(point_list_final[k].X);
  966. segmentHeight.Add(point_list_final[k].Y);
  967. }
  968. else if (point_list_final[k].Y != point_list_final[k - 1].Y)//不同行
  969. {
  970. segmentLength.Add(flag);
  971. flag = 1;
  972. segmentStart.Add(point_list_final[k].X);
  973. segmentHeight.Add(point_list_final[k].Y);
  974. }
  975. }
  976. }
  977. /// <summary>
  978. /// 排序方法
  979. /// </summary>
  980. /// <param name="p1"></param>
  981. /// <param name="p2"></param>
  982. /// <returns></returns>
  983. private int my_sort(Point p1, Point p2)
  984. {
  985. return p1.Y == p2.Y ? p1.X.CompareTo(p2.X) : p1.Y.CompareTo(p2.Y); //升序排序
  986. }
  987. public object CloneObject(object obj)
  988. {
  989. using (MemoryStream stream = new MemoryStream())
  990. {
  991. BinaryFormatter formatter = new BinaryFormatter();
  992. stream.Position = 0;
  993. formatter.Serialize(stream, obj);
  994. stream.Position = 0;
  995. return formatter.Deserialize(stream);
  996. }
  997. }
  998. #endregion
  999. }
  1000. }