OTSIncAReportFun.cs 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450
  1. 
  2. using OTSIncAReportApp.DataOperation.DataAccess;
  3. using OTSIncAReportApp.DataOperation.Model;
  4. using OTSIncAReportApp.SysMgrTools;
  5. using OTSIncAReportGraph.Class;
  6. using OTSIncAReportGraph.Controls;
  7. using System;
  8. using System.Collections;
  9. using System.Collections.Generic;
  10. using System.Data;
  11. using System.Diagnostics;
  12. using System.Drawing;
  13. using System.Linq;
  14. namespace OTSIncAReportGraph.OTSIncAReportGraphFuncation
  15. {
  16. class OTSIncAReportFun
  17. {
  18. #region 枚举定义
  19. /// <summary>
  20. /// 样品台X轴方向
  21. /// </summary>
  22. enum OTS_X_AXIS_DIRECTION
  23. {
  24. LEFT_TOWARD = 0,
  25. RIGHT_TOWARD = 1
  26. }
  27. /// <summary>
  28. /// 样品台Y轴方向
  29. /// </summary>
  30. enum OTS_Y_AXIS_DIRECTION
  31. {
  32. UP_TOWARD = 0,
  33. DOWN_TOWARD = 1
  34. }
  35. #endregion
  36. #region 定义变量
  37. private ResultFile resultFile = null;
  38. //新版排序图窗体对象
  39. private Control_DrawDistrbutionSortImage m_Control_DrawdistrbutionsortImage = null;
  40. //新版分布图和BSE图整合对象
  41. private Control_DrawDistrbutionImageAndBSE m_Control_DrawDistrbutionImageAndBSE = null;
  42. //全局对象,为了能够快速的获取到xray数据,而做为一个临时变量进行保存,使用前应该判断是否为空
  43. public List<Field> m_list_COTSFieldMgrClr = null;
  44. NLog.Logger log = NLog.LogManager.GetCurrentClassLogger();
  45. //field的数量
  46. public int m_field_count = 0;
  47. //particle的数量
  48. public int m_particle_count = 0;
  49. //加载使用的时间
  50. public string m_time_str = "";
  51. //加载使用时间计算时间段2
  52. public string m_time_str2 = "";
  53. //防止segment过多的数量限制,先写300吧,过少也不好,过防止过多程序而卡死
  54. public int m_segment_overflownumber = 400;
  55. //电镜设置对象
  56. public ServiceInterface.SemController m_cfun = null;
  57. //是否已经连接到了电镜
  58. public bool m_SEMConnectionState = false;
  59. //连接到电镜的ID号
  60. public int m_SEM_ID = 0;
  61. //国际化
  62. Language lan = new Language();
  63. Hashtable table;
  64. #endregion
  65. #region 构造函数
  66. /// <summary>
  67. /// 构造函数,接收新版分布图和排序图的构造函数
  68. /// </summary>
  69. /// <param name="in_Control_DrawDistrbutionImageAndBSE"></param>
  70. /// <param name="in_Cotsreportprojfilemgrclr"></param>
  71. public OTSIncAReportFun(Control_DrawDistrbutionImageAndBSE in_Control_DrawDistrbutionImageAndBSE, ResultFile result)
  72. {
  73. m_Control_DrawDistrbutionImageAndBSE = in_Control_DrawDistrbutionImageAndBSE;
  74. resultFile = result;
  75. m_cfun =new ServiceInterface.SemController();
  76. table = lan.GetNameTable("OTSIncAReportFun");
  77. }
  78. /// <summary>
  79. /// 构造函数,接收新版颗粒排序图的构造
  80. /// </summary>
  81. /// <param name="in_Control_DrawDistrbutionSortimage"></param>
  82. /// <param name="in_Cotsreportprojfilemgrclr"></param>
  83. public OTSIncAReportFun(Control_DrawDistrbutionSortImage in_Control_DrawDistrbutionSortimage, ResultFile result)
  84. {
  85. m_Control_DrawdistrbutionsortImage = in_Control_DrawDistrbutionSortimage;
  86. resultFile = result;
  87. m_cfun = new ServiceInterface.SemController();
  88. table = lan.GetNameTable("OTSIncAReportFun");
  89. }
  90. #endregion
  91. #region 封装自定义方法
  92. /// <summary>
  93. /// 根据颗粒排序图获取已经选择上的颗粒,返回被选择上的颗粒的列表
  94. /// </summary>
  95. /// <returns></returns>
  96. public List<Particle> GetSelectedParticleList_ForDrawDistrbutionImageAndBSE()
  97. {
  98. List<Particle> ls_list_cotsparticleclr = new List<Particle>();
  99. //防止为空校验判断
  100. if (m_list_COTSFieldMgrClr == null)
  101. return ls_list_cotsparticleclr;
  102. //先取出,所有被选择的dparticle列表的
  103. List<DParticle> ls_list_dp = new List<DParticle>();
  104. foreach (DParticle ls_dp in m_Control_DrawDistrbutionImageAndBSE.m_list_baseobject)
  105. {
  106. if (ls_dp.Operator == ParticleOperator.SELECTED)
  107. {
  108. ls_list_dp.Add(ls_dp);
  109. }
  110. }
  111. //并开始查找包含tagid和fieldid的cotsparticle的对象,保存到list当中
  112. for (int i = 0; i < ls_list_dp.Count(); i++)
  113. {
  114. for (int j = 0; j < m_list_COTSFieldMgrClr.Count(); j++)
  115. {
  116. //先获取该field中的所有particle
  117. List<Particle> list_cotsparticleclr = new List<Particle>();
  118. list_cotsparticleclr = m_list_COTSFieldMgrClr[j].ParticleList;
  119. for (int k = 0; k < list_cotsparticleclr.Count(); k++)
  120. {
  121. if (list_cotsparticleclr[k].ParticleId == ls_list_dp[i].CLRTagID
  122. && list_cotsparticleclr[k].FieldId == ls_list_dp[i].CLRFieldID)
  123. {
  124. ls_list_cotsparticleclr.Add(list_cotsparticleclr[k]);
  125. }
  126. }
  127. }
  128. }
  129. return ls_list_cotsparticleclr;
  130. }
  131. /// <summary>
  132. /// 计算像素总画面Image大小,及进行物理坐标与分辨率坐标的换算操作 传入物理坐标,及宽高,来
  133. /// </summary>
  134. /// <param name="in_list_point">传入的物理坐标数组</param>
  135. /// <param name="width">单个field宽</param>
  136. /// <param name="height">单个field高</param>
  137. /// <returns></returns>
  138. public Rectangle ConvertAndGetMaxRect(List<Point> in_list_point, int in_width, int in_height)
  139. {
  140. //首先要能确定下来,单个物理坐标的宽和高--------------------------------
  141. int i_wl_width = 0;
  142. int i_wl_height = 0;
  143. Rectangle ls_r = GetOneFieldWidthAndHeight(in_list_point);
  144. i_wl_width = ls_r.Width;
  145. i_wl_height = ls_r.Height;
  146. //-----------------------------------------------------------------------------
  147. int point_x_min = 10000000;
  148. int point_x_max = -10000000;
  149. int point_y_min = 10000000;
  150. int point_y_max = -10000000;
  151. for (int i = 0; i < in_list_point.Count(); i++)
  152. {
  153. Point ls_point = in_list_point[i];
  154. //取出正数最大x
  155. if (ls_point.X > point_x_max)
  156. point_x_max = ls_point.X;
  157. if (ls_point.Y > point_y_max)
  158. point_y_max = ls_point.Y;
  159. if (ls_point.X < point_x_min)
  160. point_x_min = ls_point.X;
  161. if (ls_point.Y < point_y_min)
  162. point_y_min = ls_point.Y;
  163. }
  164. //然后分别用最大值+abs(最小值),就是x,和y轴的总长值
  165. point_x_max = point_x_max - point_x_min;
  166. point_y_max = point_y_max - point_y_min;
  167. //该算法有个问题,就是不能直观的得到整个范围的大小,要除以倍数再补1能补充缺少的一个field视域**********
  168. point_x_max = ((point_x_max / i_wl_width) + 1) * i_wl_width;
  169. point_y_max = ((point_y_max / i_wl_height) + 1) * i_wl_height;
  170. //将物理宽高,变换成分辨率宽高
  171. if (i_wl_width != 0) point_x_max = (point_x_max / i_wl_width) * in_width; else point_x_max = 0;
  172. if (i_wl_height != 0) point_y_max = (point_y_max / i_wl_height) * in_height; else point_y_max = 0;
  173. Rectangle ret_rectangle = new Rectangle(0, 0, 0, 0);
  174. //判断一下防止出错,只有在有数据的情况下,进行赋值才行
  175. if (in_list_point.Count > 0)
  176. {
  177. ret_rectangle = new Rectangle(0, 0, point_x_max, point_y_max);
  178. }
  179. //这样返回是物理坐标的总大小,应该返回像素坐标大小才对
  180. return ret_rectangle;
  181. }
  182. /// <summary>
  183. /// 通过传入的各field物理坐标列表,和单个field的屏幕分辨率,及单个的field的物理坐标,来获取当前field在整个image中的屏幕像素坐标偏移,并且是OTS向上为正做了Y轴相反运算
  184. /// </summary>
  185. /// <param name="in_list_point"></param>
  186. /// <param name="in_screen_width"></param>
  187. /// <param name="in_screen_height"></param>
  188. /// <param name="in_physics_width"></param>
  189. /// <param name="in_physics_height"></param>
  190. /// <returns></returns>
  191. public Point GetFieldPhysicsConvertToScreen(List<Point> in_list_point, int in_screen_width, int in_screen_height, Point in_physics_point)
  192. {
  193. //先确定单个物理坐标的宽和高
  194. Rectangle rect_onefield_wl = GetOneFieldWidthAndHeight(in_list_point);
  195. //找出最小的x,y用来做偏移运算
  196. int i_offset_x = 1000000000;
  197. int i_offset_y = 1000000000;
  198. //先取出最小的x,y
  199. for (int i = 0; i < in_list_point.Count; i++)
  200. {
  201. if (i_offset_x > in_list_point[i].X)
  202. {
  203. i_offset_x = in_list_point[i].X;
  204. }
  205. if (i_offset_y > in_list_point[i].Y)
  206. {
  207. i_offset_y = in_list_point[i].Y;
  208. }
  209. }
  210. List<Point> list_point = new List<Point>();
  211. //将各Field的OTS坐标与屏幕左上角的坐标进行相减,取出与屏幕左上角的偏移量,也就是取出了屏幕坐标
  212. int index = 0;
  213. for (int i = 0; i < in_list_point.Count; i++)
  214. {
  215. list_point.Add(new Point(in_list_point[i].X - i_offset_x, in_list_point[i].Y - i_offset_y));
  216. //根据物理坐标的对应关系,找到了在数组中的位置,下面将用该位置对应得出像素坐标的位置,并进行返回
  217. if (in_list_point[i] == in_physics_point)
  218. {
  219. index = i;
  220. }
  221. }
  222. //再将物理像素list_point换算成像素list_point,再用index定位
  223. for (int i = 0; i < list_point.Count; i++)
  224. {
  225. //将单个物理像素变换成屏幕像素分辨率
  226. int i_bs_x = 0;
  227. int i_bs_y = 0;
  228. if (rect_onefield_wl.Width != 0)
  229. i_bs_x = list_point[i].X / rect_onefield_wl.Width;
  230. if (rect_onefield_wl.Height != 0)
  231. i_bs_y = list_point[i].Y / rect_onefield_wl.Height;
  232. //再将屏幕像素分辨率按倍数赋值给list_point
  233. //考虑到OTS坐标整体是Y轴向上为正,所以这里需要根据总高,减y轴就是向上为正
  234. list_point[i] = new Point(in_screen_width * i_bs_x, in_screen_height * i_bs_y);
  235. }
  236. #region Y轴向上为正转换---------------------------------------------------------------------------------------
  237. //但上面由于相减,会出现y轴为负的情况,所以这里要根据Y轴是否出现负值,再次做偏移运算
  238. //找到最小的y轴,也就是 [Y轴偏移量]
  239. int i_offset_y_second = 100000000;
  240. //找到最大的Y轴,用于做相反运算,Y轴向上
  241. int i_screen_y = -100000000;
  242. for (int i = 0; i < list_point.Count; i++)
  243. {
  244. if (i_offset_y_second > list_point[i].Y)
  245. {
  246. i_offset_y_second = list_point[i].Y;//这个偏移Y就是最小的Y,可能是负数,也可能是0
  247. }
  248. if (i_screen_y < list_point[i].Y)
  249. {
  250. i_screen_y = list_point[i].Y;
  251. }
  252. }
  253. //对Y轴进行反转,OTS坐标向屏幕坐标转换
  254. for (int i = 0; i < list_point.Count; i++)
  255. {
  256. list_point[i] = new Point(list_point[i].X, i_screen_y - list_point[i].Y);
  257. }
  258. //再将所有的Field与这个 [Y轴偏移量] 相加,防止OTS向上为正转换屏幕坐标,造成的Y轴为负的情况
  259. for (int i = 0; i < list_point.Count; i++)
  260. {
  261. list_point[i] = new Point(list_point[i].X, list_point[i].Y + Math.Abs(i_offset_y_second));
  262. }
  263. #endregion Y轴向上为正转换结束--------------------------------------------------------------------------
  264. return list_point[index];
  265. }
  266. /// <summary>
  267. /// 计算单个field的物理大小 传入field的list,还有测量结果管理类对象,在无法计算出单file的物理大小的情况下,到这里取再计算得出
  268. /// </summary>
  269. /// <returns></returns>
  270. public Rectangle GetOneFieldWidthAndHeight(List<Point> in_list_point)
  271. {
  272. int i_wl_width_max = -10000000;
  273. int i_wl_height_max = -10000000;
  274. int i_wl_width_max2 = -10000000;
  275. int i_wl_height_max2 = -10000000;
  276. //先找出最大的值,
  277. for (int i = 0; i < in_list_point.Count(); i++)
  278. {
  279. if (i_wl_width_max < in_list_point[i].X)
  280. i_wl_width_max = in_list_point[i].X;
  281. if (i_wl_height_max < in_list_point[i].Y)
  282. i_wl_height_max = in_list_point[i].Y;
  283. }
  284. //再找出第二大的值
  285. for (int i = 0; i < in_list_point.Count(); i++)
  286. {
  287. if (i_wl_width_max2 < in_list_point[i].X && i_wl_width_max != in_list_point[i].X)
  288. i_wl_width_max2 = in_list_point[i].X;
  289. if (i_wl_height_max2 < in_list_point[i].Y && i_wl_height_max != in_list_point[i].Y)
  290. i_wl_height_max2 = in_list_point[i].Y;
  291. }
  292. //需要针对第二大的值,获取时进行判断,感觉这里应该如果并未找到第二大的值的情况下,赋于0值,便于以后进行计算
  293. if (i_wl_width_max2 == -10000000)
  294. i_wl_width_max2 = 0;
  295. if (i_wl_height_max2 == -10000000)
  296. i_wl_height_max2 = 0;
  297. Rectangle ret_rect = new Rectangle(0, 0, i_wl_width_max - i_wl_width_max2, i_wl_height_max - i_wl_height_max2);
  298. //如果最后计算出的宽高有0则重新到测量数据中获取---------------------------------------
  299. if (ret_rect.Width == 0 || ret_rect.Height == 0)
  300. {
  301. //到参数中去取单个宽
  302. double d_onefilesize_width = Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  303. //然后再用单个宽去计算出高是多少
  304. double d_onefilesize_height = 0;
  305. if (d_onefilesize_width != 0)
  306. d_onefilesize_height = (d_onefilesize_width / 4) * 3;
  307. ret_rect.Width = (int)d_onefilesize_width;
  308. ret_rect.Height = (int)d_onefilesize_height;
  309. }
  310. ///-----------because all the fields 's height/width=0.75 so here we make an enforce. gsp add at 2019/10/31
  311. ///sometimes the gbfields are not conform to this for the cuting and merging operation.
  312. if (ret_rect.Height / ret_rect.Width != 0.75f)
  313. {
  314. ret_rect = new Rectangle(ret_rect.X, ret_rect.Y, ret_rect.Width, (int)(ret_rect.Width * 0.75f));
  315. }
  316. return ret_rect;
  317. }
  318. #endregion
  319. #region 电镜操作相关方法
  320. /// <summary>
  321. /// 连接电镜,分布图使用
  322. /// </summary>
  323. public void ConnectToSEM()
  324. {
  325. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM");
  326. if (!m_SEMConnectionState)
  327. {
  328. //和电镜建立通讯连接
  329. m_SEMConnectionState = m_cfun.Connect();
  330. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM" + ":--" + m_SEMConnectionState + "---");
  331. ///获取当前电镜的ID号
  332. //m_SEM_ID = m_cfun.get
  333. //log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "ID:" + m_SEM_ID.ToString());
  334. }
  335. else
  336. {
  337. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + ":allready connected, state:" + m_SEMConnectionState);
  338. //断开电镜连接
  339. }
  340. }
  341. public void DisConnectSEM()
  342. {
  343. m_SEMConnectionState = false;
  344. m_cfun.DisConnect();
  345. }
  346. /// <summary>
  347. /// 移动电镜到指定的X,Y坐标上,R坐标使用原先的值进行移动
  348. /// </summary>
  349. /// <param name="PositionX"></param>
  350. /// <param name="PositionY"></param>
  351. public void MoveSemToPointXY(double in_PositionX, double in_PositionY)
  352. {
  353. log.Trace("Begin MoveSemToPointXY:(" +in_PositionX.ToString()+","+in_PositionY.ToString()+")");
  354. //首先获取电镜当前的位置,并记录原R值
  355. double ls_PositionX = 0;
  356. double ls_PositionY = 0;
  357. double ls_PositionR = 0;
  358. if (m_SEMConnectionState)
  359. {
  360. m_cfun.GetSemPositionXY(ref ls_PositionX, ref ls_PositionY, ref ls_PositionR);
  361. }
  362. else
  363. {
  364. log.Error("Failed to GetSemPositionXY");
  365. return;
  366. }
  367. if (m_SEMConnectionState)
  368. {
  369. m_cfun.MoveSEMToPoint(new Point((int)in_PositionX, (int)in_PositionY), ls_PositionR);
  370. }
  371. }
  372. #endregion
  373. #region //--------------------------------------颗粒分布图相关部份---------------------------------------------------------------------
  374. /// <summary>
  375. /// 传入颗粒的tagid和fieldid,来获取该颗粒下对应的xray数据
  376. /// </summary>
  377. /// <param name="in_clr_tagid"></param>
  378. /// <param name="in_clr_fieldid"></param>
  379. /// <param name="Search_xray"></param>
  380. /// <param name="Analysis_xray"></param>
  381. 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)
  382. {
  383. Search_xray = new uint[2000];
  384. Analysis_xray = new uint[2000];
  385. xray_id = 0;
  386. list_celementchemistryclr = new List<Element>();
  387. //防止为空校验判断
  388. if (m_list_COTSFieldMgrClr == null)
  389. return;
  390. Particle particle = m_list_COTSFieldMgrClr.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid);
  391. if (particle.XrayId > -1)
  392. {
  393. for (int i = 0; i < 2000; i++)
  394. {
  395. Analysis_xray[i] = BitConverter.ToUInt32(particle.XRayData, i * 4);
  396. }
  397. Search_xray = Analysis_xray;
  398. xray_id = particle.XrayId;
  399. list_celementchemistryclr = particle.ElementList;
  400. }
  401. }
  402. /// <summary>
  403. /// 传入所有的物理field坐标点,和单个物理field的宽高,返回所有field的左上角位置,和整个field组成的rect大小
  404. /// </summary>
  405. /// <param name="in_list_point"></param>
  406. /// <param name="in_width"></param>
  407. /// <param name="in_height"></param>
  408. /// <returns></returns>
  409. public Rectangle GetWlRectTopLeftAndRect(List<Point> in_list_point, int in_width, int in_height)
  410. {
  411. //分别获取整个rect的xy最小值和最大值
  412. int i_rect_x_min = 100000000;
  413. int i_rect_y_min = 100000000;
  414. int i_rect_x_max = -100000000;
  415. int i_rect_y_max = -100000000;
  416. for (int i = 0; i < in_list_point.Count; i++)
  417. {
  418. if (i_rect_x_min > in_list_point[i].X)
  419. i_rect_x_min = in_list_point[i].X;
  420. if (i_rect_y_min > in_list_point[i].Y)
  421. i_rect_y_min = in_list_point[i].Y;
  422. if (i_rect_x_max < in_list_point[i].X)
  423. i_rect_x_max = in_list_point[i].X;
  424. if (i_rect_y_max < in_list_point[i].Y)
  425. i_rect_y_max = in_list_point[i].Y;
  426. }
  427. Rectangle ret_rect = new Rectangle(i_rect_x_min, i_rect_y_min,
  428. i_rect_x_max - i_rect_x_min, i_rect_y_max - i_rect_y_min);
  429. return ret_rect;
  430. }
  431. /// <summary>
  432. /// 根据Field的ID,来获取Field列表中对应FIeld的OTS 坐标
  433. /// </summary>
  434. /// <param name="in_fieldid"></param>
  435. /// <returns></returns>
  436. public Point GetOTSPointByFieldID(List<DField> in_list_dfield, int in_fieldid)
  437. {
  438. Point ret_point = new Point(0, 0);
  439. for (int i = 0; i < in_list_dfield.Count; i++)
  440. {
  441. //这里TagID先代表的是底层返回的ID
  442. if (in_list_dfield[i].FieldID == in_fieldid.ToString())
  443. {
  444. ret_point = new Point(Convert.ToInt32(in_list_dfield[i].OTS_RECT.X), Convert.ToInt32(in_list_dfield[i].OTS_RECT.Y));
  445. }
  446. }
  447. return ret_point;
  448. }
  449. /// <summary>
  450. /// 将OTS坐标转换为Sem 坐标
  451. /// </summary>
  452. /// <param name="POTSCoord"></param>
  453. /// <returns></returns>
  454. public Point ChangeOTSToSemCoord(Point POTSCoord)
  455. {
  456. //first if m_semstagedata is null to get stage inforation
  457. Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  458. //after obtaining stage info,calc stage point data
  459. Point ret_SEM_point = new Point();
  460. // get center point, um
  461. long xStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["start"]);
  462. long xEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["end"]);
  463. long xCenter = (xStart + xEnd) / 2;
  464. long yStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["start"]);
  465. long yEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["end"]);
  466. long yCenter = (yStart + yEnd) / 2;
  467. // delte = SEM - OTSa
  468. long deltex = xCenter - 0;
  469. long deltey = yCenter - 0;
  470. int xdir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["xAxisDir"]);
  471. int ydir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["yAxisDir"]);
  472. if (xdir == (int)OTS_X_AXIS_DIRECTION.LEFT_TOWARD)
  473. {
  474. ret_SEM_point.X = -1 * (POTSCoord.X - Convert.ToInt32(deltex));
  475. }
  476. else if (xdir == (int)OTS_X_AXIS_DIRECTION.RIGHT_TOWARD)
  477. {
  478. ret_SEM_point.X = POTSCoord.X + Convert.ToInt32(deltex);
  479. }
  480. if (ydir == (int)OTS_Y_AXIS_DIRECTION.UP_TOWARD)
  481. {
  482. ret_SEM_point.Y = POTSCoord.Y + Convert.ToInt32(deltey);
  483. }
  484. else if (ydir == (int)OTS_Y_AXIS_DIRECTION.DOWN_TOWARD)
  485. {
  486. ret_SEM_point.Y = -1 * (POTSCoord.Y - Convert.ToInt32(deltey));
  487. }
  488. return ret_SEM_point;
  489. }
  490. /// <summary>
  491. /// 获取组整个获取分布图和排序图图像数据的底层数据组建方式,的总过程
  492. /// </summary>
  493. public void GetDistrbutionImageAndBSE_Total(OTSIncAReportApp.frmReportApp a_Report)
  494. {
  495. string str27 = "开始从底层加载数据....";
  496. str27 = table["str27"].ToString();
  497. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(1, str27);
  498. //对底层加载速度进行计时
  499. Stopwatch stopwatch = new Stopwatch();
  500. stopwatch.Start();
  501. string path = resultFile.FilePath;
  502. FieldData fieldData = new FieldData(path);
  503. List<Field> fieldlist = fieldData.GetFieldList(a_Report);
  504. //防止有时底层返回的Field的List是0,直接返回
  505. if (fieldlist.Count == 0)
  506. {
  507. string str28 = "底层返回视域数据数量为0....";
  508. str28 = table["str28"].ToString();
  509. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(100, str28);
  510. return;
  511. }
  512. //底层加载field对象结束
  513. stopwatch.Stop();
  514. TimeSpan timespan = stopwatch.Elapsed;
  515. //重置计数器,对组建和计算图像进行计时
  516. stopwatch.Reset();
  517. stopwatch.Start();
  518. string str29 = "开始组建图像视域....";
  519. str29 = table["str29"].ToString();
  520. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(15, str29);
  521. //将field的list对象给全局变量中,供后面获取xray使用,不需要再次重新加载数据,以提升速度
  522. m_list_COTSFieldMgrClr = fieldlist;
  523. //第一次循环,用来计算单个Field的像素分辨率,和将所有的物理位置存放到List当中
  524. List<Point> list_point = new List<Point>();
  525. int i_field_width = 0, i_field_height = 0;
  526. //获取到该field的分辨率大小,循环中都是一样的
  527. if (fieldlist.Count > 0)
  528. {
  529. Bitmap bitmp = DrawFuncation.ReadImageFile(fieldlist[0].FieldImage);
  530. i_field_width = bitmp.Width;
  531. i_field_height = bitmp.Height;
  532. }
  533. for (int i = 0; i < fieldlist.Count(); i++)
  534. {
  535. //然后取出物理坐标,这个一会要与分辨率坐标进行变算一下
  536. Point ls_point = new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY };
  537. list_point.Add(ls_point);
  538. }
  539. //对单个视域的屏幕像素宽高,进行记录
  540. m_Control_DrawDistrbutionImageAndBSE.m_OneField_Screen_BackRectf = new RectangleF(0, 0, i_field_width, i_field_height);
  541. //获取单个OTS视域像素宽高,并进行记录
  542. Rectangle OTS_FieldRect = GetOneFieldWidthAndHeight(list_point);
  543. m_Control_DrawDistrbutionImageAndBSE.m_OneField_OTS_Rectf = OTS_FieldRect;
  544. //计算出整个绘制图像总Rectagnle的大小
  545. m_Control_DrawDistrbutionImageAndBSE.m_backrectf = ConvertAndGetMaxRect(list_point, i_field_width, i_field_height);
  546. string str30 = "计算标尺....";
  547. str30 = table["str30"].ToString();
  548. //更新进度条提示
  549. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(18, str30);
  550. #region //标尺相关------------------------------------------------------------------------------
  551. //在此处通过上面的i_field_width,ifield_height和list_point,来计算出个像素与实际物理值的比例
  552. Rectangle ls_jsblrect = GetOneFieldWidthAndHeight(list_point);
  553. //然后用宽度来除以i_field_width 获取单个的像素比例
  554. double d_onepixel_scale = Convert.ToDouble(ls_jsblrect.Width) / Convert.ToDouble(i_field_width);
  555. //再用该比例对标尺进行相应的赋值
  556. m_Control_DrawDistrbutionImageAndBSE.m_f_onepixel_size = (float)d_onepixel_scale;
  557. //对整个物理像素的范围进行获取与设置
  558. Rectangle ls_offsetandtopleftrect = GetWlRectTopLeftAndRect(list_point, ls_jsblrect.Width, ls_jsblrect.Height);
  559. m_Control_DrawDistrbutionImageAndBSE.m_back_wl_rectf = new RectangleF(ls_offsetandtopleftrect.X, ls_offsetandtopleftrect.Y
  560. , ls_offsetandtopleftrect.Width, ls_offsetandtopleftrect.Height);
  561. #endregion //---------------------------------------------------------------------------------------
  562. string str31 = "组建整图数据....";
  563. str31 = table["str31"].ToString();
  564. //更新进度条提示
  565. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(20, str31);
  566. //70的进度条给到下面的循环中,计算进度条各分类进度分配
  567. float ls_int_progresscalc = 0;
  568. if (fieldlist.Count > 0)
  569. ls_int_progresscalc = (float)70 / (float)fieldlist.Count;
  570. string str32 = "已完成第";
  571. str32 = table["str32"].ToString();
  572. string str33 = "个视域数据组建,共";
  573. str33 = table["str33"].ToString();
  574. string str34 = "个视域...";
  575. str34 = table["str34"].ToString();
  576. //再通过Field取到对应的Particle,循环一次
  577. for (int i = 0; i < fieldlist.Count(); i++)
  578. {
  579. //更新进度条提示
  580. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(20 + (int)(ls_int_progresscalc * (i + 1)), str32 + i.ToString() + str33 + m_list_COTSFieldMgrClr.Count.ToString() + str34);
  581. //先获取该Field中的所有Particle
  582. List<Particle> list_cotsparticleclr = new List<Particle>();
  583. list_cotsparticleclr = fieldlist[i].ParticleList;
  584. //取出该Field的物理坐标,将其转换成对应的屏幕像素坐标,屏幕左上角为原点(0,0)的偏移值,用于后面计算各Segment的位置使用
  585. //应该也就是这里根据OTS坐标转换到屏幕像素坐标,Y轴是反的,所以在这里对从OTS坐标转换成屏幕坐标的地方进行反转!
  586. Point thisfield_point = new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY };
  587. Point offset_point = GetFieldPhysicsConvertToScreen(list_point, i_field_width, i_field_height, thisfield_point);
  588. //保存该Field最终在屏幕上显示的位置及大小
  589. DField df = new DField();
  590. df.FieldID = fieldlist[i].FieldID.ToString();
  591. df.Show_Rect = new Rectangle(offset_point, new Size(i_field_width, i_field_height));
  592. df.Current_Rect = new Rectangle(offset_point, new Size(i_field_width, i_field_height));
  593. df.OTS_RECT = new RectangleF(thisfield_point.X, thisfield_point.Y, OTS_FieldRect.Width, OTS_FieldRect.Height);
  594. m_Control_DrawDistrbutionImageAndBSE.m_list_dfield.Add(df);
  595. //然后将取出的数据,转换成Bitmap对象
  596. Bitmap ls_bt = DrawFuncation.ReadImageFile(fieldlist[i].FieldImage);
  597. //再循环计算所有的Particle对象
  598. foreach (Particle ls_cotsparticleclr in list_cotsparticleclr)
  599. {
  600. //从Clr中获取所有的Segment的List对象
  601. List<Feature> list_cotssegmentclr = new List<Feature>();
  602. list_cotssegmentclr = ls_cotsparticleclr.FeatureList;
  603. //创建颗粒分布图对应的类对象
  604. List<DSegment> list_dsegment = new List<DSegment>();
  605. //创建DParticle颗粒,保存与之对应的颗粒tagid和particleid,为了后面取xray数据及多选时获取多选cotsparticleclr列表
  606. DParticle ls_dp = new DParticle();
  607. ls_dp.CLRTagID = ls_cotsparticleclr.ParticleId;
  608. ls_dp.CLRFieldID = ls_cotsparticleclr.FieldId;
  609. ls_dp.STDTypeID = ls_cotsparticleclr.TypeId;
  610. ls_dp.TypeId = ls_cotsparticleclr.TypeId;
  611. ls_dp.TypeName = ls_cotsparticleclr.TypeName;
  612. ls_dp.XRayId = ls_cotsparticleclr.XrayId;
  613. ls_dp.SEMPosX = ls_cotsparticleclr.SEMPosX;
  614. ls_dp.SEMPosY = ls_cotsparticleclr.SEMPosY;
  615. //获取该颗粒在STD标准库中已分析出化合物对应的颜色
  616. ls_dp.Color = GetColorBySTDTypeIDForBSEAndSorImage(ls_cotsparticleclr.TypeColor, ls_cotsparticleclr.TypeId);
  617. //防止超大颗粒,会让程序死掉
  618. if (list_cotssegmentclr.Count < m_segment_overflownumber)
  619. {
  620. //再循环取出里面所有的segment
  621. foreach (Feature ls_cotssegmentclr in list_cotssegmentclr)
  622. {
  623. #region 创建DSegment对象,并将STD分析出的化合物颜色保存到DSegment对象中
  624. //对Particle里的Segment进行偏移的计算等,创建了DSegment的大小
  625. DSegment ds = new DSegment();
  626. ds.Rect = new Rectangle(ls_cotssegmentclr.Start + offset_point.X,
  627. //i_field_height - ls_cotssegmentclr.GetHeight() + offset_point.Y,//这是让单个Field的图像按Y轴反过来
  628. ls_cotssegmentclr.Height + offset_point.Y,
  629. ls_cotssegmentclr.Length,
  630. 1);
  631. ds.Color = ls_dp.Color;//将线的颜色对应到颗粒的颜色
  632. #endregion
  633. #region //这里是在Field中,抠取出原BSE图像到DSegment中--------------------------------
  634. //ls_bt.RotateFlip(RotateFlipType.Rotate180FlipX);//使用系统带的图像处理方法,进行Y轴的翻转,与上面记录位置对应
  635. //合成图像完成,开始抠取像素-----------------------------------------------------------------
  636. int i_ls_length = ls_cotssegmentclr.Length;
  637. List<Color> ls_list_colors = new List<Color>();
  638. for (int m = 0; m < i_ls_length; m++)
  639. {
  640. //这里实现一下代码保护
  641. int lsjs_x = ls_cotssegmentclr.Start + m;
  642. //int lsjs_y = i_field_height - ls_cotssegmentclr.GetHeight();//这个反转要与上面对应
  643. int lsjs_y = ls_cotssegmentclr.Height;
  644. if (lsjs_x < 0)
  645. lsjs_x = 0;
  646. if (lsjs_x >= i_field_width)
  647. lsjs_x = i_field_width - 1;
  648. if (lsjs_y < 0)
  649. lsjs_y = 0;
  650. if (lsjs_y >= i_field_height)
  651. lsjs_y = i_field_height - 1;
  652. //按理说这里应该加上个横向抠取像素颜色,这里需要再处理一下
  653. ls_list_colors.Add(ls_bt.GetPixel(lsjs_x,
  654. lsjs_y));
  655. }
  656. //保存原BSE图中的颜色列表
  657. ds.List_Colors = ls_list_colors;
  658. #endregion //------------------------------------------------------------------------------
  659. list_dsegment.Add(ds);
  660. //ls_bt.Dispose();
  661. }
  662. }
  663. //设置Particle在0.5F倍数以上时才进行显示
  664. ls_dp.Zoom_DisPlayMultiplier = 0.5f;
  665. ls_dp.Zoom_DisPlay = true;
  666. //将segment对应的设置到particle中
  667. ls_dp.DSegments = list_dsegment;
  668. //并对DParticle相关信息进行计算
  669. ls_dp.Rect = ls_dp.GetRectFromDSegment();
  670. ls_dp.GPath = ls_dp.GetRegionFromDSegments();
  671. ls_dp.SmallRect = ls_dp.GetSmallRectangleFromRect();
  672. //将每个颗粒添加到颗粒分布图中的列表中
  673. m_Control_DrawDistrbutionImageAndBSE.m_list_baseobject.Add(ls_dp);
  674. if (ls_dp.XRayId > -1)
  675. {
  676. m_Control_DrawDistrbutionImageAndBSE.m_list_usebject.Add(ls_dp);
  677. }
  678. }
  679. }
  680. string str35 = "转换分辨率...";
  681. str35 = table["str35"].ToString();
  682. //更新进度条相关显示
  683. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(90, str35);
  684. //然后这里还需要计算出,各field的宽和高,帧图边框分别需要显示多少个框
  685. if (i_field_width != 0 && i_field_height != 0)
  686. {
  687. m_Control_DrawDistrbutionImageAndBSE.m_i_grid_showlinesnumber_width = Convert.ToInt32(m_Control_DrawDistrbutionImageAndBSE.BackRectF.Width / i_field_width);
  688. m_Control_DrawDistrbutionImageAndBSE.m_i_grid_showlinesnumber_height = Convert.ToInt32(m_Control_DrawDistrbutionImageAndBSE.BackRectF.Height / i_field_height);
  689. }
  690. string str36 = "完成其它工作...";
  691. str36 = table["str36"].ToString();
  692. //结束组建计算图像计数
  693. stopwatch.Stop();
  694. TimeSpan timespan2 = stopwatch.Elapsed;
  695. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(95, str36);
  696. string str37 = "分钟 ";
  697. str37 = table["str37"].ToString();
  698. string str38 = "秒 共(";
  699. str38 = table["str38"].ToString();
  700. string str39 = ")毫秒";
  701. str39 = table["str39"].ToString();
  702. //相关计数
  703. m_field_count = fieldlist.Count;
  704. m_particle_count = m_Control_DrawDistrbutionImageAndBSE.m_list_baseobject.Count;
  705. m_time_str = timespan.TotalMinutes.ToString("0.00") + str37 + timespan.TotalSeconds.ToString("0.00") + str38 + timespan.TotalMilliseconds.ToString() + str39;
  706. m_time_str2 = timespan2.TotalMinutes.ToString("0.00") + str37 + timespan2.TotalSeconds.ToString("0.00") + str38 + timespan2.TotalMilliseconds.ToString() + str39;
  707. }
  708. //读取进度条,虚拟读取,直接通过所有时域
  709. void setPr(float ls_int_progresscalc, string str32, string str33, string str34)
  710. {
  711. for (int i = 0; i < m_list_COTSFieldMgrClr.Count; i++)
  712. {
  713. m_Control_DrawDistrbutionImageAndBSE.m_frm_userprogress.SetProgressValueAndText(20 + (int)(ls_int_progresscalc * (i + 1)), str32 + i.ToString() + str33 + m_list_COTSFieldMgrClr.Count.ToString() + str34);
  714. }
  715. }
  716. /// <summary>
  717. /// 分布图和BSE图中,从底层获取相关结果后,重新组织显示
  718. /// </summary>
  719. /// <param name="ls_cgriddataclr"></param>
  720. public void GetDrawDistrbutionImageAndBSE_ByQuery(OTSIncAReportApp.OTSSampleReportInfo.OTSSampleMeaInfo sourceGridData)
  721. {
  722. var display = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 7);
  723. string display_type = display.itemVal.ToString();
  724. int disinde = display.comboDownList.IndexOf(display_type);
  725. var list = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 10);
  726. string size = list.itemVal.ToString();
  727. int inde = list.comboDownList.IndexOf(size);
  728. string size_cal_method_type = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 13).itemVal.ToString();
  729. string con = "";
  730. switch (size_cal_method_type)
  731. {
  732. case "DMAX":
  733. con = "DMAX";
  734. break;
  735. case "DMIN":
  736. con = "DMIN";
  737. break;
  738. case "Area":
  739. con = "Area";
  740. break;
  741. case "FERET":
  742. con = "DFERET";
  743. break;
  744. }
  745. string min = "0";
  746. string max = "999";
  747. if (inde != 0)
  748. {
  749. max = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 12).itemVal.ToString(); ;
  750. min = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 11).itemVal.ToString(); ;
  751. if (max.ToLower() == "max")
  752. {
  753. max = "999";
  754. }
  755. }
  756. string path = resultFile.FilePath;
  757. ParticleData particleData = new ParticleData(path);
  758. List<Particle> particles = particleData.GetParticleListByCon(con, max, min, disinde);
  759. foreach (DParticle ls_dp in m_Control_DrawDistrbutionImageAndBSE.m_list_baseobject)
  760. {
  761. int dis = 0;
  762. foreach (Particle particle in particles)
  763. {
  764. //找到对应的颗粒,将分类设置进去
  765. if (ls_dp.CLRTagID == particle.ParticleId && ls_dp.CLRFieldID == particle.FieldId)
  766. {
  767. //这里居然添加进来了7个,原来是这里,在底层直接取出了6个相同的颗粒到一起。
  768. ls_dp.ParticleFL = particle.TypeName;
  769. ls_dp.Operator = ParticleOperator.DISPLAY;
  770. dis = 1;
  771. break;
  772. }
  773. }
  774. if (dis == 0)
  775. {
  776. ls_dp.Operator = ParticleOperator.NODISPLAY;
  777. }
  778. }
  779. }
  780. #endregion
  781. #region //--------------------------------------颗粒排序图相关部份---------------------------------------------------------------------
  782. /// <summary>
  783. /// 根据颗粒排序图获取已经选择上的颗粒,返回被选择上的颗粒的列表
  784. /// </summary>
  785. /// <returns></returns>
  786. public List<Particle> GetSelectedParticleList_ForDrawDistrbutionSortImage()
  787. {
  788. List<Particle> ls_list_cotsparticleclr = new List<Particle>();
  789. //防止为空校验判断
  790. if (m_list_COTSFieldMgrClr == null)
  791. {
  792. return ls_list_cotsparticleclr;
  793. }
  794. //先取出,所有被选择的dparticle列表的
  795. List<DParticle> ls_list_dp = new List<DParticle>();
  796. foreach (SortParticleDistribution spd in m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution)
  797. {
  798. foreach (DParticle ls_dp in spd.List_DParticle)
  799. {
  800. if (ls_dp.Operator == ParticleOperator.SELECTED)
  801. {
  802. ls_list_dp.Add(ls_dp);
  803. }
  804. }
  805. }
  806. //并开始查找包含tagid和fieldid的cotsparticle的对象,保存到list当中
  807. for (int i = 0; i < ls_list_dp.Count(); i++)
  808. {
  809. for (int j = 0; j < m_list_COTSFieldMgrClr.Count(); j++)
  810. {
  811. //先获取该field中的所有particle
  812. List<Particle> list_cotsparticleclr = new List<Particle>();
  813. list_cotsparticleclr = m_list_COTSFieldMgrClr[j].ParticleList;
  814. for (int k = 0; k < list_cotsparticleclr.Count(); k++)
  815. {
  816. if (list_cotsparticleclr[k].ParticleId == ls_list_dp[i].CLRTagID
  817. && list_cotsparticleclr[k].FieldId == ls_list_dp[i].CLRFieldID)
  818. {
  819. //将cotsparticleclr保存到list当中
  820. ls_list_cotsparticleclr.Add(list_cotsparticleclr[k]);
  821. }
  822. }
  823. }
  824. }
  825. return ls_list_cotsparticleclr;
  826. }
  827. /// <summary>
  828. /// 根据传入的fieldid和tagid返回该颗粒的OTS坐标
  829. /// </summary>
  830. /// <param name="in_fieldid"></param>
  831. /// <param name="in_tagid"></param>
  832. /// <returns></returns>
  833. public Point GetOTSPointFromOld_list_sortparticledistribution(int in_fieldid, int in_tagid, Control_DrawDistrbutionSortImage in_control_drawdistrbutionsortimage)
  834. {
  835. Point ret_point = new Point(0, 0);
  836. if (m_list_COTSFieldMgrClr != null)
  837. {
  838. Field field = m_list_COTSFieldMgrClr.Find(x => x.FieldID == in_fieldid);
  839. ret_point = new Point() { X = field.FieldPosX, Y = field.FieldPosY };
  840. }
  841. return ret_point;
  842. }
  843. /// <summary>
  844. /// 排序图获取底层数据,组建整张排序图的总方法过程
  845. /// </summary>
  846. public void GetDistrbutionSortImage_Total(OTSIncAReportApp.frmReportApp a_ReportApp)
  847. {
  848. string str48 = "开始从底层加载数据....";
  849. str48 = table["str48"].ToString();
  850. m_Control_DrawdistrbutionsortImage.m_frm_userprogress.SetProgressValueAndText(1, str48);
  851. string path = resultFile.FilePath;
  852. FieldData fieldData = new FieldData(path);
  853. List<Field> fieldlist = fieldData.GetFieldList(a_ReportApp);
  854. //将field的list对象给全局变量中,供后面获取xray使用
  855. m_list_COTSFieldMgrClr = fieldlist;
  856. string str49 = "开始组建图像资源....";
  857. str49 = table["str49"].ToString();
  858. m_Control_DrawdistrbutionsortImage.m_frm_userprogress.SetProgressValueAndText(15, str49);
  859. //第一次,用来计算,总大小等,获取Field的坐标,id,同时获取对应的ImgClr里的宽高,图像大小
  860. List<Point> list_point = new List<Point>();
  861. int i_field_width = 0, i_field_height = 0;
  862. //获取到该field的分辨率大小,循环中都是一样的
  863. if (fieldlist.Count > 0)
  864. {
  865. Bitmap bitmp = DrawFuncation.ReadImageFile(fieldlist[0].FieldImage);
  866. i_field_width = bitmp.Width;
  867. i_field_height = bitmp.Height;
  868. }
  869. for (int i = 0; i < fieldlist.Count(); i++)
  870. {
  871. //然后取出物理坐标,这个一会要与分辨率坐标进行变算一下
  872. Point ls_point = new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY };
  873. list_point.Add(ls_point);
  874. }
  875. //对单个Field视域的屏幕像素宽高,进行记录
  876. m_Control_DrawdistrbutionsortImage.m_OneField_Screen_BackRectf = new RectangleF(0, 0, i_field_width, i_field_height);
  877. //获取单个OTS视域像素宽高,并进行记录
  878. Rectangle OTS_FieldRect = GetOneFieldWidthAndHeight(list_point);
  879. m_Control_DrawdistrbutionsortImage.m_OneField_OTS_Rectf = OTS_FieldRect;
  880. string str50 = "计算标尺....";
  881. str50 = table["str50"].ToString();
  882. m_Control_DrawdistrbutionsortImage.m_frm_userprogress.SetProgressValueAndText(18, str50);
  883. #region //标尺相关------------------------------------------------------------------------------
  884. //在此处通过上面的i_field_width,ifield_height和list_point,来计算出个像素与实际物理值的比例
  885. Rectangle ls_jsblrect = GetOneFieldWidthAndHeight(list_point);
  886. //然后用宽度来除以i_field_width 获取单个的像素比例
  887. double d_onepixel_scale = Convert.ToDouble(ls_jsblrect.Width) / Convert.ToDouble(i_field_width);
  888. //再用该比例对标尺进行相应的赋值
  889. m_Control_DrawdistrbutionsortImage.m_f_onepixel_size = (float)d_onepixel_scale;
  890. #endregion //---------------------------------------------------------------------------------------
  891. string str51 = "组建整图数据....";
  892. str51 = table["str51"].ToString();
  893. m_Control_DrawdistrbutionsortImage.m_frm_userprogress.SetProgressValueAndText(20, str51);
  894. //70的进度条给到下面的循环中
  895. float ls_int_progresscalc = 0;
  896. if (fieldlist.Count > 0)
  897. ls_int_progresscalc = (float)80 / (float)fieldlist.Count;
  898. string str52 = "已完成第";
  899. str52 = table["str52"].ToString();
  900. string str53 = "个数据,共";
  901. str53 = table["str53"].ToString();
  902. string str54 = "个数据...";
  903. str54 = table["str54"].ToString();
  904. //第二次,再通过Field取到对应的Particle,循环一次
  905. for (int i = 0; i < fieldlist.Count(); i++)
  906. {
  907. m_Control_DrawdistrbutionsortImage.m_frm_userprogress.SetProgressValueAndText(20 + (int)(ls_int_progresscalc * (i + 1)), str52 + i.ToString() + str53 + m_list_COTSFieldMgrClr.Count.ToString() + str54);
  908. //先获取该field中的所有particle
  909. List<Particle> list_cotsparticleclr = new List<Particle>();
  910. list_cotsparticleclr = fieldlist[i].ParticleList;
  911. //取出该Field中,从物理坐标转换到像素坐标后.不知道该算法是否可靠,先进行测试判断
  912. Point offset_point = GetFieldPhysicsConvertToScreen(list_point, i_field_width, i_field_height, new Point() { X = fieldlist[i].FieldPosX, Y = fieldlist[i].FieldPosY });
  913. //然后将取出的数据,转换成Bitmap对象
  914. Bitmap ls_bt = DrawFuncation.ReadImageFile(fieldlist[i].FieldImage);
  915. //再循环取出所有的particle
  916. foreach (Particle ls_cotsparticleclr in list_cotsparticleclr)
  917. {
  918. List<Feature> list_cotssegmentclr = new List<Feature>();
  919. list_cotssegmentclr = ls_cotsparticleclr.FeatureList;
  920. //创建颗粒分布图对应的类对象
  921. List<DSegment> list_dsegment = new List<DSegment>();
  922. //定义particle颗粒,并获取该颗粒与标准库中对应的颜色
  923. DParticle ls_dp = new DParticle();
  924. //ls_dp.Color = DrawFuncation.colorHx16toRGB(GetSTDItemClrByTypeIndex_ForDistrbutionSortImage(ls_cotsparticleclr.GetType()).GetColor());
  925. ls_dp.CLRFieldID = ls_cotsparticleclr.FieldId; //为我封装的颗粒保存上,底层对应的FieldID
  926. ls_dp.CLRTagID = ls_cotsparticleclr.ParticleId; //为我封装的颗粒对象保存上,底层对应的TagID
  927. ls_dp.STDTypeID = ls_cotsparticleclr.TypeId; //为我封装的颗粒对象保存上,类型
  928. ls_dp.TypeId = ls_cotsparticleclr.TypeId;
  929. ls_dp.TypeName = ls_cotsparticleclr.TypeName;
  930. ls_dp.XRayId = ls_cotsparticleclr.XrayId;
  931. ls_dp.SEMPosX = ls_cotsparticleclr.SEMPosX;
  932. ls_dp.SEMPosY = ls_cotsparticleclr.SEMPosY;
  933. ls_dp.Color = GetColorBySTDTypeIDForBSEAndSorImage(ls_cotsparticleclr.TypeColor, ls_cotsparticleclr.TypeId);
  934. //防止segment过多造成程序卡死
  935. if (list_cotssegmentclr.Count < m_segment_overflownumber)
  936. //再循环取出里面所有的segment
  937. foreach (Feature ls_cotssegmentclr in list_cotssegmentclr)
  938. {
  939. //这里的坐标未转换
  940. DSegment ds = new DSegment();
  941. ds.Rect = new Rectangle(ls_cotssegmentclr.Start + offset_point.X,
  942. //i_field_height - ls_cotssegmentclr.GetHeight() + offset_point.Y,
  943. ls_cotssegmentclr.Height + offset_point.Y,
  944. ls_cotssegmentclr.Length,
  945. 1);
  946. //图像上下反了,翻转一下,上下翻转
  947. //ls_bt.RotateFlip(RotateFlipType.Rotate180FlipX);//使用系统带的图像处理方法,进行x轴的翻转
  948. //合成图像完成,开始抠取像素---------------------为显示BSE原图而用--------------------------------------------
  949. int i_ls_length = ls_cotssegmentclr.Length;
  950. List<Color> ls_list_colors = new List<Color>();
  951. for (int m = 0; m < i_ls_length; m++)
  952. {
  953. //这里实现一下代码保护
  954. int lsjs_x = ls_cotssegmentclr.Start + m;
  955. //int lsjs_y = i_field_height - ls_cotssegmentclr.GetHeight();
  956. int lsjs_y = ls_cotssegmentclr.Height;
  957. if (lsjs_x < 0)
  958. lsjs_x = 0;
  959. if (lsjs_x >= i_field_width)
  960. lsjs_x = i_field_width - 1;
  961. if (lsjs_y < 0)
  962. lsjs_y = 0;
  963. if (lsjs_y >= i_field_height)
  964. lsjs_y = i_field_height - 1;
  965. //按理说这里应该加上个横向抠取像素颜色,这里需要再处理一下
  966. ls_list_colors.Add(ls_bt.GetPixel(lsjs_x,
  967. lsjs_y));
  968. }
  969. //---------------------------------------------存入标准库相关的信息------------------------------------------------
  970. ds.Color = ls_dp.Color;//将线的颜色对应到颗粒的颜色
  971. //------------------------------------------------------------------------------------------------------
  972. ds.List_Colors = ls_list_colors;
  973. list_dsegment.Add(ds);
  974. //ls_bt.Dispose();
  975. }
  976. ls_dp.Zoom_DisPlayMultiplier = 0.5f;
  977. ls_dp.Zoom_DisPlay = true;
  978. ls_dp.DSegments = list_dsegment; //将segment对应的设置到particle中
  979. //并对DParticle相关信息进行计算
  980. ls_dp.Rect = ls_dp.GetRectFromDSegment();
  981. ls_dp.GPath = ls_dp.GetRegionFromDSegments();
  982. ls_dp.SmallRect = ls_dp.GetSmallRectangleFromRect();
  983. //将每个颗粒添加到颗粒分布图中的列表中
  984. m_Control_DrawdistrbutionsortImage.m_list_baseobject.Add(ls_dp);
  985. }
  986. }
  987. //--------------然后开始操作分布图定义的结构,接接所有的field,组成一个完整的image的rect大小,定义
  988. }
  989. /// <summary>
  990. /// 根据type,从三种分类的分析库中提取当前分析物的颜色
  991. /// </summary>
  992. /// <param name="in_cotssampleclr"></param>
  993. /// <param name="in_stdtypeid"></param>
  994. /// <returns></returns>
  995. public Color GetColorBySTDTypeIDForBSEAndSorImage(string in_cotssampleclr, int in_stdtypeid)
  996. {
  997. Color ret_c = new Color();
  998. if (in_stdtypeid < 1000)
  999. {
  1000. OTSSysSTDMgrClass osc = new OTSSysSTDMgrClass();
  1001. //小于1000,使用系统默认分类
  1002. ret_c = osc.GetColorByEnum(in_stdtypeid);
  1003. }
  1004. else if (in_stdtypeid >= 1000)
  1005. {
  1006. //大于等于1000,并且小于10000时,使用用户标准库来分析夹杂物名称
  1007. if (!in_cotssampleclr.Contains("#"))
  1008. {
  1009. ret_c = DrawFuncation.colorHx16toRGB("#" + in_cotssampleclr);//接收必须是#000000的格式
  1010. }
  1011. else
  1012. {
  1013. ret_c = DrawFuncation.colorHx16toRGB(in_cotssampleclr);//接收必须是#000000的格式
  1014. }
  1015. }
  1016. return ret_c;
  1017. }
  1018. /// <summary>
  1019. /// 颗粒排序图中的颗粒,重新组织显示颗粒排序规则
  1020. /// </summary>
  1021. public void GetDistrbutionSortimage_ByQuery(OTSIncAReportApp.OTSSampleReportInfo.OTSSampleMeaInfo sourceGridData)
  1022. {
  1023. List<string> FLNameList = new List<string>();
  1024. //List<int> FLID = new List<int>() { -1,0, 1, 2, 4, 6, 7, 8, 9 };
  1025. List<int> FLID = new List<int>() { 0, 1, 2, 4, 6, 9, 10};
  1026. List<string> NameList = new List<string>();
  1027. int fltype = 0;
  1028. //先清除list
  1029. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution.Clear();
  1030. m_Control_DrawdistrbutionsortImage.m_old_list_sortparticledistribution.Clear();
  1031. m_Control_DrawdistrbutionsortImage.m_f_zoom_record = 1;
  1032. //------------------------------------分解结果内容部份------------------------------------
  1033. string display_type = "";
  1034. string con = "";
  1035. var list = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 4);
  1036. string sort_type = list.itemVal.ToString();
  1037. int _type = list.comboDownList.IndexOf(sort_type);
  1038. switch (_type)
  1039. {
  1040. case 0:
  1041. fltype = 0;
  1042. break;
  1043. case 1:
  1044. fltype = 1;
  1045. break;
  1046. case 2:
  1047. fltype = 2;
  1048. display_type = sourceGridData.SampleDataList.Find(s => Convert.ToInt32(s.iItemId) == 13).itemVal.ToString();
  1049. switch (display_type)
  1050. {
  1051. case "DMAX":
  1052. con = "DMAX";
  1053. break;
  1054. case "DMIN":
  1055. con = "DMIN";
  1056. break;
  1057. case "Area":
  1058. con = "Area";
  1059. break;
  1060. case "FERET":
  1061. con = "DFERET";
  1062. break;
  1063. }
  1064. break;
  1065. }
  1066. string path = resultFile.FilePath;
  1067. ParticleData particleData = new ParticleData(path);
  1068. List<Particle> particles = particleData.GetParticleListByCon("", "", "", 0);
  1069. foreach (DParticle ls_dp in m_Control_DrawdistrbutionsortImage.m_list_baseobject)
  1070. {
  1071. int dis = 0;
  1072. foreach (Particle particle in particles)
  1073. {
  1074. //找到对应的颗粒,将分类设置进去
  1075. if (ls_dp.CLRTagID == particle.ParticleId && ls_dp.CLRFieldID == particle.FieldId)
  1076. {
  1077. if (!FLNameList.Contains(particle.TypeName) && particle.TypeName != "")
  1078. {
  1079. FLNameList.Add(particle.TypeName);
  1080. }
  1081. if (fltype == 0)
  1082. {
  1083. ls_dp.ParticleFL = particle.TypeId.ToString();
  1084. }
  1085. if (fltype == 1)
  1086. {
  1087. ls_dp.ParticleFL = particle.TypeName.ToString();
  1088. }
  1089. if (fltype == 2)
  1090. {
  1091. if (con == "DMAX")
  1092. ls_dp.ParticleFL = particle.DMAX.ToString();
  1093. if (con == "DMIN")
  1094. ls_dp.ParticleFL = particle.DMIN.ToString();
  1095. if (con == "Area")
  1096. ls_dp.ParticleFL = particle.Area.ToString();
  1097. if (con == "DFERET")
  1098. ls_dp.ParticleFL = particle.FERET.ToString();
  1099. }
  1100. ls_dp.Operator = ParticleOperator.DISPLAY;
  1101. dis = 1;
  1102. break;
  1103. }
  1104. }
  1105. if (dis == 0)
  1106. {
  1107. ls_dp.Operator = ParticleOperator.NODISPLAY;
  1108. }
  1109. }
  1110. if (fltype == 0)
  1111. {
  1112. //NameList = new List<string>() { table["partcletype0"].ToString(), table["partcletype1"].ToString(), table["partcletype2"].ToString(), table["partcletype4"].ToString(), table["partcletype6"].ToString(), table["partcletype7"].ToString(), table["partcletype8"].ToString(), table["partcletype9"].ToString(), table["partcletype10"].ToString() };
  1113. NameList = new List<string>() {table["partcletype9"].ToString(), table["partcletype10"].ToString() };
  1114. }
  1115. if (fltype == 1)
  1116. {
  1117. NameList = FLNameList;
  1118. }
  1119. if (fltype == 2)
  1120. {
  1121. //获取粒级表
  1122. string flpath = m_Control_DrawdistrbutionsortImage.m_ReportApp.m_RptConfigFile.FileFolderSize + m_Control_DrawdistrbutionsortImage.m_ReportApp.m_RptConfigFile.PartSizeFile;
  1123. DataSet ds = XMLoperate.GetXml(flpath);
  1124. string sizestr = ds.Tables[0].Rows[0]["Sizes"].ToString();
  1125. List<string> sizeList = new List<string>();
  1126. for (int i = 0; i < sizestr.Split(',').Length - 1; i++)
  1127. {
  1128. if (sizestr.Split(',')[i].Length > 0)
  1129. {
  1130. double d1 = Convert.ToDouble(sizestr.Split(',')[i]);
  1131. double d2 = Convert.ToDouble(sizestr.Split(',')[i + 1]);
  1132. sizeList.Add(d1.ToString() + "~" + d2.ToString());
  1133. }
  1134. }
  1135. double d = Convert.ToDouble(sizestr.Split(',')[sizestr.Split(',').Length - 1]);
  1136. sizeList.Add(d.ToString() + "~MAX");
  1137. NameList = sizeList;
  1138. }
  1139. //为颗粒排序图,创建分栏grid
  1140. foreach (string name in NameList)
  1141. {
  1142. SortParticleDistribution sortparticledistribution = new SortParticleDistribution();
  1143. sortparticledistribution.RectF = new RectangleF(m_Control_DrawdistrbutionsortImage.ClientRectangle.X, m_Control_DrawdistrbutionsortImage.ClientRectangle.Y,
  1144. 800, m_Control_DrawdistrbutionsortImage.ClientRectangle.Height);
  1145. sortparticledistribution.ShowStr = name;//设置分类grid
  1146. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution.Add(sortparticledistribution);
  1147. }
  1148. //然后再重新将list_baseobject中的颗粒,分别添加到对应的sortgrid中
  1149. foreach (DParticle ls_dp in m_Control_DrawdistrbutionsortImage.m_list_baseobject)
  1150. {
  1151. var sort = m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution;
  1152. for (int i = 0; i < sort.Count; i++)
  1153. {
  1154. if (fltype == 0)
  1155. {
  1156. if (ls_dp.STDTypeID == FLID[i])
  1157. {
  1158. //将对应的颗粒添加到分栏grid中
  1159. DParticle sort_dp = ls_dp.Clone() as DParticle;
  1160. sort_dp.Rect = sort_dp.GetRectFromDSegment();
  1161. sort[i].List_DParticle.Add(sort_dp);
  1162. break;
  1163. }
  1164. else if (ls_dp.STDTypeID > 10000)
  1165. {
  1166. //将对应的颗粒添加到分栏grid中
  1167. DParticle sort_dp = ls_dp.Clone() as DParticle;
  1168. sort_dp.Rect = sort_dp.GetRectFromDSegment();
  1169. sort[sort.Count - 1].List_DParticle.Add(sort_dp);
  1170. break;
  1171. }
  1172. }
  1173. else if (fltype == 1)
  1174. {
  1175. if (ls_dp.TypeName == NameList[i])
  1176. {
  1177. //将对应的颗粒添加到分栏grid中
  1178. DParticle sort_dp = ls_dp.Clone() as DParticle;
  1179. sort_dp.Rect = sort_dp.GetRectFromDSegment();
  1180. sort[i].List_DParticle.Add(sort_dp);
  1181. break;
  1182. }
  1183. }
  1184. else if (fltype == 2)
  1185. {
  1186. double min = Convert.ToDouble(NameList[i].Split('~')[0]);
  1187. double max = 0;
  1188. if (NameList[i].Split('~')[1].ToLower() != "max")
  1189. { max = Convert.ToDouble(NameList[i].Split('~')[1]); }
  1190. else
  1191. {
  1192. max = 999;
  1193. }
  1194. double size = Convert.ToDouble(ls_dp.ParticleFL);
  1195. if (size <= max && size >= min)
  1196. {
  1197. //将对应的颗粒添加到分栏grid中
  1198. DParticle sort_dp = ls_dp.Clone() as DParticle;
  1199. sort_dp.Rect = sort_dp.GetRectFromDSegment();
  1200. sort[i].List_DParticle.Add(sort_dp);
  1201. break;
  1202. }
  1203. }
  1204. }
  1205. }
  1206. //循环分栏grid,对各分栏grid进行摆放
  1207. for (int i = 0; i < m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution.Count(); i++)
  1208. {
  1209. //计算y轴,的增量
  1210. float ls_height = 0;
  1211. if (i == 0)
  1212. {
  1213. ls_height = 0;
  1214. }
  1215. else
  1216. {
  1217. ls_height = m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i - 1].RectF.Y +
  1218. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i - 1].RectF.Height - 10;
  1219. }
  1220. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i].RectF = new RectangleF(
  1221. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i].RectF.X,
  1222. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i].RectF.Y + ls_height,
  1223. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i].RectF.Width,
  1224. m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution[i].GetSortGridHeight() + 50);//为每栏的高度增加了50补充,防止图像溢出
  1225. }
  1226. //然后再重新对分栏grid中的颗粒,重新进行摆放
  1227. foreach (SortParticleDistribution ls_spd in m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution)
  1228. {
  1229. ls_spd.SortDParticle(m_Control_DrawdistrbutionsortImage.FZOOMRecord);
  1230. }
  1231. //最后,将分栏grid,分别存放到old的分栏grid中
  1232. foreach (SortParticleDistribution ls_sortparticledistribution in m_Control_DrawdistrbutionsortImage.m_list_sortparticledistribution)
  1233. {
  1234. SortParticleDistribution old_sortparticledistribution = ls_sortparticledistribution.Clone() as SortParticleDistribution;
  1235. m_Control_DrawdistrbutionsortImage.m_old_list_sortparticledistribution.Add(old_sortparticledistribution);
  1236. foreach (DParticle ls_dp in old_sortparticledistribution.List_DParticle)
  1237. {
  1238. ls_dp.Rect = ls_dp.GetRectFromDSegment();
  1239. }
  1240. }
  1241. }
  1242. #endregion
  1243. }
  1244. }