using IStation.Model; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace IStation.Calculation.DispatchAna.Common { /// /// /// public class SimuSpeedCalcHelper { /// /// / /// /// /// /// /// /// public static IStation.Model.CurveExpress GetSimuPointQH(IStation.Model.CurveExpress OriginExpress, double origin_speed, double change_speed, int pointNum = 12) { //change可以大于origin,有时用于反求 if (OriginExpress == null) return null; if (change_speed < 1) return null; var simularPoints = new List(); var curvePoints = IStation.Model.FitCurveHelper.GetFitPoints(OriginExpress); foreach (IStation.Model.CurvePoint pt in curvePoints) { simularPoints.Add(new IStation.Model.CurvePoint( GetQ(pt.X, origin_speed, change_speed), GetH(pt.Y, origin_speed, change_speed))); } return new IStation.Model.CurveExpress(curvePoints, OriginExpress.FitType); } /// /// /// /// /// /// /// /// public static IStation.Model.CurveExpress GetSimuPointQP(IStation.Model.CurveExpress OriginExpress, double origin, double change, int pointNum = 12) { if (OriginExpress == null) return null; var simularPoints = new List(); var curvePoints = IStation.Model.FitCurveHelper.GetFitPoints(OriginExpress); foreach (IStation.Model.CurvePoint pt in curvePoints) { simularPoints.Add(new IStation.Model.CurvePoint( GetQ(pt.X, origin, change), GetP(pt.Y, origin, change))); } return new IStation.Model.CurveExpress(curvePoints, OriginExpress.FitType); } /// /// /// /// /// /// /// /// public static double GetSimuValue(IStation.Model.CurveExpress curveExpressQH, IStation.Model.CurvePoint simularPoint, double originValue, double extendRatio = 1) { if (curveExpressQH == null) return -3; if (simularPoint.X < 0.1 || simularPoint.Y < 0.1) return -2; if (simularPoint.X > curveExpressQH.Max * extendRatio * 1.5) return -4; if (curveExpressQH.FitType == IStation.Model.eCurveFitType.ThroughPoint) { } //计算交点位置参数 var sectPoint = GetSectPoint(curveExpressQH, simularPoint, extendRatio); if (sectPoint == null || IsZeroPoint(sectPoint)) return -5; //计算相似点的转速/直径 return GetSimuByH(originValue, sectPoint.Y, simularPoint.Y); } /// /// ratioIgnore:作用 当simularPoint超出曲线范围时,曲线扩大的倍数 /// /// /// /// /// public static IStation.Model.CurvePoint GetSectPoint(CurveExpress CurveExpress, IStation.Model.CurvePoint simularPoint, double ratioIgnore) { return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore); } /// /// ratioIgnore:作用 当simularPoint超出范围时,扩大的倍数 /// /// /// /// /// /// public static IStation.Model.CurvePoint GetSectPointGeneral(IStation.Model.CurveExpress curveExpress, IStation.Model.CurvePoint simularPoint, double index, double ratioIgnore) { var sectPoint = new IStation.Model.CurvePoint(0, 0); if (curveExpress == null) return sectPoint; if (simularPoint.X < 1) return sectPoint; var CurveExpressEx = new IStation.Model.CurveExpress(curveExpress); //检查是否在曲线的区域范围内 double maxQ = CurveExpressEx.Max; double maxH = IStation.Model.FitCurveHelper.GetFitPointY(CurveExpressEx, maxQ); double k1 = maxH / Math.Pow(maxQ, index); double k2 = simularPoint.Y / Math.Pow(simularPoint.X, index); if (k1 > k2) { CurveExpressEx.Max = CurveExpressEx.Max * ratioIgnore;//放大1.2倍 } if (Math.Abs(index - 1) < 0.01) return GetSectPointLine(CurveExpressEx, simularPoint); if (Math.Abs(index - 2) < 0.01) return GetSectPointParabola(CurveExpressEx, simularPoint); //计算系数K double fixK = simularPoint.Y / Math.Pow(simularPoint.X, index); if (fixK < 0.000001) return sectPoint; //思路是从simularPoint开始逐个增加0.1,直到k值最接近fixK double space = (CurveExpressEx.Max - simularPoint.X) / 1000; double x = simularPoint.X; double y, k; do { x = x + space; y = IStation.Model.FitCurveHelper.GetFitPointY(CurveExpressEx, x); k = y / Math.Pow(x, index); } while (k > fixK); sectPoint.X = x; sectPoint.Y = y; return sectPoint; } /// /// /// /// /// /// protected static IStation.Model.CurvePoint GetSectPointLine(IStation.Model.CurveExpress curveExpress, IStation.Model.CurvePoint simularPoint) { var sectPoint = new IStation.Model.CurvePoint(0, 0); if (curveExpress == null) return sectPoint; //计算直线的K if (simularPoint.X < 1) return sectPoint; double a = simularPoint.Y / simularPoint.X; if (a < 0.0001) return sectPoint; //点越多越精确 return GetSectPointLine(IStation.Model.FitCurveHelper.GetFitPoints(curveExpress, 100), simularPoint); } /// /// 通过点simularPoint和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0)) /// /// /// /// protected static IStation.Model.CurvePoint GetSectPointLine(List CurvePoints, IStation.Model.CurvePoint simularPoint) { var sectPoint = new IStation.Model.CurvePoint(0, 0); if (CurvePoints == null || CurvePoints.Count < 2) return sectPoint; //计算直线的K if (simularPoint.X < 1) return sectPoint; double a = simularPoint.Y / simularPoint.X; if (a < 0.0001) return sectPoint; //与2点连成直线的交点,判断交点是否在2点之间,即可是曲线的交点 double b, c; double x; for (int i = 0; i < CurvePoints.Count - 1; i++) { CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c); /*解方程 * y=ax * y=bx+c */ if (Math.Abs(a - b) < 0.001) continue; x = c / (a - b); if (IStation.Common.PointHelper.IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, x)) { sectPoint.X = x; sectPoint.Y = a * x; return sectPoint; } } return sectPoint; } #region 变换公式 private static double _speedIndexQ = 1; /// /// /// /// public static double GetIndexQ() { return _speedIndexQ; } private static double _speedIndexH = 2; /// /// /// /// public static double GetIndexH() { return _speedIndexH; } /// /// 知道原始速度和改变后的速度,求原始流量originQ对应改变后的流量 /// /// /// /// /// public static double GetQ(double originQ, double originN, double changeN) { double ratio = originN / changeN; return originQ / ratio; } /// /// 知道原始速度和改变后的速度,求原始扬程originH对应改变后的扬程 /// /// /// /// /// public static double GetH(double originH, double originN, double changeN) { double ratio = Math.Pow(originN / changeN, _speedIndexH); return originH / ratio; } /// /// 知道原始速度和改变后的速度,求原始功率originP对应改变后的功率 /// /// /// /// /// public static double GetP(double originP, double originN, double changeN) { double ratio = Math.Pow(originN / changeN, _speedIndexH + _speedIndexQ); return originP / ratio; } /// /// 知道原始速度和改变后的速度,求原始效率originE对应改变后的效率 /// /// /// /// /// public static double GetE(double originE, double originN, double changeN) {//变速度公式(P65页) if (changeN >= originN) return originE;//不能处理转速变大的情况,不然效率可能超过100 double ratio = originN / changeN; double bilv = Math.Pow(ratio, 0.17); return originE * 100 / (originE + (100 - originE) * bilv); } /// /// 知道原始速度,以及原始的杨程H以及对应的变速后的杨程,求变速后的速度 /// /// /// /// /// public static double GetSimuByH(double originSpeend, double originH, double changeH) { double ratio = Math.Pow(originH / changeH, 1 / _speedIndexH); return originSpeend / ratio; } #endregion /// /// 判断是否是0点,用于判断函数是否成功返回 /// /// /// public static bool IsZeroPoint(IStation.Model.CurvePoint pt) { if (pt.X < 0.01 && pt.Y < 0.01) return true; else return false; } /// /// /// /// /// /// /// public static bool GetMinMaxPointY(List points, out double maxY, out double minY) { if (points == null) { maxY = (minY = 0.0); return false; } List fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0); maxY = fitPointsByExtend.Max(x => x.Y); minY = fitPointsByExtend.Min(x => x.Y); return true; } /// /// /// /// /// /// /// public static bool GetMinMaxPointY(IStation.Model.CurveExpress curve, out double maxY, out double minY) { if (curve == null) { maxY = (minY = 0.0); return false; } var points = IStation.Model.FitCurveHelper.GetFitPoints(curve); if (points == null) { maxY = (minY = 0.0); return false; } List fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0); maxY = fitPointsByExtend.Max(x => x.Y); minY = fitPointsByExtend.Min(x => x.Y); return true; } /// /// /// /// /// /// public static IStation.Model.CurvePoint GetSectPointParabola(CurveExpress CurveExpress, IStation.Model.CurvePoint simularPoint) { IStation.Model.CurvePoint result = new IStation.Model.CurvePoint(0, 0); if (CurveExpress == null) { return result; } return GetSectPointParabola(FitCurveHelper.GetFitPointsByExtend(CurveExpress, 1.2, 50), simularPoint); } /// /// /// /// /// /// public static IStation.Model.CurvePoint GetSectPointParabola(List CurvePoints, IStation.Model.CurvePoint simularPoint) { return GetSectPoint(CurvePoints, simularPoint, 0.0); } /// /// /// /// /// /// /// public static IStation.Model.CurvePoint GetSectPoint(List CurvePoints, IStation.Model.CurvePoint simularPoint, double equipCurveZeroH) { IStation.Model.CurvePoint point = new IStation.Model.CurvePoint(0, 0); if (CurvePoints == null || CurvePoints.Count < 2) { return point; } if (simularPoint.X < CurvePoints.First().X) { return point; } if (simularPoint.X < 0.1) { return point; } double num = (simularPoint.Y - equipCurveZeroH) / (simularPoint.X * simularPoint.X); if (num < 0.0001) { GetSectPointLn(CurvePoints, simularPoint); } double num2 = 0.0; for (int i = 0; i < CurvePoints.Count - 1; i++) { CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out double k, out double b, 1E-10); b -= equipCurveZeroH; num2 = k * k + 4.0 * num * b; if (!(num2 < 0.0)) { double num3 = (k + Math.Sqrt(num2)) / (2.0 * num); if (IStation.Common.PointHelper.IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, num3)) { point.X = num3; point.Y = k * num3 + b + equipCurveZeroH; return point; } double num4 = (k - Math.Sqrt(num2)) / (2.0 * num); if (IStation.Common.PointHelper.IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, num4)) { point.X = num4; point.Y = k * num4 + b + equipCurveZeroH; return point; } } } return point; } /// /// /// /// /// /// protected static IStation.Model.CurvePoint GetSectPointLn(List CurvePoints, IStation.Model.CurvePoint simularPoint) { IStation.Model.CurvePoint featPoint = new IStation.Model.CurvePoint(0, 0); if (CurvePoints == null || CurvePoints.Count < 2) { return featPoint; } double num = Math.Log10(simularPoint.Y) / Math.Log10(simularPoint.X); if (num < 0.0001) { return featPoint; } var list = new List(); for (int i = 0; i < CurvePoints.Count; i++) { if (CurvePoints[i].X > 1.0) { list.Add(new IStation.Model.CurvePoint(Math.Log10(CurvePoints[i].X), Math.Log10(CurvePoints[i].Y))); } } for (int j = 0; j < list.Count - 1; j++) { CurveLineHelper.GetKandB(list[j], list[j + 1], out double k, out double b); if (!(Math.Abs(num - k) < 0.001)) { double num2 = b / (num - k); if (IStation.Common.PointHelper.IsMiddlePt(list[j].X, list[j + 1].X, num2)) { featPoint.X = Math.Pow(10.0, num2); featPoint.Y = Math.Pow(10.0, num * num2); return featPoint; } } } return featPoint; } } }