using IStation.Model;
|
using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
using System.Text;
|
using System.Threading.Tasks;
|
|
namespace IStation.Calculation.DispatchAna.Common
|
{
|
/// <summary>
|
///
|
/// </summary>
|
public class SimuSpeedCalcHelper
|
{
|
/// <summary>
|
/// /
|
/// </summary>
|
/// <param name="OriginExpress"></param>
|
/// <param name="origin_speed"></param>
|
/// <param name="change_speed"></param>
|
/// <param name="pointNum"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurveExpress GetSimuPointQH(IStation.Model.CurveExpress 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<IStation.Model.CurvePoint>();
|
var curvePoints = IStation.Model.FitCurveHelper.GetFitPoints(OriginExpress);
|
foreach (IStation.Model.CurvePoint pt in curvePoints)
|
{
|
simularPoints.Add(new IStation.Model.CurvePoint(
|
GetQ(pt.X, origin_speed, change_speed),
|
GetH(pt.Y, origin_speed, change_speed)));
|
}
|
return new IStation.Model.CurveExpress(curvePoints, OriginExpress.FitType);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="OriginExpress"></param>
|
/// <param name="origin"></param>
|
/// <param name="change"></param>
|
/// <param name="pointNum"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurveExpress GetSimuPointQP(IStation.Model.CurveExpress OriginExpress, double origin, double change, int pointNum = 12)
|
{
|
if (OriginExpress == null)
|
return null;
|
|
var simularPoints = new List<IStation.Model.CurvePoint>();
|
var curvePoints = IStation.Model.FitCurveHelper.GetFitPoints(OriginExpress);
|
foreach (IStation.Model.CurvePoint pt in curvePoints)
|
{
|
simularPoints.Add(new IStation.Model.CurvePoint(
|
GetQ(pt.X, origin, change),
|
GetP(pt.Y, origin, change)));
|
}
|
|
return new IStation.Model.CurveExpress(curvePoints, OriginExpress.FitType);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="curveExpressQH"></param>
|
/// <param name="simularPoint"></param>
|
/// <param name="originValue"></param>
|
/// <param name="extendRatio"></param>
|
/// <returns></returns>
|
public static double GetSimuValue(IStation.Model.CurveExpress curveExpressQH, IStation.Model.CurvePoint 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 == IStation.Model.eCurveFitType.ThroughPoint)
|
{
|
}
|
//计算交点位置参数
|
var sectPoint = GetSectPoint(curveExpressQH, simularPoint, extendRatio);
|
if (sectPoint == null || IsZeroPoint(sectPoint))
|
return -5;
|
|
//计算相似点的转速/直径
|
return GetSimuByH(originValue, sectPoint.Y, simularPoint.Y);
|
}
|
|
/// <summary>
|
/// ratioIgnore:作用 当simularPoint超出曲线范围时,曲线扩大的倍数
|
/// </summary>
|
/// <param name="CurveExpress"></param>
|
/// <param name="simularPoint"></param>
|
/// <param name="ratioIgnore"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetSectPoint(CurveExpress CurveExpress, IStation.Model.CurvePoint simularPoint, double ratioIgnore)
|
{
|
return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore);
|
}
|
|
/// <summary>
|
/// ratioIgnore:作用 当simularPoint超出范围时,扩大的倍数
|
/// </summary>
|
/// <param name="curveExpress"></param>
|
/// <param name="simularPoint"></param>
|
/// <param name="index"></param>
|
/// <param name="ratioIgnore"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetSectPointGeneral(IStation.Model.CurveExpress curveExpress, IStation.Model.CurvePoint simularPoint, double index, double ratioIgnore)
|
{
|
var sectPoint = new IStation.Model.CurvePoint(0, 0);
|
if (curveExpress == null)
|
return sectPoint;
|
|
if (simularPoint.X < 1)
|
return sectPoint;
|
var CurveExpressEx = new IStation.Model.CurveExpress(curveExpress);
|
//检查是否在曲线的区域范围内
|
double maxQ = CurveExpressEx.Max;
|
double maxH = IStation.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 = IStation.Model.FitCurveHelper.GetFitPointY(CurveExpressEx, x);
|
k = y / Math.Pow(x, index);
|
} while (k > fixK);
|
|
sectPoint.X = x;
|
sectPoint.Y = y;
|
return sectPoint;
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="curveExpress"></param>
|
/// <param name="simularPoint"></param>
|
/// <returns></returns>
|
protected static IStation.Model.CurvePoint GetSectPointLine(IStation.Model.CurveExpress curveExpress, IStation.Model.CurvePoint simularPoint)
|
{
|
var sectPoint = new IStation.Model.CurvePoint(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(IStation.Model.FitCurveHelper.GetFitPoints(curveExpress, 100), simularPoint);
|
}
|
|
/// <summary>
|
/// 通过点simularPoint和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0))
|
/// </summary>
|
/// <param name="CurvePoints"></param>
|
/// <param name="simularPoint"></param>
|
/// <returns></returns>
|
protected static IStation.Model.CurvePoint GetSectPointLine(List<IStation.Model.CurvePoint> CurvePoints, IStation.Model.CurvePoint simularPoint)
|
{
|
var sectPoint = new IStation.Model.CurvePoint(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 (IStation.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;
|
/// <summary>
|
///
|
/// </summary>
|
/// <returns></returns>
|
public static double GetIndexQ() { return _speedIndexQ; }
|
|
private static double _speedIndexH = 2;
|
/// <summary>
|
///
|
/// </summary>
|
/// <returns></returns>
|
public static double GetIndexH() { return _speedIndexH; }
|
|
/// <summary>
|
/// 知道原始速度和改变后的速度,求原始流量originQ对应改变后的流量
|
/// </summary>
|
/// <param name="originQ"></param>
|
/// <param name="originN"></param>
|
/// <param name="changeN"></param>
|
/// <returns></returns>
|
public static double GetQ(double originQ, double originN, double changeN)
|
{
|
double ratio = originN / changeN;
|
return originQ / ratio;
|
}
|
|
/// <summary>
|
/// 知道原始速度和改变后的速度,求原始扬程originH对应改变后的扬程
|
/// </summary>
|
/// <param name="originH"></param>
|
/// <param name="originN"></param>
|
/// <param name="changeN"></param>
|
/// <returns></returns>
|
public static double GetH(double originH, double originN, double changeN)
|
{
|
double ratio = Math.Pow(originN / changeN, _speedIndexH);
|
return originH / ratio;
|
}
|
/// <summary>
|
/// 知道原始速度和改变后的速度,求原始功率originP对应改变后的功率
|
/// </summary>
|
/// <param name="originP"></param>
|
/// <param name="originN"></param>
|
/// <param name="changeN"></param>
|
/// <returns></returns>
|
public static double GetP(double originP, double originN, double changeN)
|
{
|
double ratio = Math.Pow(originN / changeN, _speedIndexH + _speedIndexQ);
|
return originP / ratio;
|
}
|
/// <summary>
|
/// 知道原始速度和改变后的速度,求原始效率originE对应改变后的效率
|
/// </summary>
|
/// <param name="originE"></param>
|
/// <param name="originN"></param>
|
/// <param name="changeN"></param>
|
/// <returns></returns>
|
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);
|
}
|
|
/// <summary>
|
/// 知道原始速度,以及原始的杨程H以及对应的变速后的杨程,求变速后的速度
|
/// </summary>
|
/// <param name="originSpeend"></param>
|
/// <param name="originH"></param>
|
/// <param name="changeH"></param>
|
/// <returns></returns>
|
public static double GetSimuByH(double originSpeend, double originH, double changeH)
|
{
|
double ratio = Math.Pow(originH / changeH, 1 / _speedIndexH);
|
return originSpeend / ratio;
|
}
|
#endregion
|
|
/// <summary>
|
/// 判断是否是0点,用于判断函数是否成功返回
|
/// </summary>
|
/// <param name="pt"></param>
|
/// <returns></returns>
|
public static bool IsZeroPoint(IStation.Model.CurvePoint pt)
|
{
|
if (pt.X < 0.01 && pt.Y < 0.01)
|
return true;
|
else
|
return false;
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="points"></param>
|
/// <param name="maxY"></param>
|
/// <param name="minY"></param>
|
/// <returns></returns>
|
public static bool GetMinMaxPointY(List<IStation.Model.CurvePoint> points, out double maxY, out double minY)
|
{
|
if (points == null)
|
{
|
maxY = (minY = 0.0);
|
return false;
|
}
|
|
List<IStation.Model.CurvePoint> fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0);
|
maxY = fitPointsByExtend.Max(x => x.Y);
|
minY = fitPointsByExtend.Min(x => x.Y);
|
return true;
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="curve"></param>
|
/// <param name="maxY"></param>
|
/// <param name="minY"></param>
|
/// <returns></returns>
|
public static bool GetMinMaxPointY(IStation.Model.CurveExpress curve, out double maxY, out double minY)
|
{
|
if (curve == null)
|
{
|
maxY = (minY = 0.0);
|
return false;
|
}
|
var points = IStation.Model.FitCurveHelper.GetFitPoints(curve);
|
if (points == null)
|
{
|
maxY = (minY = 0.0);
|
return false;
|
}
|
|
List<IStation.Model.CurvePoint> fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0);
|
maxY = fitPointsByExtend.Max(x => x.Y);
|
minY = fitPointsByExtend.Min(x => x.Y);
|
return true;
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="CurveExpress"></param>
|
/// <param name="simularPoint"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetSectPointParabola(CurveExpress CurveExpress, IStation.Model.CurvePoint simularPoint)
|
{
|
IStation.Model.CurvePoint result = new IStation.Model.CurvePoint(0, 0);
|
if (CurveExpress == null)
|
{
|
return result;
|
}
|
|
return GetSectPointParabola(FitCurveHelper.GetFitPointsByExtend(CurveExpress, 1.2, 50), simularPoint);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="CurvePoints"></param>
|
/// <param name="simularPoint"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetSectPointParabola(List<IStation.Model.CurvePoint> CurvePoints, IStation.Model.CurvePoint simularPoint)
|
{
|
return GetSectPoint(CurvePoints, simularPoint, 0.0);
|
}
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="CurvePoints"></param>
|
/// <param name="simularPoint"></param>
|
/// <param name="equipCurveZeroH"></param>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetSectPoint(List<IStation.Model.CurvePoint> CurvePoints, IStation.Model.CurvePoint simularPoint, double equipCurveZeroH)
|
{
|
IStation.Model.CurvePoint point = new IStation.Model.CurvePoint(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 (IStation.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 (IStation.Common.PointHelper.IsMiddlePt(CurvePoints[i].X, CurvePoints[i + 1].X, num4))
|
{
|
point.X = num4;
|
point.Y = k * num4 + b + equipCurveZeroH;
|
return point;
|
}
|
}
|
}
|
return point;
|
}
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="CurvePoints"></param>
|
/// <param name="simularPoint"></param>
|
/// <returns></returns>
|
protected static IStation.Model.CurvePoint GetSectPointLn(List<IStation.Model.CurvePoint> CurvePoints, IStation.Model.CurvePoint simularPoint)
|
{
|
IStation.Model.CurvePoint featPoint = new IStation.Model.CurvePoint(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<IStation.Model.CurvePoint>();
|
for (int i = 0; i < CurvePoints.Count; i++)
|
{
|
if (CurvePoints[i].X > 1.0)
|
{
|
list.Add(new IStation.Model.CurvePoint(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 (IStation.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;
|
}
|
|
|
}
|
}
|