MathTools.cs 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace Uninpho.Railway.Waveform
  8. {
  9. class MathTools
  10. {
  11. string type = "";
  12. static int bs = 150;
  13. public List<float> xAxis = new List<float>();
  14. public List<float> xAxisF = new List<float>();
  15. public List<string> AxisValue = new List<string>();
  16. static double[] MaxMinArr;
  17. static double step = 10;
  18. static double[] clolist;//显示的步长的集合
  19. //static double max = -9999999;
  20. //static double min = 9999999;
  21. public MathTools(string type)
  22. {
  23. this.type = type;
  24. }
  25. public void MathLoad(List<PointF> mycoor, int coutt)
  26. {
  27. MaxMinArr = ZuiZhiFanWei(mycoor);
  28. step = (MaxMinArr[0] - MaxMinArr[1]) / (coutt + 5);
  29. //if (MaxMinArr[0] > max)
  30. //{
  31. // max = MaxMinArr[0];
  32. //}
  33. //if (MaxMinArr[1] < min)
  34. //{
  35. // min = MaxMinArr[1];
  36. //}
  37. //clolist = JiSuanChaValue(max, min, coutt);
  38. clolist = JiSuanChaValue(MaxMinArr[0], MaxMinArr[1], coutt);
  39. }
  40. /// <summary>
  41. /// 直接构造绘图的PointF点集
  42. /// </summary>
  43. /// <param name="mycoor">CoorClass类型点集</param>
  44. /// <param name="Width">视口宽(px)(用于归范化/归一化)</param>
  45. /// <param name="Height">画布高(px)(用于归范化/归一化)</param>
  46. /// <param name="OffsetX">最终坐标的x偏移值(px)(自定义显示位置的x坐标,用于数据组织)</param>
  47. /// <param name="OffsetY">最终坐标的y偏移值(px)</param>
  48. /// <param name="stepX">x方向步长(确定x方向上1像素对应的数据的单位)</param>
  49. /// <param name="revalue">一个实际的值,用于实时显示</param>
  50. /// <returns></returns>
  51. public PointF[] getDrawPoints(List<PointF> mycoor, int Width, int Height, int OffsetX, int OffsetY, ref string revalue)
  52. {
  53. AxisValue.Clear();
  54. xAxis.Clear();
  55. xAxisF.Clear();
  56. List<PointF> points = new List<PointF>();
  57. List<PointF> pointtemp = new List<PointF>();
  58. PointF temp = new PointF();
  59. int index = 0;
  60. int indexqian = -1;
  61. for (int i = 0; i < mycoor.Count; i++)
  62. {
  63. if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX - 15) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + bs) * step)
  64. {
  65. if (indexqian == -1)
  66. {
  67. indexqian = i;
  68. }
  69. if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + 10) * step)
  70. {
  71. temp = mycoor[i];
  72. }
  73. PointF p = GuiFiHua(mycoor[i], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  74. //PointF p = GuiFiHua(item, MaxMinArr, Height, Width);
  75. p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  76. p.Y += OffsetY;
  77. pointtemp.Add(p);
  78. index = i;
  79. }
  80. //PointF p = GuiFiHua(mycoor[i], MaxMinArr, Height, Width);
  81. ////PointF p = GuiFiHua(item, MaxMinArr, Height, Width);
  82. //p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  83. //p.Y += OffsetY;
  84. //pointtemp.Add(p);
  85. //index = i;
  86. }
  87. if (pointtemp[0].X > 0 && indexqian > 0)
  88. {
  89. //如果点不够,画出来的线就没占满画布视口
  90. //给最前面加一个点
  91. PointF p = GuiFiHua(mycoor[indexqian - 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  92. p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  93. p.Y += OffsetY;
  94. List<PointF> newlis = new List<PointF>() { p };
  95. pointtemp.InsertRange(0, newlis);
  96. }
  97. if (pointtemp[pointtemp.Count - 1].X < Width && index < mycoor.Count - 1)
  98. {
  99. //如果点不够,画出来的线就没占满画布视口
  100. //给最后面加一个点
  101. PointF p = GuiFiHua(mycoor[index + 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  102. p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  103. p.Y += OffsetY;
  104. pointtemp.Add(p);
  105. }
  106. for (int i = 0; i < clolist.Length; i++)
  107. {
  108. if (clolist[i] >= MaxMinArr[1] + step * (OffsetX - 15) && clolist[i] <= MaxMinArr[1] + (OffsetX + bs) * step)
  109. {
  110. PointF p = GuiFiHua(new PointF((float)clolist[i], 0), new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  111. p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  112. if ((i + 6) % 6 == 0)
  113. {
  114. xAxis.Add(p.X);
  115. AxisValue.Add(foo(clolist[i], 7).ToString());
  116. }
  117. else if ((i + 1) % 1 == 0)
  118. {
  119. xAxisF.Add(p.X);
  120. }
  121. }
  122. }
  123. revalue = foo(temp.Y, 5).ToString();
  124. //DataBus.g.DrawEllipse(new Pen(Color.Red, 5), new RectangleF(pointtemp[pointtemp.Count - 1],new Size(5,5)));
  125. return pointtemp.ToArray();
  126. }
  127. public PointF[] getDrawPointsOld(List<PointF> mycoor, int Width, int Height, int OffsetX, int OffsetY, int pianyi)
  128. {
  129. List<PointF> points = new List<PointF>();
  130. List<PointF> pointtemp = new List<PointF>();
  131. PointF temp = new PointF();
  132. int index = 0;
  133. int indexqian = -1;
  134. for (int i = 0; i < mycoor.Count; i++)
  135. {
  136. if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX - 15) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + bs) * step)
  137. {
  138. if (indexqian == -1)
  139. {
  140. indexqian = i;
  141. }
  142. if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + 10) * step)
  143. {
  144. temp = mycoor[i];
  145. }
  146. PointF p = GuiFiHua(mycoor[i], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  147. //PointF p = GuiFiHua(item, MaxMinArr, Height, Width);
  148. p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  149. p.Y += OffsetY;
  150. pointtemp.Add(p);
  151. index = i;
  152. }
  153. }
  154. if (pointtemp[0].X > 0 && indexqian > 0)
  155. {
  156. //如果点不够,画出来的线就没占满画布视口
  157. //给最前面加一个点
  158. PointF p = GuiFiHua(mycoor[indexqian - 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  159. p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  160. p.Y += OffsetY;
  161. List<PointF> newlis = new List<PointF>() { p };
  162. pointtemp.InsertRange(0, newlis);
  163. }
  164. if (pointtemp[pointtemp.Count - 1].X < Width && index < mycoor.Count - 1)
  165. {
  166. //如果点不够,画出来的线就没占满画布视口
  167. //给最后面加一个点
  168. PointF p = GuiFiHua(mycoor[index + 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width);
  169. p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来
  170. p.Y += OffsetY;
  171. pointtemp.Add(p);
  172. }
  173. return pointtemp.ToArray();
  174. }
  175. /// <summary>
  176. /// 进行坐标归一化处理,将原始数据归一化到指定范围内,范围不局限于0-1。
  177. /// </summary>
  178. /// <param name="x0">待处理坐标</param>
  179. /// <param name="MaxMinArr">一个二位数组,记录坐标集y最大最小值。</param>
  180. /// <param name="Height">归一化y范围/画布高/纵轴范围</param>
  181. /// <param name="Width">归一化x范围/画布高/纵轴范围</param>
  182. /// <returns></returns>
  183. public PointF GuiFiHua(PointF x0, double[] MaxMinArr, int Height, int Width)
  184. {
  185. float x = (float)(Width * (x0.X - MaxMinArr[1]) / (MaxMinArr[0] - MaxMinArr[1]));
  186. var zore = 0.0;//把0的归一化值专门做计算,然后减去这个校正值
  187. if (Math.Abs(MaxMinArr[2]) + Math.Abs(MaxMinArr[3]) > Math.Abs(MaxMinArr[2] + MaxMinArr[3]))
  188. {
  189. zore = -MaxMinArr[3] / (MaxMinArr[2] - MaxMinArr[3]);//把0的归一化值专门做计算,然后减去这个校正值
  190. }
  191. float y = 0.0F;
  192. if (MaxMinArr[2] == MaxMinArr[3])
  193. {
  194. y = (float)Height;
  195. }
  196. else
  197. {
  198. y = (float)((Height / 2) * ((x0.Y - MaxMinArr[3]) / (MaxMinArr[2] - MaxMinArr[3]) - zore)); //-0.5是要归一化到(-1,1)之间
  199. }
  200. return new PointF(x, y);
  201. }
  202. /// <summary>
  203. /// 得到一个四位数组,存储坐标集的xy最大最小值,
  204. /// <>依次为[横轴最大值(Xmax),横轴最小值(Xmin),纵轴最大值(Ymax),纵轴最小值(Ymin)]
  205. /// </summary>
  206. /// <param name="mycoor">List<CoorYX>坐标集</param>
  207. /// <returns></returns>
  208. public double[] ZuiZhiFanWei(List<PointF> mycoor)
  209. {
  210. double ymax = -999999999, ymin = 999999999, xmin = 999999999, xmax = -999999999;
  211. foreach (var item in mycoor)
  212. {
  213. if (item.Y >= ymax)
  214. {
  215. ymax = item.Y;
  216. }
  217. if (item.Y < ymin)
  218. {
  219. ymin = item.Y;
  220. }
  221. if (item.X < xmin)
  222. {
  223. xmin = item.X;
  224. }
  225. if (item.X >= xmax)
  226. {
  227. xmax = item.X;
  228. }
  229. }
  230. return new double[] { xmax, xmin, ymax, ymin };
  231. }
  232. /// <summary>
  233. /// 矫正偏移量,将小数偏移量映射到坐标系中,按照步长进行矫正
  234. /// </summary>
  235. public int PYLJZ(double offset, double constOffset, int height, int step)
  236. {
  237. return (int)((height - (offset + constOffset) * height) / step) * step;
  238. }
  239. /// <summary>
  240. /// 保留有效数字
  241. /// </summary>
  242. /// <param name="d">数</param>
  243. /// <param name="n">几位</param>
  244. /// <returns></returns>
  245. public double foo(double d, int n)
  246. {
  247. if (d == 0.0) return 0;
  248. if (d > 1 || d < -1)
  249. n = n - (int)Math.Log10(Math.Abs(d)) - 1;
  250. else
  251. n = n + (int)Math.Log10(1.0 / Math.Abs(d));
  252. if (n < 0)
  253. {
  254. d = (int)(d / Math.Pow(10, 0 - n)) * Math.Pow(10, 0 - n);
  255. n = 0;
  256. }
  257. return Math.Round(d, n);
  258. }
  259. static double[] JiSuanChaValue(double UpValue, double DownValue, int Number)
  260. {
  261. double[] dataList = new double[Number];
  262. dataList[0] = UpValue;
  263. bool IsUp = UpValue < DownValue ? true : false;
  264. double Up_Number = UpValue;//找到底数 //得到两个数值之间的差
  265. double Cha = Math.Abs(DownValue - UpValue);
  266. //得到平均数
  267. double MeanValue = Cha / (Number - 1);
  268. if (IsUp)//从小到大
  269. {
  270. for (int i = 1; i < Number - 1; i++)
  271. {
  272. dataList[i] = Up_Number + (MeanValue * (i));
  273. }
  274. }
  275. else
  276. {
  277. for (int i = 1; i < Number - 1; i++)
  278. {
  279. dataList[i] = Up_Number - (MeanValue * (i));
  280. }
  281. }
  282. dataList[dataList.Length - 1] = DownValue;
  283. return dataList;
  284. }
  285. }
  286. }