using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Runtime.Serialization; using System.Security.Permissions; using System.ComponentModel; namespace IStation.Model { /// /// 曲线表达式 /// [DataContract] public class CurveExpress : ICloneable { #region 构造函数 public CurveExpress() { } public CurveExpress(CurveExpress rhs) { this.FitPow = rhs.FitPow; this.FitType = rhs.FitType; this.Min = rhs.Min; this.Max = rhs.Max; this.Index0 = rhs.Index0; this.Index1 = rhs.Index1; this.Index2 = rhs.Index2; this.Index3 = rhs.Index3; this.DefinePoints = rhs.DefinePoints?.Select(x => new CurvePoint(x)).ToList(); this.IsNull = rhs.IsNull; } public CurveExpress(CurveExpress rhs, double ratio_y) { this.FitPow = rhs.FitPow; this.FitType = rhs.FitType; this.Min = rhs.Min; this.Max = rhs.Max; this.Index0 = rhs.Index0 * ratio_y; this.Index1 = rhs.Index1 * ratio_y; this.Index2 = rhs.Index2 * ratio_y; this.Index3 = rhs.Index3 * ratio_y; this.DefinePoints = rhs.DefinePoints?.Select(x => new CurvePoint(x.X, x.Y * ratio_y)).ToList(); this.IsNull = rhs.IsNull; } public CurveExpress(string strParas) { if (string.IsNullOrEmpty(strParas)) { this.IsNull = true; return; } var str_list = strParas.Split(new string[] { Separator }, StringSplitOptions.RemoveEmptyEntries); var count = str_list.Count(); if (count < 8) { this.IsNull = true; return; } this.IsNull = false ; this.FitPow = Convert.ToInt32(str_list[0]); this.FitType = (eCurveFitType)Convert.ToInt32(str_list[1]); this.Min = Convert.ToDouble(str_list[2]); this.Max = Convert.ToDouble(str_list[3]); this.Index0 = Convert.ToDouble(str_list[4]); this.Index1 = Convert.ToDouble(str_list[5]); this.Index2 = Convert.ToDouble(str_list[6]); this.Index3 = Convert.ToDouble(str_list[7]); if (count > 8) { this.DefinePoints = CurvePoint.ToList(str_list[8]); } } public CurveExpress(List points) { ResetCurve(points, eCurveFitType.CubicCurve, false); } public CurveExpress(List points, bool savePoints) { ResetCurve(points, eCurveFitType.CubicCurve, savePoints); } public CurveExpress(List points, eCurveFitType fitType) { ResetCurve(points, fitType,false); } public CurveExpress(List points, eCurveFitType fitType, bool savePoints) { ResetCurve(points, fitType, savePoints); } public CurveExpress(List points, int fitPow) { ResetCurve(points, fitPow,false); } public CurveExpress(List points, int fitPow, bool savePoints) { ResetCurve(points, fitPow, savePoints); } /// /// 重置曲线 /// public virtual void ResetCurve(CurveExpress rhs) { this.FitPow = rhs.FitPow; this.FitType = rhs.FitType; this.Min = rhs.Min; this.Max = rhs.Max; this.Index0 = rhs.Index0; this.Index1 = rhs.Index1; this.Index2 = rhs.Index2; this.Index3 = rhs.Index3; this.DefinePoints = rhs.DefinePoints?.Select(x => new CurvePoint(x)).ToList(); this.IsNull = rhs.IsNull; } /// /// 重置曲线 /// public virtual void ResetCurve(List points, eCurveFitType fitType, bool savePoints = false ) { var express = FitCurveHelper.BuildCurveExpress(points, fitType); if (express == null) { this.IsNull = true; return; } if (express.IsNull) { this.IsNull = true; return; } this.FitType = express.FitType; this.FitPow = express.FitPow; this.Min = express.Min; this.Max = express.Max; this.Index0 = express.Index0; this.Index1 = express.Index1; this.Index2 = express.Index2; this.Index3 = express.Index3; this.IsNull = express.IsNull; if (savePoints) { this.DefinePoints = express.DefinePoints; } else if (fitType == eCurveFitType.ThroughPoint) { this.DefinePoints = express.DefinePoints; } } /// /// 重置曲线 /// public virtual void ResetCurve(List points, int fitPow, bool savePoints = false ) { var fitType = GetFitType(fitPow); this.ResetCurve(points, fitType, savePoints); } #endregion #region 静态值 public const string Separator = "#"; #endregion #region 属性 /// /// 拟合次数 /// [DataMember] public int FitPow { get { return fitPow; } set { fitPow = value; } } protected int fitPow = 3; /// /// 拟合类型 /// [DataMember] public eCurveFitType FitType { get { return fitType; } set { fitType = value; } } protected eCurveFitType fitType = eCurveFitType.CubicCurve; /// /// 最大值 /// [DataMember] public double Max { get { return max; } set { max = value; } } protected double max; /// /// 最小值 /// [DataMember] public double Min { get { return min; } set { min = value; } } protected double min; /// /// 0次系数 /// [DataMember] public double Index0 { get { return index0; } set { index0 = value; } } protected double index0; /// /// 1次系数 /// [DataMember] public double Index1 { get { return index1; } set { index1 = value; } } protected double index1; /// /// 2次系数 /// [DataMember] public double Index2 { get { return index2; } set { index2 = value; } } protected double index2; /// /// 3次系数 /// [DataMember] public double Index3 { get { return index3; } set { index3 = value; } } protected double index3; /// /// 定义点 /// [DataMember] public List DefinePoints { get { return definePoints; } set { definePoints = value; } } protected List definePoints = null; /// /// 是否为空 /// [DataMember] public bool IsNull { get { return isNull; } set { isNull = value; } } protected bool isNull; #endregion /// /// 转化为保存字符串 /// public string ToDsString() { var str_list = new List(); str_list.Add(this.FitPow.ToString()); str_list.Add(((int)this.FitType).ToString()); str_list.Add(this.Min.ToString()); str_list.Add(this.Max.ToString()); //str_list.Add(this.Index0.ToString()); //str_list.Add(this.Index1.ToString("0.00000")); //str_list.Add(this.Index2.ToString("0.0000000000")); //str_list.Add(this.Index3.ToString("0.00000000000000")); //nsx var dc = new DoubleConverter(); str_list.Add(dc.ConvertToString(this.Index0)); str_list.Add(dc.ConvertToString(this.Index1)); str_list.Add(dc.ConvertToString(this.Index2)); str_list.Add(dc.ConvertToString(this.Index3)); if (this.DefinePoints != null && this.DefinePoints.Count > 0) { str_list.Add(this.DefinePoints.ToDsString()); } return string.Join(Separator, str_list); } object ICloneable.Clone() { return Clone(); } public CurveExpress Clone() { return new CurveExpress(this); } /// /// 是否在内部 /// public bool IsInterior(double x) { if (x < Min) return false; if (x > Max) return false; return true; } /// /// 获取拟合次方 /// public static int GetFitPow(eCurveFitType fitType) { switch (fitType) { case eCurveFitType.CubicCurve: return 3; case eCurveFitType.ConicCurve: return 2; case eCurveFitType.ConicCurveB0: return 2; case eCurveFitType.LinearCurve: return 1; case eCurveFitType.ThroughPoint: return 0; default: return 3; } } /// /// 获取拟合类型 /// public static eCurveFitType GetFitType(int fitPow) { switch (fitPow) { case 3: return eCurveFitType.CubicCurve; case 2: return eCurveFitType.ConicCurve; case 1: return eCurveFitType.LinearCurve; case 0: return eCurveFitType.ThroughPoint; default: return eCurveFitType.CubicCurve; } } /// /// 获取拟合点 /// public double GetFitPointY(double x) { return FitCurveHelper.GetFitPointY(this, x); } /// /// 获取拟合点 /// public List GetFitPoints(int pointNumber = 20) { if (this.IsNull) return default; return FitCurveHelper.GetFitPoints(this, pointNumber); } /// /// 通过区间内拟合点 /// public List GetFitPointsByRange(double minX, double maxX, int pointNumber = 20) { if (this.IsNull) return default; return FitCurveHelper.GetFitPointsByRange(this, minX, maxX, pointNumber); } /// /// 获取拟合点 /// public List GetFitPointsByExtend(double ratioExtend, int pointNumber = 20) { if (this.IsNull) return default; return GetFitPointsByRange(this.min, this.max * ratioExtend, pointNumber); } /// /// 获取第一个拟合点 /// public CurvePoint GetFirstFitPoint() { return new CurvePoint(this.Min, GetFitPointY(this.Min)); } /// /// 获取最后一个拟合点 /// public CurvePoint GetLastFitPoint() { return new CurvePoint(this.Max, GetFitPointY(this.Max)); } /// /// 获取零点的Y值 /// public double GetZeroFitPointY() { return this.Index0; } /// /// 转换为Model /// public static CurveExpress ToModel(string strParas) { if (string.IsNullOrEmpty(strParas)) return default; var express = new CurveExpress(strParas); if (express == null) return default; return express; } /// /// 是否相等 /// public bool IsEquals(CurveExpress rhs) { if (rhs == null) return false; if (rhs.ToDsString().Equals(this.ToDsString())) return true; else return false; } /// /// 是否为Zero表达式 /// public bool IsZeroExpress() { if (this.Index0 != 0) return false; if (this.Index1 != 0) return false; if (this.Index2 != 0) return false; if (this.Index3 != 0) return false; return true; } /// /// 通过 X转换 /// public CurveExpress TransferX(double ratioX) { var fitPoints = this.GetFitPoints(); fitPoints = fitPoints?.Select(x => new CurvePoint(x.X * ratioX, x.Y)).ToList(); if (fitPoints == null || fitPoints.Count < 1) return default; var exp = new CurveExpress(fitPoints, this.FitType); var definePoints = this.DefinePoints?.Select(x => new CurvePoint(x.X * ratioX, x.Y)).ToList(); if (definePoints != null && definePoints.Count > 0) exp.DefinePoints = definePoints; return exp; } /// /// 相似换算(speed_ratio = 新的转速 除以 老的转速) /// public CurveExpress SimuBySpeed(eFeatCurveType featType, double speed_ratio, int pointNumber = 20) { double space = (this.Max - this.Min) / (pointNumber - 1); switch (featType) { case eFeatCurveType.QH: { List pointInfo60 = new List(); for (int i = 0; i < pointNumber; i++) { double q50 = space * i + this.Min; double q60 = q50 * speed_ratio; double Y50 = GetFitPointY(q50); pointInfo60.Add(new CurvePoint() { X = q60, Y = Y50 * speed_ratio * speed_ratio }); } var new_curve = new CurveExpress(pointInfo60, this.FitType); new_curve.DefinePoints = this.DefinePoints?.Select(x => new CurvePoint() { X = x.X * speed_ratio, Y = x.Y * speed_ratio * speed_ratio }).ToList(); return new_curve; } case eFeatCurveType.QE: { List pointInfo60 = new List(); for (int i = 0; i < pointNumber; i++) { double q50 = space * i + this.Min; double q60 = q50 * speed_ratio; double Y50 = GetFitPointY(q50); pointInfo60.Add(new CurvePoint() { X = q60, Y = Y50 }); } var new_curve = new CurveExpress(pointInfo60, this.FitType); return new_curve; } case eFeatCurveType.QP: { List pointInfo60 = new List(); for (int i = 0; i < pointNumber; i++) { double q50 = space * i + this.Min; double q60 = q50 * speed_ratio; double Y50 = GetFitPointY(q50); pointInfo60.Add(new CurvePoint() { X = q60, Y = Y50 * speed_ratio * speed_ratio * speed_ratio }); } var new_curve = new CurveExpress(pointInfo60); new_curve.DefinePoints = this.DefinePoints?.Select(x => new CurvePoint() { X = x.X * speed_ratio, Y = x.Y * speed_ratio * speed_ratio * speed_ratio }).ToList(); return new_curve; } default: { List pointInfo60 = new List(); for (int i = 0; i < pointNumber; i++) { double q50 = space * i + this.Min; double q60 = q50 * speed_ratio; double Y50 = GetFitPointY(q50); pointInfo60.Add(new CurvePoint() { X = q60, Y = Y50 }); } var new_curve = new CurveExpress(pointInfo60); new_curve.DefinePoints = this.DefinePoints?.Select(x => new CurvePoint() { X = x.X * speed_ratio, Y = x.Y }).ToList(); return new_curve; } } } /// /// 50 到 60 /// public CurveExpress SimuFrom50To60(eFeatCurveType featType, int pointNumber = 20) { return SimuBySpeed(featType, 1.2, pointNumber); } /// /// 曲线方程:用于显示 /// public string GetCurveFunction(string xName = "Q") { //double signValue = 0; //int value = 0; StringBuilder sb = new StringBuilder(); //sb.Append(this.index0.ToString("G")); //sb.Append(this.index0.ToString("0.00E+000"));//ToString("G")); sb.Append(Math.Abs(this.Index0).ToString("0.00"));//.ToString("G")); if (this.Index1 > 0) sb.Append(" + "); else sb.Append(" - "); //GetFuncScientificValue(1,Math.Abs(index1),ref signValue,ref value); //sb.AppendFormat("{0}E{1}",signValue,value); sb.Append(Math.Abs(this.Index1).ToString("0.0000"));//.ToString("G")); sb.Append(" * "); sb.Append(xName); if (this.Index2 > 0) sb.Append(" + "); else sb.Append(" - "); //GetFuncScientificValue(2,Math.Abs(index2),ref signValue,ref value); //sb.AppendFormat("{0}E{1}",signValue,value); //sb.Append(Math.Round(Math.Abs(this.index2),4).ToString("G"));//.ToString("G")); sb.Append(Math.Abs(this.Index2).ToString("0.000000000"));//.ToString("G")); sb.Append(" * "); sb.Append(xName); sb.Append("^2 "); if (this.Index3 > 0) sb.Append(" + "); else sb.Append(" - "); //GetFuncScientificValue(3,Math.Abs(index3),ref signValue,ref value); //sb.AppendFormat("{0}E{1}",signValue,value); //sb.Append(Math.Abs(this.index3).ToString("G"));//.ToString("G")); sb.Append(Math.Abs(this.Index3).ToString("0.000000000000"));//.ToString("G")); sb.Append(" * "); sb.Append(xName); sb.Append("^3 "); return sb.ToString(); } private static void GetFuncScientificValue(int FunctionIndex, double FunctionCoeff, ref double signValue, ref int indexValue) { string strList = ""; if (FunctionIndex == 0) { strList = FunctionCoeff.ToString("0.000e+000"); } else if (FunctionIndex == 1) { strList = FunctionCoeff.ToString("0.000000e+000"); } else if (FunctionIndex == 2) { strList = FunctionCoeff.ToString("#.#########e+000"); } else if (FunctionIndex == 3) { strList = FunctionCoeff.ToString("#.############e+000"); } string[] st1 = null; st1 = strList.Split('e'); signValue = Convert.ToDouble(st1[0]); indexValue = Convert.ToInt32(st1[1]); } } }