OTSImageDisHelp.cs 44 KB

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