123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301 |
- 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<float> xAxis = new List<float>();
- public List<float> xAxisF = new List<float>();
- public List<string> AxisValue = new List<string>();
- 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<PointF> 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);
- }
- /// <summary>
- /// 直接构造绘图的PointF点集
- /// </summary>
- /// <param name="mycoor">CoorClass类型点集</param>
- /// <param name="Width">视口宽(px)(用于归范化/归一化)</param>
- /// <param name="Height">画布高(px)(用于归范化/归一化)</param>
- /// <param name="OffsetX">最终坐标的x偏移值(px)(自定义显示位置的x坐标,用于数据组织)</param>
- /// <param name="OffsetY">最终坐标的y偏移值(px)</param>
- /// <param name="stepX">x方向步长(确定x方向上1像素对应的数据的单位)</param>
- /// <param name="revalue">一个实际的值,用于实时显示</param>
- /// <returns></returns>
- public PointF[] getDrawPoints(List<PointF> mycoor, int Width, int Height, int OffsetX, int OffsetY, ref string revalue)
- {
- AxisValue.Clear();
- xAxis.Clear();
- xAxisF.Clear();
- List<PointF> points = new List<PointF>();
- List<PointF> pointtemp = new List<PointF>();
- 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<PointF> newlis = new List<PointF>() { 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<PointF> mycoor, int Width, int Height, int OffsetX, int OffsetY, int pianyi)
- {
- List<PointF> points = new List<PointF>();
- List<PointF> pointtemp = new List<PointF>();
- 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<PointF> newlis = new List<PointF>() { 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();
- }
- /// <summary>
- /// 进行坐标归一化处理,将原始数据归一化到指定范围内,范围不局限于0-1。
- /// </summary>
- /// <param name="x0">待处理坐标</param>
- /// <param name="MaxMinArr">一个二位数组,记录坐标集y最大最小值。</param>
- /// <param name="Height">归一化y范围/画布高/纵轴范围</param>
- /// <param name="Width">归一化x范围/画布高/纵轴范围</param>
- /// <returns></returns>
- 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);
- }
- /// <summary>
- /// 得到一个四位数组,存储坐标集的xy最大最小值,
- /// <>依次为[横轴最大值(Xmax),横轴最小值(Xmin),纵轴最大值(Ymax),纵轴最小值(Ymin)]
- /// </summary>
- /// <param name="mycoor">List<CoorYX>坐标集</param>
- /// <returns></returns>
- public double[] ZuiZhiFanWei(List<PointF> 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 };
- }
- /// <summary>
- /// 矫正偏移量,将小数偏移量映射到坐标系中,按照步长进行矫正
- /// </summary>
- public int PYLJZ(double offset, double constOffset, int height, int step)
- {
- return (int)((height - (offset + constOffset) * height) / step) * step;
- }
- /// <summary>
- /// 保留有效数字
- /// </summary>
- /// <param name="d">数</param>
- /// <param name="n">几位</param>
- /// <returns></returns>
- 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;
- }
- }
- }
|