namespace IStation.Curve
|
{
|
/// <summary>
|
/// 抛物线 Parabola : H=K*Q^2 + S (流量扬程线)
|
/// </summary>
|
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);
|
}
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="curveExpress"></param>
|
/// <param name="simularPoint"></param>
|
/// <param name="equipCurveZeroH"></param>
|
/// <param name="ratioExtend"></param>
|
/// <returns></returns>
|
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<IStation.Curve.CurvePoint> 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<IStation.Curve.CurvePoint> 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<IStation.Curve.CurvePoint> CurvePointsLn = new List<IStation.Curve.CurvePoint>();
|
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;
|
}
|
}
|
|
/// <summary>
|
/// 抛物线 Parabola : y = K * Q^2 + B * Q;
|
/// </summary>
|
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;
|
}
|
|
|
}
|
|
/// <summary>
|
/// 抛物线 Parabola : H = K * Q^2 (装置曲线)
|
/// </summary>
|
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;
|
}
|
|
}
|
|
/// <summary>
|
/// 抛物线 Parabola : H = K * Q^2 (装置曲线) :图表法: 有时用QH差别比较大时, 用距离计算会有些问题
|
/// </summary>
|
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;
|
}
|
|
}
|
|
}
|