OTSIncAReportFun.cs 69 KB

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