using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Uninpho.Railway.Waveform { class MathTools { string type = ""; static int bs = 150; public List xAxis = new List(); public List xAxisF = new List(); public List AxisValue = new List(); static double[] MaxMinArr; static double step = 10; static double[] clolist;//显示的步长的集合 //static double max = -9999999; //static double min = 9999999; public MathTools(string type) { this.type = type; } public void MathLoad(List mycoor, int coutt) { MaxMinArr = ZuiZhiFanWei(mycoor); step = (MaxMinArr[0] - MaxMinArr[1]) / (coutt + 5); //if (MaxMinArr[0] > max) //{ // max = MaxMinArr[0]; //} //if (MaxMinArr[1] < min) //{ // min = MaxMinArr[1]; //} //clolist = JiSuanChaValue(max, min, coutt); clolist = JiSuanChaValue(MaxMinArr[0], MaxMinArr[1], coutt); } /// /// 直接构造绘图的PointF点集 /// /// CoorClass类型点集 /// 视口宽(px)(用于归范化/归一化) /// 画布高(px)(用于归范化/归一化) /// 最终坐标的x偏移值(px)(自定义显示位置的x坐标,用于数据组织) /// 最终坐标的y偏移值(px) /// x方向步长(确定x方向上1像素对应的数据的单位) /// 一个实际的值,用于实时显示 /// public PointF[] getDrawPoints(List mycoor, int Width, int Height, int OffsetX, int OffsetY, ref string revalue) { AxisValue.Clear(); xAxis.Clear(); xAxisF.Clear(); List points = new List(); List pointtemp = new List(); PointF temp = new PointF(); int index = 0; int indexqian = -1; for (int i = 0; i < mycoor.Count; i++) { if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX - 15) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + bs) * step) { if (indexqian == -1) { indexqian = i; } if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + 10) * step) { temp = mycoor[i]; } PointF p = GuiFiHua(mycoor[i], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); //PointF p = GuiFiHua(item, MaxMinArr, Height, Width); p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; pointtemp.Add(p); index = i; } //PointF p = GuiFiHua(mycoor[i], MaxMinArr, Height, Width); ////PointF p = GuiFiHua(item, MaxMinArr, Height, Width); //p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 //p.Y += OffsetY; //pointtemp.Add(p); //index = i; } if (pointtemp[0].X > 0 && indexqian > 0) { //如果点不够,画出来的线就没占满画布视口 //给最前面加一个点 PointF p = GuiFiHua(mycoor[indexqian - 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; List newlis = new List() { p }; pointtemp.InsertRange(0, newlis); } if (pointtemp[pointtemp.Count - 1].X < Width && index < mycoor.Count - 1) { //如果点不够,画出来的线就没占满画布视口 //给最后面加一个点 PointF p = GuiFiHua(mycoor[index + 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; pointtemp.Add(p); } for (int i = 0; i < clolist.Length; i++) { if (clolist[i] >= MaxMinArr[1] + step * (OffsetX - 15) && clolist[i] <= MaxMinArr[1] + (OffsetX + bs) * step) { 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); p.X -= OffsetX * 2;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 if ((i + 6) % 6 == 0) { xAxis.Add(p.X); AxisValue.Add(foo(clolist[i], 7).ToString()); } else if ((i + 1) % 1 == 0) { xAxisF.Add(p.X); } } } revalue = foo(temp.Y, 5).ToString(); //DataBus.g.DrawEllipse(new Pen(Color.Red, 5), new RectangleF(pointtemp[pointtemp.Count - 1],new Size(5,5))); return pointtemp.ToArray(); } public PointF[] getDrawPointsOld(List mycoor, int Width, int Height, int OffsetX, int OffsetY, int pianyi) { List points = new List(); List pointtemp = new List(); PointF temp = new PointF(); int index = 0; int indexqian = -1; for (int i = 0; i < mycoor.Count; i++) { if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX - 15) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + bs) * step) { if (indexqian == -1) { indexqian = i; } if (mycoor[i].X >= MaxMinArr[1] + step * (OffsetX) && mycoor[i].X <= MaxMinArr[1] + (OffsetX + 10) * step) { temp = mycoor[i]; } PointF p = GuiFiHua(mycoor[i], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); //PointF p = GuiFiHua(item, MaxMinArr, Height, Width); p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; pointtemp.Add(p); index = i; } } if (pointtemp[0].X > 0 && indexqian > 0) { //如果点不够,画出来的线就没占满画布视口 //给最前面加一个点 PointF p = GuiFiHua(mycoor[indexqian - 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; List newlis = new List() { p }; pointtemp.InsertRange(0, newlis); } if (pointtemp[pointtemp.Count - 1].X < Width && index < mycoor.Count - 1) { //如果点不够,画出来的线就没占满画布视口 //给最后面加一个点 PointF p = GuiFiHua(mycoor[index + 1], new double[] { MaxMinArr[1] + (OffsetX + 10) * step, MaxMinArr[1] + step * OffsetX, MaxMinArr[2], MaxMinArr[3] }, Height, Width); p.X -= OffsetX * 2 + pianyi;//OffsetX*2可以让波形图进行平移,左右给他滚动起来 p.Y += OffsetY; pointtemp.Add(p); } return pointtemp.ToArray(); } /// /// 进行坐标归一化处理,将原始数据归一化到指定范围内,范围不局限于0-1。 /// /// 待处理坐标 /// 一个二位数组,记录坐标集y最大最小值。 /// 归一化y范围/画布高/纵轴范围 /// 归一化x范围/画布高/纵轴范围 /// public PointF GuiFiHua(PointF x0, double[] MaxMinArr, int Height, int Width) { float x = (float)(Width * (x0.X - MaxMinArr[1]) / (MaxMinArr[0] - MaxMinArr[1])); var zore = 0.0;//把0的归一化值专门做计算,然后减去这个校正值 if (Math.Abs(MaxMinArr[2]) + Math.Abs(MaxMinArr[3]) > Math.Abs(MaxMinArr[2] + MaxMinArr[3])) { zore = -MaxMinArr[3] / (MaxMinArr[2] - MaxMinArr[3]);//把0的归一化值专门做计算,然后减去这个校正值 } float y = 0.0F; if (MaxMinArr[2] == MaxMinArr[3]) { y = (float)Height; } else { y = (float)((Height / 2) * ((x0.Y - MaxMinArr[3]) / (MaxMinArr[2] - MaxMinArr[3]) - zore)); //-0.5是要归一化到(-1,1)之间 } return new PointF(x, y); } /// /// 得到一个四位数组,存储坐标集的xy最大最小值, /// <>依次为[横轴最大值(Xmax),横轴最小值(Xmin),纵轴最大值(Ymax),纵轴最小值(Ymin)] /// /// List坐标集 /// public double[] ZuiZhiFanWei(List mycoor) { double ymax = -999999999, ymin = 999999999, xmin = 999999999, xmax = -999999999; foreach (var item in mycoor) { if (item.Y >= ymax) { ymax = item.Y; } if (item.Y < ymin) { ymin = item.Y; } if (item.X < xmin) { xmin = item.X; } if (item.X >= xmax) { xmax = item.X; } } return new double[] { xmax, xmin, ymax, ymin }; } /// /// 矫正偏移量,将小数偏移量映射到坐标系中,按照步长进行矫正 /// public int PYLJZ(double offset, double constOffset, int height, int step) { return (int)((height - (offset + constOffset) * height) / step) * step; } /// /// 保留有效数字 /// /// 数 /// 几位 /// public double foo(double d, int n) { if (d == 0.0) return 0; if (d > 1 || d < -1) n = n - (int)Math.Log10(Math.Abs(d)) - 1; else n = n + (int)Math.Log10(1.0 / Math.Abs(d)); if (n < 0) { d = (int)(d / Math.Pow(10, 0 - n)) * Math.Pow(10, 0 - n); n = 0; } return Math.Round(d, n); } static double[] JiSuanChaValue(double UpValue, double DownValue, int Number) { double[] dataList = new double[Number]; dataList[0] = UpValue; bool IsUp = UpValue < DownValue ? true : false; double Up_Number = UpValue;//找到底数 //得到两个数值之间的差 double Cha = Math.Abs(DownValue - UpValue); //得到平均数 double MeanValue = Cha / (Number - 1); if (IsUp)//从小到大 { for (int i = 1; i < Number - 1; i++) { dataList[i] = Up_Number + (MeanValue * (i)); } } else { for (int i = 1; i < Number - 1; i++) { dataList[i] = Up_Number - (MeanValue * (i)); } } dataList[dataList.Length - 1] = DownValue; return dataList; } } }