namespace Yw.Geometry { //抛物线 Parabola : H=K*Q^2 + S (流量扬程线) public class ParabolaCurveHelper { //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)) //曲线公式:H=K*Q^2+S (S就是equipuipCurveZeroH装置曲线静扬程) //equipuipCurveZeroH是装置曲线的静扬程,当Q=0时的扬程 public static Yw.Geometry.Point2d GetSectPoint(Yw.Geometry.CubicSpline2d curveExpress, Yw.Geometry.Point2d simularPoint, double equipuipCurveZeroH) { if (curveExpress == null) return null; //if (curveExpress.SplineType == eSpline2dType.) //{ // var points = Eventech.Common.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); // return GetSectPoint(points, simularPoint, equipuipCurveZeroH); //} //else { var points = curveExpress.GetPointListByXRange(curveExpress.MinX, curveExpress.MaxX * 1.2, 50); return GetSectPoint(points, simularPoint, equipuipCurveZeroH); } } // public static Yw.Geometry.Point2d GetSectPoint(Yw.Geometry.CubicSpline2d curveExpress, Yw.Geometry.Point2d simularPoint, double equipuipCurveZeroH, double ratioExtend) { if (curveExpress == null) return null; //if (curveExpress.CurveFitType == Model.eCurveFitType.ThroughPoint) //{ // if (curveExpress.DefinePoints == null || curveExpress.DefinePoints.Count() < 3) // return null; // var points = Eventech.Common.BezierCurveHelper.GetMultiplyPoints(curveExpress.DefinePoints, 3); // return GetSectPoint(points, simularPoint, equipuipCurveZeroH); //} //else { var points = curveExpress.GetPointListByXRange(curveExpress.MinX, curveExpress.MaxX * ratioExtend, 50); return GetSectPoint(points, simularPoint, equipuipCurveZeroH); } } //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)) //曲线公式:H=K*Q^2+S (S就是equipuipCurveZeroH装置曲线静扬程) //S是装置曲线的静扬程,当Q=0时的扬程 public static Yw.Geometry.Point2d GetSectPoint(List CurvePoints, Yw.Geometry.Point2d simularPoint, double equipuipCurveZeroH) { Yw.Geometry.Point2d sectPoint = new Yw.Geometry.Point2d(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 - equipuipCurveZeroH) / (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 - equipuipCurveZeroH) / a); if (IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, x_j1)) { sectPoint.X = x_j1; sectPoint.Y = CurvePoints[i].Y; return sectPoint; } } else { Yw.Geometry.Line2dHelper.GetKandB(CurvePoints[i], CurvePoints[i + 1], out b, out c, 0.0000000001); c = c - equipuipCurveZeroH; //解方程 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 && IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, x_j1)) { sectPoint.X = x_j1; sectPoint.Y = b * x_j1 + c + equipuipCurveZeroH; return sectPoint; } x_j2 = (b - Math.Sqrt(delta)) / (2 * a); if (x_j2 >= 0 && IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, x_j2)) { sectPoint.X = x_j2; sectPoint.Y = b * x_j2 + c + equipuipCurveZeroH; return sectPoint; } } } return sectPoint; } //判断 是否在2个数之间 public static bool IsMiddlePt(double pt1, double pt2, double p) { if (p > pt1 && p < pt2) return true; if (p < pt1 && p > pt2) return true; return false; } //通过点simularPoint和点(0,0)的抛物线,与曲线Curve的交点(没有,返回Point(0,0)):当流量特别大,H比较小时用 //曲线公式:H=K*Q^2,然后两边取对数 protected static Yw.Geometry.Point2d GetSectPointLn(List CurvePoints, Yw.Geometry.Point2d simularPoint) { Yw.Geometry.Point2d sectPoint = new Yw.Geometry.Point2d(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 Yw.Geometry.Point2d(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++) { Yw.Geometry.Line2dHelper.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 (IsMiddlePt(CurvePointsLn[i].X, 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 ParabolaCurveHelper_E //{ // //任意两点 // public static bool GetCurvePara(Yw.Geometry.Point2d pt1, Yw.Geometry.Point2d 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(Yw.Geometry.Point2d 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 ParabolaCurveHelper_Z //{ // private double _k = 0; // public double GetK() // { // return _k; // } // public ParabolaCurveHelper_Z(Yw.Geometry.Point2d pt) // { // this._k = pt.Y / pt.X / pt.X; // } // public ParabolaCurveHelper_Z(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 Yw.Geometry.Point2d CalcPointPosiByX(double x1, double x2, double length_ratio) // { // if (length_ratio < 0.001) // { // return new Yw.Geometry.Point2d(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 Yw.Geometry.Point2d(x, y); // } // } // return new Yw.Geometry.Point2d(x2, GetY(x2)); // } // public Yw.Geometry.Point2d CalcPointPosi(Yw.Geometry.Point2d pt1, Yw.Geometry.Point2d 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(Yw.Geometry.Point2d pt1, Yw.Geometry.Point2d 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 ParabolaCurveHelper_Z_4Chart //{ // 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 ParabolaCurveHelper_Z_4Chart(Yw.Geometry.Point2d 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 ParabolaCurveHelper_Z_4Chart(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 Yw.Geometry.Point2d FromChartToReal(double chart_pt_x, double chart_pt_y) // { // return new Yw.Geometry.Point2d(chart_pt_x / this._ratio_scale_x, chart_pt_y / this._ratio_scale_y); // } // //计算点的位置, x1到x2弧长的摆放路 // public Yw.Geometry.Point2d 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 Yw.Geometry.Point2d CalcPointPosi(Yw.Geometry.Point2d pt1, Yw.Geometry.Point2d 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(Yw.Geometry.Point2d pt1, Yw.Geometry.Point2d pt2, double x_center) // { // double length1 = CalcCurveLengthByX(pt1.X, pt2.X); // double length2 = CalcCurveLengthByX(pt1.X, x_center); // return length2 / length1; // } //} }