namespace IStation.Curve { /// /// 抛物线 Parabola : H=K*Q^2 + S (流量扬程线) /// public class ParabolaCurveHelper { //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)) //曲线公式:H=K*Q^2+S (S就是equipCurveZeroH装置曲线静扬程) //equipCurveZeroH是装置曲线的静扬程,当Q=0时的扬程 public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH) { //if (curveExpress.FitType == eFitType.ThroughPoint) //{ // var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); // return GetSectPoint(points, simularPoint, equipCurveZeroH); //} //else { var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress); curveExpress2.Max = curveExpress2.Max * 1.2; var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50); return GetSectPoint(points, simularPoint, equipCurveZeroH); } } /// /// /// /// /// /// /// /// public static IStation.Curve.CurvePoint GetSectPoint(IStation.Curve.CurveExpress curveExpress, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH, double ratioExtend) { //if (curveExpress.FitType == eFitType.ThroughPoint) //{ // if (curveExpress.DefinePoints == null || curveExpress.DefinePoints.Count() < 3) // return null; // var points = IStation.Curve.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); // return GetSectPoint(points, simularPoint, equipCurveZeroH); //} //else { var curveExpress2 = new IStation.Curve.CurveExpress(curveExpress); curveExpress2.Max = curveExpress2.Max * ratioExtend; var points = IStation.Curve.FitHelper.GetFitPoints(curveExpress2, 50); //var points = IStation.Curve.FitHelper.GetFitPointsByExtend(curveExpress, ratioExtend, 50); return GetSectPoint(points, simularPoint, equipCurveZeroH); } } //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)) //曲线公式:H=K*Q^2+S (S就是equipCurveZeroH装置曲线静扬程) //S是装置曲线的静扬程,当Q=0时的扬程 public static IStation.Curve.CurvePoint GetSectPoint(List CurvePoints, IStation.Curve.CurvePoint simularPoint, double equipCurveZeroH) { IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0); if (CurvePoints == null || CurvePoints.Count < 2) return sectPoint; //if (simularPoint.X < CurvePoints.First().X) // return sectPoint; //if (DesignPoint.X > CurvePoints.Last().X) // return sectPoint; //计算抛物线的K (a) if (simularPoint.X < 0.1) {//X=0 return CurvePoints.First(); } if (simularPoint.Y < 0.01) {//Y=0 return CurvePoints.Last(); } double a = (simularPoint.Y - equipCurveZeroH) / (simularPoint.X * simularPoint.X); if (a < 0.0001) GetSectPointLn(CurvePoints, simularPoint); //2点连成直线与抛物线的交点,判断交点是否在2点之间,即可是曲线的交点 double b, c; double delta = 0; double x_j1, x_j2; for (int i = 0; i < CurvePoints.Count - 1; i++) { if (Math.Abs(CurvePoints[i].Y - CurvePoints[i + 1].Y) < 0.00001) {//水平的 x_j1 = Math.Sqrt((CurvePoints[i].Y - equipCurveZeroH) / a); if (CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1)) { sectPoint.X = x_j1; sectPoint.Y = CurvePoints[i].Y; return sectPoint; } } else { CurveLineHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c, 0.0000000001); c = c - equipCurveZeroH; //解方程 ax2-bx-c=0 delta = b * b + 4 * a * c; if (delta < 0) continue; x_j1 = (b + Math.Sqrt(delta)) / (2 * a); if (x_j1 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j1)) { sectPoint.X = x_j1; sectPoint.Y = b * x_j1 + c + equipCurveZeroH; return sectPoint; } x_j2 = (b - Math.Sqrt(delta)) / (2 * a); if (x_j2 >= 0 && CurvePoints[i].X.IsMiddle(CurvePoints[i + 1].X, x_j2)) { sectPoint.X = x_j2; sectPoint.Y = b * x_j2 + c + equipCurveZeroH; return sectPoint; } } } return sectPoint; } //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)):当流量特别大,H比较小时用 //曲线公式:H=K*Q^2,然后两边取对数 protected static IStation.Curve.CurvePoint GetSectPointLn(List CurvePoints, IStation.Curve.CurvePoint simularPoint) { IStation.Curve.CurvePoint sectPoint = new IStation.Curve.CurvePoint(0, 0); if (CurvePoints == null || CurvePoints.Count < 2) return sectPoint; //计算取对数后直线的K double a = Math.Log10(simularPoint.Y) / Math.Log10(simularPoint.X); if (a < 0.0001) return sectPoint; //所有的线上的点取对数 List CurvePointsLn = new List(); for (int i = 0; i < CurvePoints.Count; i++) { if (CurvePoints[i].X > 1)//防止第一个点:X=0 CurvePointsLn.Add(new IStation.Curve.CurvePoint(Math.Log10(CurvePoints[i].X), Math.Log10(CurvePoints[i].Y))); } //与2点连成直线的交点,判断交点是否在2点之间,即可是曲线的交点 double b, c; double x; for (int i = 0; i < CurvePointsLn.Count - 1; i++) { CurveLineHelper.GetKandB(CurvePointsLn[i], CurvePointsLn[i + 1], out b, out c); /*解方程 * y=ax * y=bx+c */ if (Math.Abs(a - b) < 0.001) continue; x = c / (a - b); if (CurvePointsLn[i].X.IsMiddle(CurvePointsLn[i + 1].X, x)) { sectPoint.X = Math.Pow(10, x); sectPoint.Y = Math.Pow(10, a * x); return sectPoint; } } return sectPoint; } } /// /// 抛物线 Parabola : y = K * Q^2 + B * Q; /// public class ParabolaECurveHelper { //任意两点 public static bool GetCurvePara(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, out double K, out double B) { //抛物线拟合 y=ax2+bx; double y1 = pt1.Y; double x1 = pt1.X; double y2 = pt2.Y; double x2 = pt2.X; K = (y1 * x2 - y2 * x1) / (x1 * x1 * x2 - x2 * x2 * x1); B = (y1 * x2 * x2 - y2 * x1 * x1) / (x1 * x2 * x2 - x2 * x1 * x1); return true; } //工作点和高效点 public static bool GetCurveParaByBEP(IStation.Curve.CurvePoint wrkPt, double bep_q, out double bep_eta, out double K, out double B) { //抛物线拟合 //思路 Y=0时, X=0或 -B/K //所以 bep_q = -B/K * 0.5 K = wrkPt.Y / (wrkPt.X * wrkPt.X - 2 * bep_q * wrkPt.X); B = -2 * K * bep_q; bep_eta = K * bep_q * bep_q + B * bep_q; //if (bep_eta > 0.95) //{ //} return true; } } /// /// 抛物线 Parabola : H = K * Q^2 (装置曲线) /// public class ParabolaZCurveHelper { private double _k = 0; public double GetK() { return _k; } public ParabolaZCurveHelper(IStation.Curve.CurvePoint pt) { this._k = pt.Y / pt.X / pt.X; } public ParabolaZCurveHelper(double x, double y) { this._k = y / x / x; } public double GetY(double x) { return x * x * this._k; } public double GetX(double y) { return Math.Sqrt(y * this._k); } //计算从x1到x2的弧长 public double CalcCurveLengthByX(double pt1_x, double pt2_x) { //思路是从按直线叠加 double x1 = pt1_x; double x2 = pt2_x; if (pt1_x > pt2_x) { x1 = pt2_x; x2 = pt1_x; } double space = (x2 - x1) / 1200; double x_last = x1; double y_last = GetY(x1); double total_length = 0; for (int i = 1; i <= 1200; i++) { double x = x1 + space * i; double y = GetY(x); double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; total_length += sub_length; } return total_length; } //计算点的位置, x1到x2弧长的摆放路 public IStation.Curve.CurvePoint CalcPointPosiByX(double x1, double x2, double length_ratio) { if (length_ratio < 0.001) { return new IStation.Curve.CurvePoint(x1, GetY(x1)); } //思路是从按直线叠加 int point_number = 1800; double space = (x2 - x1) / point_number; double x_last = x1; double y_last = GetY(x1); double total_length = 0; for (int i = 1; i <= point_number; i++) { double x = x1 + space * i; double y = GetY(x); double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; total_length += len; } double calc_length = total_length * length_ratio; double len2 = 0; x_last = x1; y_last = GetY(x1); for (int i = 1; i <= point_number; i++) { double x = x1 + space * i; double y = GetY(x); double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; len2 += len; if (len2 > calc_length) { return new IStation.Curve.CurvePoint(x, y); } } return new IStation.Curve.CurvePoint(x2, GetY(x2)); } public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio) { return CalcPointPosiByX(pt1.X, pt2.X, length_ratio); } //计算点x在弧长(x1->x2)中的百分率 public double CalcPointRatioByX(double x1, double x2, double x_center) { double length1 = CalcCurveLengthByX(x1, x2); double length2 = CalcCurveLengthByX(x1, x_center); return length2 / length1; } public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center) { double length1 = CalcCurveLengthByX(pt1.X, pt2.X); double length2 = CalcCurveLengthByX(pt1.X, x_center); return length2 / length1; } } /// /// 抛物线 Parabola : H = K * Q^2 (装置曲线) :图表法: 有时用QH差别比较大时, 用距离计算会有些问题 /// public class ParabolaZChartCurveHelper { private double _k = 1; private double _chartWidth = 1000; private double _chartHeight = 600; private double _ratio_scale_x = 1; private double _ratio_scale_y = 1; private double GetK() {//不对外 , 外部知道K 没有意义 return _k; } public ParabolaZChartCurveHelper(IStation.Curve.CurvePoint pt) { if (pt == null) return; this._ratio_scale_x = _chartWidth / pt.X; this._ratio_scale_y = _chartHeight / pt.Y; this._k = _chartHeight / _chartWidth / _chartWidth; } public ParabolaZChartCurveHelper(double x, double y) { this._ratio_scale_x = _chartWidth / x; this._ratio_scale_y = _chartHeight / y; this._k = _chartHeight / _chartWidth / _chartWidth; } private double GetY_chart(double x) { return x * x * this._k; } private double GetX_chart(double y) { return Math.Sqrt(y * this._k); } public double GetY(double x) { double chart_x = x * this._ratio_scale_x; var chart_y = chart_x * chart_x * this._k; return chart_y / this._ratio_scale_y; } //计算从x1到x2的弧长(注意时图表上的距离) public double CalcCurveLengthByX(double real_x_1, double real_x_2) { double pt1_x = real_x_1 * this._ratio_scale_x; double pt2_x = real_x_2 * this._ratio_scale_x; //思路是从按直线叠加 double x1 = pt1_x; double x2 = pt2_x; if (pt1_x > pt2_x) { x1 = pt2_x; x2 = pt1_x; } double space = (x2 - x1) / 1200; double x_last = x1; double y_last = GetY_chart(x1); double total_length = 0; for (int i = 1; i <= 1200; i++) { double x = x1 + space * i; double y = GetY_chart(x); double sub_length = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; total_length += sub_length; } return total_length; } private IStation.Curve.CurvePoint FromChartToReal(double chart_pt_x, double chart_pt_y) { return new IStation.Curve.CurvePoint(chart_pt_x / this._ratio_scale_x, chart_pt_y / this._ratio_scale_y); } //计算点的位置, x1到x2弧长的摆放路 public IStation.Curve.CurvePoint CalcPointPosiByX(double real_x_1, double real_x_2, double length_ratio) { double x1 = real_x_1 * this._ratio_scale_x; double x2 = real_x_2 * this._ratio_scale_x; if (length_ratio < 0.001) { return FromChartToReal(x1, GetY_chart(x1)); } //思路是从按直线叠加 int point_number = 1800; double space = (x2 - x1) / point_number; double x_last = x1; double y_last = GetY_chart(x1); double total_length = 0; for (int i = 1; i <= point_number; i++) { double x = x1 + space * i; double y = GetY_chart(x); double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; total_length += len; } double calc_length = total_length * length_ratio; double len2 = 0; x_last = x1; y_last = GetY_chart(x1); for (int i = 1; i <= point_number; i++) { double x = x1 + space * i; double y = GetY_chart(x); double len = Math.Sqrt((x - x_last) * (x - x_last) + (y - y_last) * (y - y_last)); x_last = x; y_last = y; len2 += len; if (len2 > calc_length) { return FromChartToReal(x, y); } } return FromChartToReal(x2, GetY_chart(x2)); } public IStation.Curve.CurvePoint CalcPointPosi(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double length_ratio) { return CalcPointPosiByX(pt1.X, pt2.X, length_ratio); } //计算点x在弧长(x1->x2)中的百分率 public double CalcPointRatioByX(double x1, double x2, double x_center) { double length1 = CalcCurveLengthByX(x1, x2); double length2 = CalcCurveLengthByX(x1, x_center); return length2 / length1; } public double CalcPointRatio(IStation.Curve.CurvePoint pt1, IStation.Curve.CurvePoint pt2, double x_center) { double length1 = CalcCurveLengthByX(pt1.X, pt2.X); double length2 = CalcCurveLengthByX(pt1.X, x_center); return length2 / length1; } } }