OTSIncAReportFun.cs 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617
  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.Drawing.Drawing2D;
  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. //全局对象,为了能够快速的获取到xray数据,而做为一个临时变量进行保存,使用前应该判断是否为空
  40. public List<Field> m_list_OTSField = null;
  41. NLog.Logger log;
  42. //field的数量
  43. public int m_field_count = 0;
  44. //particle的数量
  45. public int m_particle_count = 0;
  46. //加载使用的时间
  47. public string m_time_str = "";
  48. //加载使用时间计算时间段2
  49. public string m_time_str2 = "";
  50. //电镜设置对象
  51. public ServiceInterface.SemController m_cfun = null;
  52. //是否已经连接到了电镜
  53. public bool m_SEMConnectionState = false;
  54. //连接到电镜的ID号
  55. public int m_SEM_ID = 0;
  56. #endregion
  57. #region 构造函数
  58. /// <summary>
  59. /// 构造函数,接收新版分布图和排序图的构造函数
  60. /// </summary>
  61. /// <param name="in_Control_DrawDistrbutionImageAndBSE"></param>
  62. /// <param name="in_Cotsreportprojfilemgrclr"></param>
  63. public OTSIncAReportFun( ResultFile result)
  64. {
  65. m_list_OTSField = new List<Field>();
  66. resultFile = result;
  67. m_cfun =new ServiceInterface.SemController();
  68. log = NLog.LogManager.GetCurrentClassLogger();
  69. }
  70. #endregion
  71. #region 封装自定义方法
  72. public Point GetPhysicalCoordLeftBottomPoint(List<Point> allFldPos)
  73. {
  74. //the ots coordinate system is always positive on the right and up direction.So the leftbottom point would be the smallest point.
  75. //找出最小的x,y用来做偏移运算
  76. int i_offset_x = 1000000000;
  77. int i_offset_y = 1000000000;
  78. //先取出最小的x,y
  79. for (int i = 0; i < allFldPos.Count; i++)
  80. {
  81. if (i_offset_x > allFldPos[i].X)
  82. {
  83. i_offset_x = allFldPos[i].X;
  84. }
  85. if (i_offset_y > allFldPos[i].Y)
  86. {
  87. i_offset_y = allFldPos[i].Y;
  88. }
  89. }
  90. return new Point(i_offset_x, i_offset_y);
  91. }
  92. /// <summary>
  93. /// 通过传入的各field物理坐标列表,和单个field的屏幕分辨率,及单个的field的物理坐标,来获取当前field在整个image中的屏幕像素坐标偏移,并且是OTS向上为正做了Y轴相反运算
  94. /// </summary>
  95. /// <param name="allFldPos"></param>
  96. /// <param name="in_screen_width"></param>
  97. /// <param name="in_screen_height"></param>
  98. /// <param name="in_physics_width"></param>
  99. /// <param name="in_physics_height"></param>
  100. /// <returns></returns>
  101. public Point ConvertPhysicalCoordinateToScreenCoord(Point otsleftBottomPoint,double pixelSize, Point currenFldPos)//ots coordinate equals to the physical coordinate.
  102. {
  103. var OTSPoint=new Point(currenFldPos.X - otsleftBottomPoint.X, currenFldPos.Y - otsleftBottomPoint.Y);
  104. var screenPoint = new Point((int)(Convert.ToDouble(OTSPoint.X)/pixelSize), (int)(Convert.ToDouble(OTSPoint.Y)/pixelSize));
  105. return screenPoint;
  106. }
  107. /// <summary>
  108. /// 根据type,从三种分类的分析库中提取当前分析物的颜色
  109. /// </summary>
  110. /// <param name="in_cotssampleclr"></param>
  111. /// <param name="in_stdtypeid"></param>
  112. /// <returns></returns>
  113. /// <summary>
  114. /// 计算像素总画面Image大小,及进行物理坐标与分辨率坐标的换算操作 传入物理坐标,及宽高,来
  115. /// </summary>
  116. /// <param name="inPoints">传入的物理坐标数组</param>
  117. /// <param name="width">单个field宽</param>
  118. /// <param name="height">单个field高</param>
  119. /// <returns></returns>
  120. public Rectangle ConvertAndGetMaxRect(List<Point> inPoints, int in_width, int in_height)
  121. {
  122. //首先要能确定下来,单个物理坐标的宽和高--------------------------------
  123. int i_wl_width = 0;
  124. int i_wl_height = 0;
  125. RectangleF ls_r = GetPhysicalFieldWidthAndHeight(inPoints,in_width,in_height);
  126. i_wl_width = (int)ls_r.Width;
  127. i_wl_height = (int)ls_r.Height;
  128. //-----------------------------------------------------------------------------
  129. int point_x_min = 10000000;
  130. int point_x_max = -10000000;
  131. int point_y_min = 10000000;
  132. int point_y_max = -10000000;
  133. for (int i = 0; i < inPoints.Count(); i++)
  134. {
  135. Point ls_point = inPoints[i];
  136. //取出正数最大x
  137. if (ls_point.X > point_x_max)
  138. point_x_max = ls_point.X;
  139. if (ls_point.Y > point_y_max)
  140. point_y_max = ls_point.Y;
  141. if (ls_point.X < point_x_min)
  142. point_x_min = ls_point.X;
  143. if (ls_point.Y < point_y_min)
  144. point_y_min = ls_point.Y;
  145. }
  146. //然后分别用最大值+abs(最小值),就是x,和y轴的总长值
  147. point_x_max = point_x_max - point_x_min;
  148. point_y_max = point_y_max - point_y_min;
  149. //该算法有个问题,就是不能直观的得到整个范围的大小,要除以倍数再补1能补充缺少的一个field视域**********
  150. point_x_max = ((point_x_max / i_wl_width) + 1) * i_wl_width;
  151. point_y_max = ((point_y_max / i_wl_height) + 1) * i_wl_height;
  152. //将物理宽高,变换成分辨率宽高
  153. if (i_wl_width != 0) point_x_max = (point_x_max / i_wl_width) * in_width; else point_x_max = 0;
  154. if (i_wl_height != 0) point_y_max = (point_y_max / i_wl_height) * in_height; else point_y_max = 0;
  155. Rectangle ret_rectangle = new Rectangle(0, 0, 0, 0);
  156. //判断一下防止出错,只有在有数据的情况下,进行赋值才行
  157. if (inPoints.Count > 0)
  158. {
  159. ret_rectangle = new Rectangle(0, 0, point_x_max, point_y_max);
  160. }
  161. //这样返回是物理坐标的总大小,应该返回像素坐标大小才对
  162. return ret_rectangle;
  163. }
  164. /// <summary>
  165. /// 计算单个field的物理大小 传入field的list,还有测量结果管理类对象,在无法计算出单field的物理大小的情况下,到这里取再计算得出
  166. /// </summary>
  167. /// <returns></returns>
  168. public RectangleF GetPhysicalFieldWidthAndHeight(List<Point> points,int imageWidth,int imageHeight)
  169. {
  170. int width_max = -10000000;
  171. int height_max = -10000000;
  172. int width_max2 = -10000000;
  173. int height_max2 = -10000000;
  174. //先找出最大的值,
  175. for (int i = 0; i < points.Count(); i++)
  176. {
  177. if (width_max < points[i].X)
  178. width_max = points[i].X;
  179. if (height_max < points[i].Y)
  180. height_max = points[i].Y;
  181. }
  182. //再找出第二大的值
  183. for (int i = 0; i < points.Count(); i++)
  184. {
  185. if (width_max2 < points[i].X && width_max != points[i].X)
  186. width_max2 = points[i].X;
  187. if (height_max2 < points[i].Y && height_max != points[i].Y)
  188. height_max2 = points[i].Y;
  189. }
  190. //需要针对第二大的值,获取时进行判断,感觉这里应该如果并未找到第二大的值的情况下,赋于0值,便于以后进行计算
  191. if (width_max2 == -10000000)
  192. width_max2 = 0;
  193. if (height_max2 == -10000000)
  194. height_max2 = 0;
  195. RectangleF ret_rect = new RectangleF(0, 0, width_max - width_max2, height_max - height_max2);
  196. //如果最后计算出的宽高有0则重新到测量数据中获取---------------------------------------
  197. if (ret_rect.Width == 0 || ret_rect.Height == 0)
  198. {
  199. //到参数中去取单个宽
  200. double d_scanFieldSize_width = Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  201. //然后再用单个宽去计算出高是多少
  202. double d_scanFieldSize_height = 0;
  203. if (d_scanFieldSize_width != 0)
  204. d_scanFieldSize_height = (d_scanFieldSize_width / Convert.ToDouble(imageWidth)) * imageHeight;
  205. ret_rect.Width = (int)d_scanFieldSize_width;
  206. ret_rect.Height = (int)d_scanFieldSize_height;
  207. }
  208. ///-----------because all the fields 's height/width=0.75 so here we make an enforce. gsp add at 2019/10/31
  209. ///sometimes the gbfields are not conform to this for the cuting and merging operation.
  210. //if (ret_rect.Height / ret_rect.Width != 0.75f)
  211. //{
  212. // ret_rect = new Rectangle(ret_rect.X, ret_rect.Y, ret_rect.Width, (int)(ret_rect.Width * 0.75f));
  213. //}
  214. return ret_rect;
  215. }
  216. #endregion
  217. #region 电镜操作相关方法
  218. /// <summary>
  219. /// 连接电镜,分布图使用
  220. /// </summary>
  221. public void ConnectToSEM()
  222. {
  223. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM");
  224. if (!m_SEMConnectionState)
  225. {
  226. //和电镜建立通讯连接
  227. m_SEMConnectionState = m_cfun.Connect();
  228. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + "Connect to SEM" + ":--" + m_SEMConnectionState + "---");
  229. }
  230. else
  231. {
  232. log.Trace("(Connection_ForDrawDistrbutionImageAndBSE)" + ":allready connected, state:" + m_SEMConnectionState);
  233. //断开电镜连接
  234. }
  235. }
  236. public void DisConnectSEM()
  237. {
  238. m_SEMConnectionState = false;
  239. m_cfun.DisConnect();
  240. }
  241. /// <summary>
  242. /// 移动电镜到指定的X,Y坐标上,R坐标使用原先的值进行移动
  243. /// </summary>
  244. /// <param name="PositionX"></param>
  245. /// <param name="PositionY"></param>
  246. public void MoveSemToPointXY(double in_PositionX, double in_PositionY)
  247. {
  248. log.Trace("Begin MoveSemToPointXY:(" +in_PositionX.ToString()+","+in_PositionY.ToString()+")");
  249. //首先获取电镜当前的位置,并记录原R值
  250. double ls_PositionX = 0;
  251. double ls_PositionY = 0;
  252. double ls_PositionR = 0;
  253. if (m_SEMConnectionState)
  254. {
  255. m_cfun.GetSemPositionXY(ref ls_PositionX, ref ls_PositionY, ref ls_PositionR);
  256. }
  257. else
  258. {
  259. log.Error("Failed to GetSemPositionXY");
  260. return;
  261. }
  262. if (m_SEMConnectionState)
  263. {
  264. m_cfun.MoveSEMToPoint(new Point((int)in_PositionX, (int)in_PositionY), ls_PositionR);
  265. }
  266. }
  267. #endregion
  268. #region //--------------------------------------颗粒分布图相关部份---------------------------------------------------------------------
  269. /// <summary>
  270. /// 传入颗粒的tagid和fieldid,来获取该颗粒下对应的xray数据
  271. /// </summary>
  272. /// <param name="in_clr_tagid"></param>
  273. /// <param name="in_clr_fieldid"></param>
  274. /// <param name="Search_xray"></param>
  275. /// <param name="Analysis_xray"></param>
  276. 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)
  277. {
  278. Search_xray = new uint[2000];
  279. Analysis_xray = new uint[2000];
  280. xray_id = 0;
  281. list_celementchemistryclr = new List<Element>();
  282. //防止为空校验判断
  283. if (m_list_OTSField == null)
  284. return;
  285. Particle particle = m_list_OTSField.Find(x => x.FieldID == in_clr_fieldid).ParticleList.Find(x => x.ParticleId == in_clr_tagid);
  286. var tmpPart = new ParticleData(resultFile.FilePath).GetParticleXrayDataByFidAndPid(Convert.ToString(particle.FieldId), Convert.ToString(particle.XrayId));
  287. particle.XRayData = tmpPart.XRayData;
  288. if (particle.XrayId > -1)
  289. {
  290. for (int i = 0; i < 2000; i++)
  291. {
  292. Analysis_xray[i] = BitConverter.ToUInt32(particle.XRayData, i * 4);
  293. }
  294. Search_xray = Analysis_xray;
  295. xray_id = particle.XrayId;
  296. list_celementchemistryclr = particle.ElementList;
  297. }
  298. }
  299. /// <summary>
  300. /// 传入所有的物理field坐标点,和单个物理field的宽高,返回所有field的左上角位置,和整个field组成的rect大小
  301. /// </summary>
  302. /// <param name="in_list_point"></param>
  303. /// <param name="in_width"></param>
  304. /// <param name="in_height"></param>
  305. /// <returns></returns>
  306. public Rectangle GetWlRectTopLeftAndRect(List<Point> in_list_point, int in_width, int in_height)
  307. {
  308. //分别获取整个rect的xy最小值和最大值
  309. int i_rect_x_min = 100000000;
  310. int i_rect_y_min = 100000000;
  311. int i_rect_x_max = -100000000;
  312. int i_rect_y_max = -100000000;
  313. for (int i = 0; i < in_list_point.Count; i++)
  314. {
  315. if (i_rect_x_min > in_list_point[i].X)
  316. i_rect_x_min = in_list_point[i].X;
  317. if (i_rect_y_min > in_list_point[i].Y)
  318. i_rect_y_min = in_list_point[i].Y;
  319. if (i_rect_x_max < in_list_point[i].X)
  320. i_rect_x_max = in_list_point[i].X;
  321. if (i_rect_y_max < in_list_point[i].Y)
  322. i_rect_y_max = in_list_point[i].Y;
  323. }
  324. Rectangle ret_rect = new Rectangle(i_rect_x_min, i_rect_y_min,
  325. i_rect_x_max - i_rect_x_min, i_rect_y_max - i_rect_y_min);
  326. return ret_rect;
  327. }
  328. /// <summary>
  329. /// 根据Field的ID,来获取Field列表中对应FIeld的OTS 坐标
  330. /// </summary>
  331. /// <param name="in_fieldid"></param>
  332. /// <returns></returns>
  333. public Point GetOTSPointByFieldID(List<DisplayField> in_list_dfield, int in_fieldid)
  334. {
  335. Point ret_point = new Point(0, 0);
  336. for (int i = 0; i < in_list_dfield.Count; i++)
  337. {
  338. //这里TagID先代表的是底层返回的ID
  339. if (in_list_dfield[i].FieldID == in_fieldid.ToString())
  340. {
  341. ret_point = new Point(Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.X), Convert.ToInt32(in_list_dfield[i].OTSCoordinatePos.Y));
  342. }
  343. }
  344. return ret_point;
  345. }
  346. /// <summary>
  347. /// 将OTS坐标转换为Sem 坐标
  348. /// </summary>
  349. /// <param name="POTSCoord"></param>
  350. /// <returns></returns>
  351. public Point ChangeOTSToSemCoord(Point POTSCoord)
  352. {
  353. //first if m_semstagedata is null to get stage inforation
  354. Convert.ToDouble(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["scanFieldSize"]);
  355. //after obtaining stage info,calc stage point data
  356. Point ret_SEM_point = new Point();
  357. // get center point, um
  358. long xStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["start"]);
  359. long xEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["XAxis"])["end"]);
  360. long xCenter = (xStart + xEnd) / 2;
  361. long yStart = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["start"]);
  362. long yEnd = Convert.ToInt64(((Dictionary<string, object>)((Dictionary<string, object>)((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["Members"])["YAxis"])["end"]);
  363. long yCenter = (yStart + yEnd) / 2;
  364. // delte = SEM - OTSa
  365. long deltex = xCenter - 0;
  366. long deltey = yCenter - 0;
  367. int xdir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["xAxisDir"]);
  368. int ydir = Convert.ToInt32(((Dictionary<string, object>)resultFile.ResultInfo["SEMStageData"])["yAxisDir"]);
  369. if (xdir == (int)OTS_X_AXIS_DIRECTION.LEFT_TOWARD)
  370. {
  371. ret_SEM_point.X = -1 * (POTSCoord.X - Convert.ToInt32(deltex));
  372. }
  373. else if (xdir == (int)OTS_X_AXIS_DIRECTION.RIGHT_TOWARD)
  374. {
  375. ret_SEM_point.X = POTSCoord.X + Convert.ToInt32(deltex);
  376. }
  377. if (ydir == (int)OTS_Y_AXIS_DIRECTION.UP_TOWARD)
  378. {
  379. ret_SEM_point.Y = POTSCoord.Y + Convert.ToInt32(deltey);
  380. }
  381. else if (ydir == (int)OTS_Y_AXIS_DIRECTION.DOWN_TOWARD)
  382. {
  383. ret_SEM_point.Y = -1 * (POTSCoord.Y - Convert.ToInt32(deltey));
  384. }
  385. return ret_SEM_point;
  386. }
  387. #endregion
  388. /// <summary>
  389. /// 判断该点是否在多边形的范围内
  390. /// </summary>
  391. /// <param name="inPoints"></param>
  392. /// <param name="WhetherPoint"></param>
  393. /// <returns></returns>
  394. public bool WhetherInRange(DisplayParticle Part,/*PointF[] inPoints,*/ Point WhetherPoint)
  395. {
  396. var rect = Part.Rect;
  397. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  398. {
  399. var itm = (BaseObject)Part;
  400. itm.GPath = Part.GetRegionFromDSegments();
  401. PointF[] inPoints = itm.GPath.PathPoints;
  402. bool b_inrange = false;
  403. GraphicsPath myGraphicsPath = new GraphicsPath();
  404. Region myRegion = new Region();
  405. myGraphicsPath.Reset();
  406. myGraphicsPath.AddPolygon(inPoints);
  407. myRegion.MakeEmpty();
  408. myRegion.Union(myGraphicsPath);
  409. //返回判断点是否在多边形里
  410. b_inrange = myRegion.IsVisible(WhetherPoint);
  411. return b_inrange;
  412. }
  413. else
  414. {
  415. return false;
  416. }
  417. }
  418. public bool WhetherInRange(RectangleF rec,PointF[] inPoints, Point WhetherPoint)
  419. {
  420. var rect = rec;
  421. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  422. {
  423. //var itm = (BaseObject)Part;
  424. //PointF[] inPoints = itm.GPath.PathPoints;
  425. bool b_inrange = false;
  426. GraphicsPath myGraphicsPath = new GraphicsPath();
  427. Region myRegion = new Region();
  428. myGraphicsPath.Reset();
  429. myGraphicsPath.AddPolygon(inPoints);
  430. myRegion.MakeEmpty();
  431. myRegion.Union(myGraphicsPath);
  432. //返回判断点是否在多边形里
  433. b_inrange = myRegion.IsVisible(WhetherPoint);
  434. return b_inrange;
  435. }
  436. else
  437. {
  438. return false;
  439. }
  440. }
  441. /// <summary>
  442. /// 判断该点是否在多边形的范围内的float版本重载
  443. /// </summary>
  444. /// <param name="inPoints"></param>
  445. /// <param name="WhetherPoint"></param>
  446. /// <returns></returns>
  447. public bool WhetherInRange(DisplayParticle Part,/* PointF[] inPoints, */PointF WhetherPoint)
  448. {
  449. var rect = Part.Rect;
  450. if ((rect.Left < WhetherPoint.X && WhetherPoint.X < rect.Right) && (rect.Top < WhetherPoint.Y && WhetherPoint.Y < rect.Bottom))
  451. {
  452. var itm = (BaseObject)Part;
  453. PointF[] inPoints = itm.GPath.PathPoints;
  454. bool b_inrange = false;
  455. GraphicsPath myGraphicsPath = new GraphicsPath();
  456. Region myRegion = new Region();
  457. myGraphicsPath.Reset();
  458. myGraphicsPath.AddPolygon(inPoints);
  459. myRegion.MakeEmpty();
  460. myRegion.Union(myGraphicsPath);
  461. //返回判断点是否在多边形里
  462. b_inrange = myRegion.IsVisible(WhetherPoint);
  463. return b_inrange;
  464. }
  465. else
  466. {
  467. return false;
  468. }
  469. }
  470. #region //--------------------------------------颗粒排序图相关部份---------------------------------------------------------------------
  471. /// <summary>
  472. /// 根据传入的fieldid和tagid返回该颗粒的OTS坐标
  473. /// </summary>
  474. /// <param name="in_fieldid"></param>
  475. /// <param name="in_tagid"></param>
  476. /// <returns></returns>
  477. public Point GetOTSPointFromOld_list_sortparticledistribution(int in_fieldid, int in_tagid, Control_DrawDistrbutionSortImage in_control_drawdistrbutionsortimage)
  478. {
  479. Point ret_point = new Point(0, 0);
  480. if (m_list_OTSField != null)
  481. {
  482. Field field = m_list_OTSField.Find(x => x.FieldID == in_fieldid);
  483. ret_point = new Point() { X = field.FieldPosX, Y = field.FieldPosY };
  484. }
  485. return ret_point;
  486. }
  487. #endregion
  488. }
  489. }