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;
}
}
}