DrawCrl.cs 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Drawing;
  5. using System.Data;
  6. using System.Text;
  7. using System.Linq;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. using DevExpress.XtraEditors;
  11. using System.IO;
  12. using System.Reflection;
  13. using DevExpress.XtraEditors.Controls;
  14. namespace Uninpho.Railway.Waveform
  15. {
  16. public partial class DrawCrl : DevExpress.XtraEditors.XtraUserControl
  17. {
  18. #region 变量
  19. public static int boardkey = 0;//键盘key
  20. bool ishover = false;//鼠标是否在控件内
  21. WaveInput waveinput = new WaveInput();
  22. Bitmap bmp;
  23. Graphics g;
  24. Bitmap bmpsc;
  25. Graphics gg;
  26. List<CheckedListBoxItem> labelTitle = new List<CheckedListBoxItem>();
  27. public Dictionary<string, RightLabelControl> labelList = new Dictionary<string, RightLabelControl>();//label集合
  28. MathTools MT;//计算工具
  29. int pianyi = 0;//对比的图的偏移量
  30. int step = 25;//纵轴平移步长
  31. int stepX = 10;//横轴方向显示步长
  32. double blc = 0.5;//波形图显示高与实际bitmap的比值
  33. double blcx = 0.5;//波形图显示高与实际bitmap的比值
  34. int maxW = 0;//滚动条最大宽度,按照输入参数中坐标的数量确定
  35. int nowX = 0;//滚动条当前位置的x值
  36. #endregion
  37. public DrawCrl()
  38. {
  39. InitializeComponent();
  40. }
  41. #region !!!初始化信息 !!!
  42. /// <summary>
  43. /// 初始化加载项
  44. /// </summary>
  45. public void YXCLoadEvnet(WaveInput waveinput_,bool showJGT)
  46. {
  47. waveinput = waveinput_;
  48. if (waveinput_.InputType.Split('_')[0] == "jh")
  49. {
  50. TitlleCrl.Text = " 几 何 波 形";
  51. }
  52. else if (waveinput_.InputType.Split('_')[0] == "lgl")
  53. {
  54. TitlleCrl.Text = " 轮 轨 力 波 形";
  55. }
  56. else
  57. {
  58. TitlleCrl.Text = "";
  59. }
  60. TitlleCrl.BackColor = Color.White;
  61. MT = new MathTools(waveinput.InputType);
  62. //1.加载结构图(判断是否有,有则加载)
  63. YXCjiegoutuLoad(showJGT);
  64. //2.加载需要绘制的数据
  65. YXCDrawDataLoad();
  66. //3.加载相关组件
  67. YXCComponentsLoad();
  68. //4.绘制
  69. DrawMainBox_PaintFun();
  70. }
  71. /// <summary>
  72. /// 初始化加载结构图
  73. /// </summary>
  74. private void YXCjiegoutuLoad(bool showJGT)
  75. {
  76. if (showJGT && File.Exists(waveinput.jgtPath))
  77. {
  78. JGTpictureBox.Image = Image.FromFile(waveinput.jgtPath);
  79. //JGTpictureBox.ImageLocation
  80. }
  81. else
  82. {
  83. MytableLayoutPanel.RowStyles[0].Height = 0;
  84. }
  85. }
  86. /// <summary>
  87. /// 初始化加载绘制数据
  88. /// </summary>
  89. private void YXCDrawDataLoad()
  90. {
  91. //1.修正pictureBox宽度
  92. maxW = waveinput.waveData.ElementAt(0).Value.CoorList.Count;
  93. int sho = maxW / 10;
  94. if (sho >= 10)
  95. {
  96. maxW = (sho * 10 + 10) / 10;
  97. }
  98. //2.初始化画布等参数
  99. bmp = new Bitmap(2000, 2000);//初始化bitmap宽高
  100. bmpsc = new Bitmap(2000, 90);
  101. blc = Convert.ToDouble(DrawMainBox.Height) / Convert.ToDouble(bmp.Height);//采集bmp的拉伸比例,用来修正右侧label位置,可以理解为label控件坐标系统和波形图坐标系统转换的一个参数
  102. blcx = Convert.ToDouble(DrawMainBox.Width) / Convert.ToDouble(bmp.Width);//采集bmp的拉伸比例,用来修正右侧label位置,可以理解为label控件坐标系统和波形图坐标系统转换的一个参数
  103. //DrawMainBox.Location = new Point(0, 0);
  104. g = Graphics.FromImage(bmp);
  105. gg = Graphics.FromImage(bmpsc);
  106. DrawFunClass.Trans(g, 0, bmp.Height);
  107. DrawFunClass.Trans(gg, 0, bmpsc.Height);
  108. }
  109. /// <summary>
  110. /// 初始化组件
  111. /// </summary>
  112. private void YXCComponentsLoad()
  113. {
  114. //图片互操作激活
  115. JGTpictureBox.MouseWheel += pictureBox1_MouseWheel;
  116. DrawMainBox.MouseWheel += DrawMainBox_MouseWheel;
  117. //初始化checkedcombobox
  118. for (int i = 0; i < waveinput.waveData.Count; i++)
  119. {
  120. iniSetClass.updataPZflash1(waveinput.waveData.ElementAt(i).Value);//只要选择框出现的字段都在配置文件中添加一次
  121. BXCheckedComboBox.Properties.Items.Add(new CheckedListBoxItem()
  122. {
  123. CheckState = waveinput.waveData.ElementAt(i).Value.Visible == true ? CheckState.Checked : CheckState.Unchecked,
  124. Description = waveinput.waveData.ElementAt(i).Value.ListName,
  125. Value = waveinput.waveData.ElementAt(i).Value.ListId,
  126. });
  127. }
  128. initLabelFun();//初始化波形图右侧的label控件
  129. checkedDataWithCCB();
  130. showLabelFun();
  131. }
  132. #endregion
  133. #region 事件
  134. #region 绘制
  135. List<float> xarr = new List<float>();
  136. /// <summary>
  137. /// 画图
  138. /// </summary>
  139. public void DrawMainBox_PaintFun()
  140. {
  141. string temp = string.Empty;
  142. blc = Convert.ToDouble(DrawMainBox.Height) / Convert.ToDouble(bmp.Height);//采集bmp的拉伸比例,用来修正右侧label位置,可以理解为label控件坐标系统和波形图坐标系统转换的一个参数
  143. blcx = Convert.ToDouble(DrawMainBox.Width) / Convert.ToDouble(bmp.Width);//采集bmp的拉伸比例,用来修正右侧label位置,可以理解为label控件坐标系统和波形图坐标系统转换的一个参数
  144. g.Clear(Color.White);
  145. for (int i = 0; i < labelTitle.Count; i++)
  146. {
  147. CoorListClass c = waveinput.waveData[(string)labelTitle[i].Value];
  148. if (c.Visible == false)
  149. {
  150. continue;
  151. }
  152. int offset = MT.PYLJZ(c.Offset, c.AxisY, bmp.Height, step);
  153. if (c.CoorListOld != null)
  154. {
  155. MT.MathLoad(c.CoorListOld, maxW);//为了提高渲染效率,把计算范围的过程提出来了
  156. PointF[] points1 = MT.getDrawPointsOld(c.CoorListOld, bmp.Width, (int)(300 / c.Scale), nowX, offset, pianyi);
  157. DrawFunClass.DrawLinesFun(g, points1, Color.Black, c.Width);
  158. }
  159. MT.MathLoad(c.CoorList, maxW);//为了提高渲染效率,把计算范围的过程提出来了
  160. PointF[] points = MT.getDrawPoints(c.CoorList, bmp.Width, (int)(300 / c.Scale), nowX, offset, ref temp);
  161. DrawFunClass.DrawLinesFun(g, points, Color.FromArgb(c.RGBA[3], c.RGBA[0], c.RGBA[1], c.RGBA[2]), c.Width);
  162. if (waveinput.InputType == "qsfx_all")
  163. {
  164. if (xarr.Count == 0)
  165. {
  166. for (int j = 0; j < points.Length; j++)
  167. {
  168. xarr.Add(points[j].X);
  169. }
  170. }
  171. }
  172. //************************
  173. //画横坐标轴
  174. Pen p = new Pen(Color.Black, 2);
  175. p.DashStyle = System.Drawing.Drawing2D.DashStyle.Custom;
  176. p.DashPattern = new float[] { stepX, stepX };
  177. g.DrawLine(p, new PointF(0 - nowX * 2, offset), new PointF(bmp.Width, offset));
  178. labelList[c.ListId].changeLabelValue(temp);
  179. }
  180. PaintZZ(MT.xAxis, MT.xAxisF);//画纵坐标轴
  181. ScalePanel_PaintFun();
  182. DrawMainBox.Image = bmp;
  183. }
  184. /// <summary>
  185. /// 画比例尺图
  186. /// </summary>
  187. public void ScalePanel_PaintFun()
  188. {
  189. gg.Clear(Color.White);
  190. DrawFunClass.DrawScaleLine(gg, new PointF(0, bmpsc.Height / 8), new PointF(bmpsc.Width, bmpsc.Height / 8), Color.Red, bmpsc.Height / 4);
  191. if (waveinput.InputType == "qsfx_all")
  192. {
  193. for (int i = 0; i < xarr.Count; i++)
  194. {
  195. PointF p1 = new PointF(xarr[i], 0);
  196. PointF p2 = new PointF(xarr[i], bmpsc.Height / 2);
  197. DrawFunClass.DrawScaleLine(gg, p1, p2, Color.Red, 10);
  198. DrawFunClass.DrawScaleString(gg, p2, Color.Red, 30, waveinput.waveData.ElementAt(0).Value.qsfxXstring[i], 125);
  199. }
  200. }
  201. else
  202. {
  203. for (int i = 0; i < MT.xAxis.Count; i++)
  204. {
  205. PointF p1 = new PointF(MT.xAxis[i], 0);
  206. PointF p2 = new PointF(MT.xAxis[i], bmpsc.Height / 2);
  207. DrawFunClass.DrawScaleLine(gg, p1, p2, Color.Red, 10);
  208. DrawFunClass.DrawScaleString(gg, p2, Color.Red, 30, MT.AxisValue[i],25);
  209. }
  210. for (int i = 0; i < MT.xAxisF.Count; i++)
  211. {
  212. PointF p1 = new PointF(MT.xAxisF[i], 0);
  213. PointF p2 = new PointF(MT.xAxisF[i], bmpsc.Height / 2);
  214. DrawFunClass.DrawScaleLine(gg, p1, p2, Color.Red, 5);
  215. }
  216. }
  217. ScalePanel.Image = bmpsc;
  218. }
  219. /// <summary>
  220. /// 画纵轴
  221. /// </summary>
  222. private void PaintZZ(List<float> xAxis, List<float> xAxisF)
  223. {
  224. for (int j = 0; j < xAxis.Count; j++)
  225. {
  226. float x = xAxis[j];
  227. Pen ps = new Pen(Color.Black, 1);
  228. g.DrawLine(ps, new PointF(x, 0), new PointF(x, bmp.Height));
  229. for (int i = 0; i < bmp.Height; i = i + step)
  230. {
  231. g.DrawLine(ps, new PointF(x - 5, i), new PointF(x + 5, i));
  232. }
  233. }
  234. for (int j = 0; j < xAxisF.Count; j++)
  235. {
  236. float x = xAxisF[j];
  237. Pen ps = new Pen(Color.Black, 1);
  238. //g.DrawLine(ps, new PointF(x, 0), new PointF(x, bmp.Height));
  239. for (int i = 0; i < bmp.Height; i = i + step)
  240. {
  241. g.DrawLine(ps, new PointF(x - 5, i), new PointF(x + 5, i));
  242. }
  243. }
  244. }
  245. #endregion
  246. /// <summary>
  247. /// 重选通道、重新绘制
  248. /// </summary>
  249. /// <param name="sender"></param>
  250. /// <param name="e"></param>
  251. private void BXCheckedComboBox_Closed(object sender, ClosedEventArgs e)
  252. {
  253. checkedDataWithCCB();
  254. showLabelFun();
  255. DrawMainBox_PaintFun();
  256. }
  257. /// <summary>
  258. /// 使用Resize方法修正label坐标
  259. /// </summary>
  260. private void LabelPanel_Resize(object sender, EventArgs e)
  261. {
  262. if (bmp != null)
  263. {
  264. DrawMainBox_PaintFun();
  265. }
  266. correctLabelLocation();
  267. }
  268. #region 键盘鼠标交互
  269. private void DrawMainBox_MouseEnter(object sender, EventArgs e)
  270. {
  271. ishover = true;
  272. }
  273. private void DrawMainBox_MouseLeave(object sender, EventArgs e)
  274. {
  275. ishover = false;
  276. }
  277. private void DrawMainBox_MouseWheel(object sender, MouseEventArgs e)
  278. {
  279. if (ishover)
  280. {
  281. if (e.Delta > 0)
  282. {
  283. if (boardkey == 18)
  284. {
  285. //历史数据对比 //仅限波形分析使用 //历史波形向右移动 alt
  286. pianyi = pianyi + 5;
  287. }
  288. else if (boardkey == 17)
  289. {
  290. //缩放 放大 ctrl
  291. }
  292. else
  293. {
  294. //平移 向右
  295. nowX = nowX < 0 ? 0 : nowX - 1;
  296. BitMapHScroll.Value = nowX;
  297. }
  298. }
  299. else
  300. {
  301. if (boardkey == 18)
  302. {
  303. //历史数据对比 //仅限波形分析使用 //还原
  304. pianyi = pianyi - 5;
  305. }
  306. else if (boardkey == 17)
  307. {
  308. //缩放 缩小
  309. }
  310. else
  311. {
  312. //平移 向左
  313. nowX = nowX > BitMapHScroll.Maximum ? BitMapHScroll.Maximum : nowX + 1;
  314. BitMapHScroll.Value = nowX;
  315. }
  316. }
  317. DrawMainBox_PaintFun();
  318. }
  319. }
  320. #endregion
  321. #endregion
  322. #region Tools
  323. public void updataWaveInput(CoorListClass newlist)
  324. {
  325. waveinput.waveData[newlist.ListId] = newlist;
  326. iniSetClass.updataPZflash(newlist);
  327. iniSetClass.savePZFun();
  328. DrawMainBox_PaintFun();
  329. }
  330. #region 鼠标点击上下移动波形图
  331. int ay;
  332. int y;
  333. PanelControl rc;
  334. private void panel1_MouseDown(object sender, MouseEventArgs e)
  335. {
  336. rc = (PanelControl)sender;
  337. ay = e.Y;
  338. //y = DeepCopyByReflect<int>(labelList[rc.Name].Location.Y);
  339. y = labelList[rc.Name].Location.Y;
  340. }
  341. private void panel1_MouseMove(object sender, MouseEventArgs e)
  342. {
  343. if (e.Button == MouseButtons.Left)
  344. {
  345. int yy = labelList[rc.Name].Location.Y;
  346. //int offset = (int)((e.Y - ay) / (step * blc)) * (int)(step * blc);
  347. int offset = (int)Math.Round((int)((e.Y - ay) / (step * blc)) * (step * blc), 0);
  348. labelList[rc.Name].Location = new Point(5, yy + offset);
  349. //DataBus.coorslist[DataBus.dictindex][rc.Name].Offset += (double)offset / (double)LabelPanel.Height;
  350. //DrawMainBox_PaintFun();
  351. }
  352. }
  353. private void panel1_MouseUp(object sender, MouseEventArgs e)
  354. {
  355. if (e.Button == MouseButtons.Left)
  356. {
  357. waveinput.waveData[rc.Name].Offset += (double)(labelList[rc.Name].Location.Y - y) / (double)LabelPanel.Height;
  358. DrawMainBox_PaintFun();
  359. }
  360. }
  361. #endregion
  362. #region 初始化右侧可移动的label标签
  363. /// <summary>
  364. /// 新建一个RightLabelControl
  365. /// </summary>
  366. private void createLabelCtrl(Point location, CoorListClass coor)
  367. {
  368. RightLabelControl rlc = new RightLabelControl(coor, this);
  369. rlc.Name = coor.ListId + "_RLC";
  370. rlc.Parent = LabelPanel;
  371. rlc.Visible = false;
  372. rlc.move_Panel.Name = coor.ListId;
  373. rlc.move_Panel.MouseDown += panel1_MouseDown;
  374. rlc.move_Panel.MouseMove += panel1_MouseMove;
  375. rlc.move_Panel.MouseUp += panel1_MouseUp;
  376. labelList.Add(coor.ListId, rlc);
  377. }
  378. /// <summary>
  379. /// 初始化波形图右侧的label控件
  380. /// </summary>
  381. private void initLabelFun()
  382. {
  383. for (int i = 0; i < waveinput.waveData.Count; i++)
  384. {
  385. createLabelCtrl(new Point(0, 0), waveinput.waveData.ElementAt(i).Value);
  386. }
  387. }
  388. /// <summary>
  389. /// 选择勾选的通道进行显示
  390. /// </summary>
  391. private void checkedDataWithCCB()
  392. {
  393. labelTitle.Clear();
  394. labelTitle = BXCheckedComboBox.Properties.Items.Where(c => { return c.CheckState == CheckState.Checked; }).ToList();
  395. double rows = 1.0 / (labelTitle.Count + 1.0);
  396. foreach (var item in waveinput.waveData)
  397. {
  398. item.Value.Visible = false;
  399. }
  400. for (int i = 0; i < labelTitle.Count; i++)
  401. {
  402. waveinput.waveData[(string)labelTitle[i].Value].Visible = true;
  403. waveinput.waveData[(string)labelTitle[i].Value].AxisY = rows * (i + 1);
  404. iniSetClass.updataPZflash(waveinput.waveData[(string)labelTitle[i].Value]);
  405. }
  406. iniSetClass.savePZFun();
  407. }
  408. /// <summary>
  409. /// 控制波形图右侧的label控件显隐
  410. /// </summary>
  411. private void showLabelFun()
  412. {
  413. for (int i = 0; i < waveinput.waveData.Count; i++)
  414. {
  415. CoorListClass c = waveinput.waveData.ElementAt(i).Value;
  416. labelList[c.ListId].Visible = c.Visible;
  417. }
  418. correctLabelLocation();
  419. }
  420. /// <summary>
  421. /// 修正label坐标
  422. /// </summary>
  423. private void correctLabelLocation()
  424. {
  425. for (int i = 0; i < labelTitle.Count; i++)
  426. {
  427. CoorListClass c = waveinput.waveData[(string)labelTitle[i].Value];
  428. //int offset = (int)(c.AxisY * DrawMainBox.Height);
  429. int offset = (int)((c.Offset + c.AxisY) * DrawMainBox.Height);
  430. labelList[c.ListId].Location = new Point(5, offset - labelList[c.ListId].Height);
  431. }
  432. }
  433. #endregion
  434. /// <summary>
  435. /// Scroll左右滑动波形图
  436. /// </summary>
  437. private void BitMapHScroll_Scroll(object sender, ScrollEventArgs e)
  438. {
  439. //DrawMainBox.Left = -BitMapHScroll.Value;
  440. nowX = (int)BitMapHScroll.Value;
  441. DrawMainBox_PaintFun();
  442. }
  443. /// <summary>
  444. /// 深拷贝
  445. /// </summary>
  446. /// <typeparam name="T"></typeparam>
  447. /// <param name="obj"></param>
  448. /// <returns></returns>
  449. public static T DeepCopyByReflect<T>(T obj)
  450. {
  451. //如果是字符串或值类型则直接返回
  452. if (obj is string || obj.GetType().IsValueType) return obj;
  453. object retval = Activator.CreateInstance(obj.GetType());
  454. FieldInfo[] fields = obj.GetType().GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
  455. foreach (FieldInfo field in fields)
  456. {
  457. try { field.SetValue(retval, DeepCopyByReflect(field.GetValue(obj))); }
  458. catch { }
  459. }
  460. return (T)retval;
  461. }
  462. #endregion
  463. #region 测试用的,结构图移动
  464. private void pictureBox1_MouseClick(object sender, MouseEventArgs e)
  465. {
  466. JGTpictureBox.Focus();
  467. if (isMove)
  468. {
  469. int x, y;
  470. int moveX, moveY;
  471. moveX = Cursor.Position.X - mouseDownPoint.X;
  472. moveY = Cursor.Position.Y - mouseDownPoint.Y;
  473. x = JGTpictureBox.Location.X + moveX;
  474. y = JGTpictureBox.Location.Y + moveY;
  475. JGTpictureBox.Location = new Point(x, y);
  476. mouseDownPoint.X = Cursor.Position.X;
  477. mouseDownPoint.Y = Cursor.Position.Y;
  478. }
  479. }
  480. Point mouseDownPoint = new Point();
  481. bool isMove;
  482. private void pictureBox1_MouseUp(object sender, MouseEventArgs e)
  483. {
  484. if (e.Button == MouseButtons.Left)
  485. {
  486. isMove = false;
  487. }
  488. }
  489. private void pictureBox1_MouseDown(object sender, MouseEventArgs e)
  490. {
  491. if (e.Button == MouseButtons.Left)
  492. {
  493. mouseDownPoint.X = Cursor.Position.X;
  494. mouseDownPoint.Y = Cursor.Position.Y;
  495. isMove = true;
  496. JGTpictureBox.Focus();
  497. }
  498. }
  499. int zoomStep = 20;
  500. private void pictureBox1_MouseWheel(object sender, MouseEventArgs e)
  501. {
  502. int x = e.Location.X;
  503. int y = e.Location.Y;
  504. int ow = JGTpictureBox.Width;
  505. int oh = JGTpictureBox.Height;
  506. int vx, vy;
  507. if (e.Delta > 0) //放大
  508. {
  509. //1、
  510. JGTpictureBox.Width += zoomStep + 10;
  511. JGTpictureBox.Height += zoomStep + 10;
  512. //2、
  513. PropertyInfo pInfo = JGTpictureBox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
  514. Rectangle rect = (Rectangle)pInfo.GetValue(JGTpictureBox);//()里可以含两个参数,index[]为null
  515. //3、
  516. JGTpictureBox.Width = rect.Width;
  517. JGTpictureBox.Height = rect.Height;
  518. }
  519. if (e.Delta < 0)//缩小
  520. {
  521. //防止缩小成负
  522. if (JGTpictureBox.Width < zoomStep)
  523. {
  524. return;
  525. }
  526. JGTpictureBox.Width -= zoomStep;
  527. JGTpictureBox.Height -= zoomStep;
  528. PropertyInfo pInfo = JGTpictureBox.GetType().GetProperty("ImageRectangle", BindingFlags.Instance | BindingFlags.NonPublic);
  529. Rectangle rect = (Rectangle)pInfo.GetValue(JGTpictureBox);
  530. JGTpictureBox.Width = rect.Width;
  531. JGTpictureBox.Height = rect.Height;
  532. }
  533. //4、
  534. vx = (int)((double)x * (ow - JGTpictureBox.Width) / ow);
  535. vy = (int)((double)y * (oh - JGTpictureBox.Height) / oh);
  536. JGTpictureBox.Location = new Point(JGTpictureBox.Location.X + vx, JGTpictureBox.Location.Y + vy);
  537. }
  538. #endregion
  539. }
  540. }