namespace PBS.WinFrmUI.Hydro.Dispatch.Common { /// /// /// public class SimuSpeedCalcHelper { /// /// / /// /// /// /// /// /// public static Yw.Ahart.CubicCurve GetSimuPointQH(Yw.Ahart.CubicCurve 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 = OriginExpress.GetPointList(); foreach (Yw.Geometry.Point2d pt in curvePoints) { simularPoints.Add(new Yw.Geometry.Point2d( GetQ(pt.X, origin_speed, change_speed), GetH(pt.Y, origin_speed, change_speed))); } return FitHelper.BuildCurveExpress(curvePoints, OriginExpress.FitType); } /// /// /// /// /// /// /// /// public static Yw.Ahart.CubicCurve GetSimuPointQP(Yw.Ahart.CubicCurve OriginExpress, double origin, double change, int pointNum = 12) { if (OriginExpress == null) return null; var simularPoints = new List(); var curvePoints = OriginExpress.GetPointList(); foreach (Yw.Geometry.Point2d pt in curvePoints) { simularPoints.Add(new Yw.Geometry.Point2d( GetQ(pt.X, origin, change), GetP(pt.Y, origin, change))); } return new Yw.Ahart.CubicCurve(curvePoints, OriginExpress.FitType); } /// /// /// /// /// /// /// /// public static double GetSimuValue(ISupply.c.CurveExpress curveExpressQH, Yw.Geometry.Point2d 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 == ISupply.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 Yw.Geometry.Point2d GetSectPoint(CurveExpress CurveExpress, Yw.Geometry.Point2d simularPoint, double ratioIgnore) { return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore); } /// /// ratioIgnore:作用 当simularPoint超出范围时,扩大的倍数 /// /// /// /// /// /// public static Yw.Geometry.Point2d GetSectPointGeneral(Yw.Ahart.CubicCurve curveExpress, Yw.Geometry.Point2d simularPoint, double index, double ratioIgnore) { var sectPoint = new Yw.Geometry.Point2d(0, 0); if (curveExpress == null) return sectPoint; if (simularPoint.X < 1) return sectPoint; var CurveExpressEx = new Yw.Ahart.CubicCurve(curveExpress); //检查是否在曲线的区域范围内 double maxQ = CurveExpressEx.MaxX; double maxH = ISupply.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 = ISupply.Model.FitCurveHelper.GetFitPointY(CurveExpressEx, x); k = y / Math.Pow(x, index); } while (k > fixK); sectPoint.X = x; sectPoint.Y = y; return sectPoint; } /// /// /// /// /// /// protected static Yw.Geometry.Point2d GetSectPointLine(Yw.Ahart.CubicCurve curveExpress, Yw.Geometry.Point2d simularPoint) { var sectPoint = new Yw.Geometry.Point2d(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(ISupply.Model.FitCurveHelper.GetPointList(curveExpress, 100), simularPoint); } /// /// 通过点simularPoint和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0)) /// /// /// /// protected static Yw.Geometry.Point2d GetSectPointLine(List CurvePoints, Yw.Geometry.Point2d simularPoint) { var sectPoint = new Yw.Geometry.Point2d(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 (ISupply.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(Yw.Geometry.Point2d 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 = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0, 20); maxY = fitPointsByExtend.Max(x => x.Y); minY = fitPointsByExtend.Min(x => x.Y); return true; } /// /// /// /// /// /// /// public static bool GetMinMaxPointY(Yw.Ahart.CubicCurve curve, out double maxY, out double minY) { if (curve == null) { maxY = (minY = 0.0); return false; } var points = ISupply.Model.FitCurveHelper.GetPointList(curve); if (points == null) { maxY = (minY = 0.0); return false; } List fitPointsByExtend = ISupply.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0, 20); maxY = fitPointsByExtend.Max(x => x.Y); minY = fitPointsByExtend.Min(x => x.Y); return true; } /// /// /// /// /// /// public static Yw.Geometry.Point2d GetSectPointParabola(CurveExpress CurveExpress, Yw.Geometry.Point2d simularPoint) { Yw.Geometry.Point2d result = new Yw.Geometry.Point2d(0, 0); if (CurveExpress == null) { return result; } return GetSectPointParabola(FitCurveHelper.GetFitPointsByExtend(CurveExpress, 1.2, 50), simularPoint); } /// /// /// /// /// /// public static Yw.Geometry.Point2d GetSectPointParabola(List CurvePoints, Yw.Geometry.Point2d simularPoint) { return GetSectPoint(CurvePoints, simularPoint, 0.0); } /// /// /// /// /// /// /// public static Yw.Geometry.Point2d GetSectPoint(List CurvePoints, Yw.Geometry.Point2d simularPoint, double equipCurveZeroH) { Yw.Geometry.Point2d point = new Yw.Geometry.Point2d(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 (ISupply.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 (ISupply.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 Yw.Geometry.Point2d GetSectPointLn(List CurvePoints, Yw.Geometry.Point2d simularPoint) { Yw.Geometry.Point2d featPoint = new Yw.Geometry.Point2d(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 Yw.Geometry.Point2d(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 (ISupply.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; } } }