using IStation.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IStation.Calculation.DispatchAna.Common
{
///
///
///
public class SimuSpeedCalcHelper
{
///
/// /
///
///
///
///
///
///
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();
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);
}
///
///
///
///
///
///
///
///
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();
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);
}
///
///
///
///
///
///
///
///
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);
}
///
/// ratioIgnore:作用 当simularPoint超出曲线范围时,曲线扩大的倍数
///
///
///
///
///
public static IStation.Model.CurvePoint GetSectPoint(CurveExpress CurveExpress, IStation.Model.CurvePoint simularPoint, double ratioIgnore)
{
return GetSectPointGeneral(CurveExpress, simularPoint, 2, ratioIgnore);
}
///
/// ratioIgnore:作用 当simularPoint超出范围时,扩大的倍数
///
///
///
///
///
///
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;
}
///
///
///
///
///
///
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);
}
///
/// 通过点simularPoint和点(0,0)的直线,与曲线Curve的交点(没有,返回Point(0,0))
///
///
///
///
protected static IStation.Model.CurvePoint GetSectPointLine(List 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;
///
///
///
///
public static double GetIndexQ() { return _speedIndexQ; }
private static double _speedIndexH = 2;
///
///
///
///
public static double GetIndexH() { return _speedIndexH; }
///
/// 知道原始速度和改变后的速度,求原始流量originQ对应改变后的流量
///
///
///
///
///
public static double GetQ(double originQ, double originN, double changeN)
{
double ratio = originN / changeN;
return originQ / ratio;
}
///
/// 知道原始速度和改变后的速度,求原始扬程originH对应改变后的扬程
///
///
///
///
///
public static double GetH(double originH, double originN, double changeN)
{
double ratio = Math.Pow(originN / changeN, _speedIndexH);
return originH / ratio;
}
///
/// 知道原始速度和改变后的速度,求原始功率originP对应改变后的功率
///
///
///
///
///
public static double GetP(double originP, double originN, double changeN)
{
double ratio = Math.Pow(originN / changeN, _speedIndexH + _speedIndexQ);
return originP / ratio;
}
///
/// 知道原始速度和改变后的速度,求原始效率originE对应改变后的效率
///
///
///
///
///
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);
}
///
/// 知道原始速度,以及原始的杨程H以及对应的变速后的杨程,求变速后的速度
///
///
///
///
///
public static double GetSimuByH(double originSpeend, double originH, double changeH)
{
double ratio = Math.Pow(originH / changeH, 1 / _speedIndexH);
return originSpeend / ratio;
}
#endregion
///
/// 判断是否是0点,用于判断函数是否成功返回
///
///
///
public static bool IsZeroPoint(IStation.Model.CurvePoint pt)
{
if (pt.X < 0.01 && pt.Y < 0.01)
return true;
else
return false;
}
///
///
///
///
///
///
///
public static bool GetMinMaxPointY(List points, out double maxY, out double minY)
{
if (points == null)
{
maxY = (minY = 0.0);
return false;
}
List fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0);
maxY = fitPointsByExtend.Max(x => x.Y);
minY = fitPointsByExtend.Min(x => x.Y);
return true;
}
///
///
///
///
///
///
///
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 fitPointsByExtend = IStation.Model.FitCurveHelper.GetFitPointsByExtend(points, 50.0);
maxY = fitPointsByExtend.Max(x => x.Y);
minY = fitPointsByExtend.Min(x => x.Y);
return true;
}
///
///
///
///
///
///
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);
}
///
///
///
///
///
///
public static IStation.Model.CurvePoint GetSectPointParabola(List CurvePoints, IStation.Model.CurvePoint simularPoint)
{
return GetSectPoint(CurvePoints, simularPoint, 0.0);
}
///
///
///
///
///
///
///
public static IStation.Model.CurvePoint GetSectPoint(List 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;
}
///
///
///
///
///
///
protected static IStation.Model.CurvePoint GetSectPointLn(List 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();
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;
}
}
}