namespace IStation.Model
|
{
|
/// <summary>
|
/// 曲线拟合辅助类(维护在IStation.Common)
|
/// </summary>
|
public class FitCurveHelper
|
{
|
public FitCurveHelper(List<CurvePoint> points)
|
{
|
_ifitCurvePoint = new TwinRelateCurve3M(points);
|
}
|
public FitCurveHelper(List<CurvePoint> points, eCurveFitType fitType)
|
{
|
switch (fitType)
|
{
|
case eCurveFitType.ThroughPoint: _ifitCurvePoint = new TwinRelateCurve0(points); break;
|
case eCurveFitType.LinearCurve: _ifitCurvePoint = new TwinRelateCurve1(points); break;
|
case eCurveFitType.ConicCurveB0: _ifitCurvePoint = new TwinRelateCurve2B0(points); break;
|
case eCurveFitType.ConicCurve: _ifitCurvePoint = new TwinRelateCurve2M(points); break;
|
case eCurveFitType.CubicCurve: _ifitCurvePoint = new TwinRelateCurve3M(points); break;
|
case eCurveFitType.FourM: _ifitCurvePoint = new TwinRelateCurve4M(points); break;
|
default: break;
|
}
|
}
|
public FitCurveHelper(List<CurvePoint> points, int fitPow)
|
{
|
switch (fitPow)
|
{
|
case 0: _ifitCurvePoint = new TwinRelateCurve0(points); break;
|
case 1: _ifitCurvePoint = new TwinRelateCurve1(points); break;
|
case 2: _ifitCurvePoint = new TwinRelateCurve2M(points); break;
|
case 3: _ifitCurvePoint = new TwinRelateCurve3M(points); break;
|
case 4: _ifitCurvePoint = new TwinRelateCurve4M(points); break;
|
default: break;
|
}
|
}
|
public FitCurveHelper(CurveExpress express)
|
{
|
switch (express.FitType)
|
{
|
case eCurveFitType.ThroughPoint: _ifitCurvePoint = new TwinRelateCurve0(express); break;
|
case eCurveFitType.LinearCurve: _ifitCurvePoint = new TwinRelateCurve1(express); break;
|
case eCurveFitType.ConicCurveB0: _ifitCurvePoint = new TwinRelateCurve2B0(express); break;
|
case eCurveFitType.ConicCurve: _ifitCurvePoint = new TwinRelateCurve2M(express); break;
|
case eCurveFitType.CubicCurve: _ifitCurvePoint = new TwinRelateCurve3M(express); break;
|
case eCurveFitType.FourM: _ifitCurvePoint = new TwinRelateCurve4M(express); break;
|
default: break;
|
}
|
}
|
|
private IFitCurvePoint _ifitCurvePoint = null;//拟合点接口对象
|
|
#region 创建曲线表达式
|
|
/// <summary>
|
/// 创建曲线表达式
|
/// </summary>
|
public static CurveExpress BuildCurveExpress(List<CurvePoint> points, eCurveFitType fitType)
|
{
|
if (points == null)
|
return default;
|
if (points.Count < 1)
|
return default;
|
switch (fitType)
|
{
|
case eCurveFitType.ThroughPoint: return TwinRelateCurve0.BuildCurveExpress(points);
|
case eCurveFitType.LinearCurve: return TwinRelateCurve1.BuildCurveExpress(points);
|
case eCurveFitType.ConicCurveB0: return TwinRelateCurve2B0.BuildCurveExpress(points);
|
case eCurveFitType.ConicCurve: return TwinRelateCurve2M.BuildCurveExpress(points);
|
case eCurveFitType.CubicCurve: return TwinRelateCurve3M.BuildCurveExpress(points);
|
case eCurveFitType.FourM: return TwinRelateCurve4M.BuildCurveExpress(points);
|
default: return default;
|
}
|
}
|
|
/// <summary>
|
/// 创建曲线表达式
|
/// </summary>
|
public static CurveExpress BuildCurveExpress(List<CurvePoint> points, int fitPow)
|
{
|
var fitType = CurveExpress.GetFitType(fitPow);
|
return BuildCurveExpress(points, fitType);
|
}
|
|
#endregion
|
|
#region 获取零点的Y值
|
|
/// <summary>
|
/// 获取零点的Y值
|
/// </summary>
|
public static double GetZeroPointY(CurveExpress express)
|
{
|
return express.Index0;
|
}
|
|
/// <summary>
|
/// 获取零点的Y值 2022_03_17_nsx
|
/// </summary>
|
public static double GetZeroPointY(List<Model.CurvePoint> points)
|
{
|
var express = new CurveExpress(points);
|
return express.Index0;
|
}
|
|
#endregion
|
|
#region 获取线性插值
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):不延长
|
/// </summary>
|
public static List<CurvePoint> GetInterPointY(List<CurvePoint> points, double x)
|
{
|
if (points == null || points.Count() == 0)
|
return default;
|
|
var equalPoints = new List<CurvePoint>();
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
equalPoints.Add(new CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点,取第一个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
/// <param name="points"></param>
|
/// <param name="x"></param>
|
/// <param name="y"></param>
|
/// <returns></returns>
|
public static bool GetInterPointY(List<IStation.Model.CurvePoint> points, double x, out double y)
|
{
|
y = 0;
|
if (points == null)
|
return false;
|
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
return true;
|
}
|
}
|
return false;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):会延长
|
/// </summary>
|
public static List<CurvePoint> GetInterPointYByExtend(List<CurvePoint> points, double x)
|
{
|
if (points == null || points.Count() == 0)
|
return null;
|
var equalPoints = new List<CurvePoint>();
|
|
if (x <= points.First().X)
|
{//暂时不延长,只相同,以后可以继续优化
|
equalPoints.Add(points.First());
|
|
return equalPoints;
|
}
|
if (x >= points.Last().X)
|
{
|
equalPoints.Add(points.Last());
|
|
return equalPoints;
|
}
|
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
equalPoints.Add(new CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点,取第一个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static bool GetFirstInterPointY(List<CurvePoint> points, double x, out double y)
|
{
|
y = 0;
|
if (points == null)
|
return false;
|
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
return true;
|
}
|
}
|
return false;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点,取第一个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static double GetFirstInterPointY(List<CurvePoint> points, double x)
|
{
|
if (points == null || points.Count < 1)
|
return default;
|
for (int i = 0; i < points.Count - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
return y;
|
}
|
}
|
return default;
|
}
|
|
|
//获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):会延长
|
public static IStation.Model.CurvePointList GetInterPointY_Extend(List<IStation.Model.CurvePoint> points, double x)
|
{
|
if (points == null || points.Count() == 0)
|
return null;
|
IStation.Model.CurvePointList equalPoints = new IStation.Model.CurvePointList();
|
|
if (x <= points.First().X)
|
{//暂时不延长,只相同,以后可以继续优化
|
equalPoints.Add(points.First());
|
|
return equalPoints;
|
}
|
if (x >= points.Last().X)
|
{
|
equalPoints.Add(points.Last());
|
|
return equalPoints;
|
}
|
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= points[i].X && x <= points[i + 1].X) || (x <= points[i].X && x >= points[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(points[i].X - points[i + 1].X) < 0.01)
|
y = (points[i].Y + points[i + 1].Y) * 0.5;
|
else
|
y = points[i].Y + (points[i + 1].Y - points[i].Y) * (x - points[i].X) / (points[i + 1].X - points[i].X);
|
|
equalPoints.Add(new IStation.Model.CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
|
#endregion
|
|
#region 获取拟合点
|
|
/// <summary>
|
/// 获取曲线拟合点Y值
|
/// </summary>
|
public double GetFitPointY(double x)
|
{
|
if (_ifitCurvePoint == null)
|
return default;
|
return _ifitCurvePoint.GetFitPointY(x);
|
}
|
|
/// <summary>
|
/// 获取拟合点列表
|
/// </summary>
|
public List<CurvePoint> GetFitPoints(int pointNumber)
|
{
|
if (_ifitCurvePoint == null)
|
return default;
|
return _ifitCurvePoint.GetFitPoints(pointNumber);
|
}
|
|
/// <summary>
|
/// 通过区间获取拟合点列表
|
/// </summary>
|
public List<CurvePoint> GetFitPointsByRange(double x_min, double x_max, int pointNumber)
|
{
|
if (_ifitCurvePoint == null)
|
return default;
|
return _ifitCurvePoint.GetFitPointsByRange(x_min, x_max, pointNumber);
|
}
|
|
|
/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(List<CurvePoint> points, int fitPow, double x)
|
{
|
if (points == null || points.Count < fitPow + 1)
|
return default;
|
var helper = new FitCurveHelper(points, fitPow);
|
return helper.GetFitPointY(x);
|
}
|
|
|
/*/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(List<CurvePoint> points, eCurveFitType fitType, double x)
|
{
|
if (points == null)
|
return default;
|
var fitPow = CurveExpress.GetFitPow(fitType);
|
if (points.Count < fitPow + 1)
|
return default;
|
var helper = new FitCurveHelper(points, fitType);
|
return helper.GetFitPointY(x);
|
}*/
|
|
/// <summary>
|
/// 获取
|
/// </summary>
|
/// <param name="points"></param>
|
/// <param name="curveFitType"></param>
|
/// <param name="x"></param>
|
/// <returns></returns>
|
|
public static double GetFitPointY(List<CurvePoint> points, eCurveFitType curveFitType, double x)
|
{
|
if (points == null)
|
return 0;
|
if (curveFitType == eCurveFitType.ThroughPoint)
|
{
|
if (points.Count() < 3)
|
return 0;
|
var bbb = BezierCurveHelper.CreateOpenCurves(points);
|
var ppp = BezierCurveHelper.GetSectPointsByX(bbb, x);
|
if (ppp == null || ppp.Count() == 0)
|
return 0;
|
return ppp.Last().Y;
|
}
|
else if (curveFitType == eCurveFitType.ConicCurve || curveFitType == eCurveFitType.ConicCurveB0)
|
{
|
if (points.Count() < 3)
|
return 0;
|
CurveExpress express = new CurveExpress(points, curveFitType, false);
|
return TwinRelateCurve2M.GetFitPointY(express, x);
|
}
|
else if (curveFitType == eCurveFitType.CubicCurve)
|
{
|
if (points.Count() <= 3)
|
return 0;
|
CurveExpress express = new CurveExpress(points, curveFitType, false);
|
return TwinRelateCurve3M.GetFitPointY(express, x);
|
}
|
else if (curveFitType == eCurveFitType.FourM)
|
{
|
if (points.Count() <= 4)
|
return 0;
|
CurveExpress express = new CurveExpress(points, curveFitType, false);
|
return TwinRelateCurve4M.GetFitPointY(express, x);
|
}
|
else
|
{
|
if (points.Count() <= 3)
|
return 0;
|
CurveExpress express = new CurveExpress(points, curveFitType, false);
|
return TwinRelateCurve3M.GetFitPointY(express, x);
|
}
|
}
|
|
|
/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(CurveExpress express, double x)
|
{
|
if (express == null)
|
return default;
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPointY(x);
|
}
|
|
/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(string strExpress, double x)
|
{
|
if (string.IsNullOrEmpty(strExpress))
|
return default;
|
var express = new CurveExpress(strExpress);
|
if (express.IsNull)
|
return default;
|
return GetFitPointY(express, x);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPoints(List<CurvePoint> points, int pointNumber = 20)
|
{
|
if (points == null)
|
return default;
|
var express = new CurveExpress(points);
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPoints(pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPoints(List<CurvePoint> points, eCurveFitType fitType, int pointNumber = 20)
|
{
|
if (points == null)
|
return default;
|
var express = new CurveExpress(points, fitType);
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(points, fitType);
|
return helper.GetFitPoints(pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPoints(string strExpress, int point_number = 20)
|
{
|
if (string.IsNullOrEmpty(strExpress))
|
return default;
|
var express = new CurveExpress(strExpress);
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPoints(point_number);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPoints(CurveExpress express, int pointNumber = 20)
|
{
|
if (express == null)
|
return default;
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPoints(pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByExtend(CurveExpress express, double ratioExtend, int pointNumber)
|
{
|
if (express == null)
|
return default;
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPointsByRange(express.Min, express.Max * ratioExtend, pointNumber);
|
}
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByExtend2(CurveExpress express, double ratioExtendmin, double ratioExtendmax, int pointNumber)
|
{
|
if (express == null)
|
return default;
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPointsByRange(express.Min * ratioExtendmin, express.Max * ratioExtendmax, pointNumber);
|
}
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByExtend(List<CurvePoint> points, eCurveFitType fitType, double ratioExtend, int pointNumber)
|
{
|
if (points == null)
|
return default;
|
var fitPow = CurveExpress.GetFitPow(fitType);
|
if (points.Count < fitPow + 1)
|
return default;
|
var express = new CurveExpress(points, fitType);
|
return GetFitPointsByExtend(express, ratioExtend, pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByExtend(List<CurvePoint> points, double ratioExtend, int pointNumber)
|
{
|
if (points == null)
|
return default;
|
var fitPow = CurveExpress.GetFitPow(eCurveFitType.CubicCurve);
|
if (points.Count < fitPow + 1)
|
return default;
|
if (pointNumber == 0)
|
{
|
pointNumber = points.Count();
|
}
|
var curveExpress = new CurveExpress(points);
|
return GetFitPointsByExtend(curveExpress, ratioExtend, pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByRange(CurveExpress express, double minX, double maxX, int pointNumber = 20)
|
{
|
if (express == null)
|
return default;
|
if (express.IsNull)
|
return default;
|
var helper = new FitCurveHelper(express);
|
return helper.GetFitPointsByRange(minX, maxX, pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByRange(List<CurvePoint> points, double minX, double maxX, int pointNumber = 20)
|
{
|
if (points == null)
|
return default;
|
var express = new CurveExpress(points);
|
if (express.IsNull)
|
return default;
|
return GetFitPointsByRange(express, minX, maxX, pointNumber);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByRange(List<CurvePoint> points, eCurveFitType fitType, double minX, double maxX, int pointNumber = 20)
|
{
|
if (points == null)
|
return default;
|
var express = new CurveExpress(points, fitType);
|
if (express.IsNull)
|
return default;
|
return GetFitPointsByRange(express, minX, maxX, pointNumber);
|
}
|
|
|
|
#endregion
|
|
#region 获得X值
|
|
//获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):会计算延长部分:而且要求points点按照从小到大排序
|
public static IStation.Model.CurvePointList GetInterPointExX(List<IStation.Model.CurvePoint> points, double y)
|
{
|
if (points == null)
|
return null;
|
|
//在范围内
|
double maxY = (from yyy in points select yyy.Y).Max();
|
double minY = (from yyy in points select yyy.Y).Min();
|
if (y > minY && y < maxY)
|
{
|
return GetInterPointX(points, y);
|
}
|
|
IStation.Model.CurvePointList ptList = new IStation.Model.CurvePointList();
|
|
//判断是否在前面的延长部分
|
double x_start = IStation.Model.CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y);
|
if (x_start <= points[0].X)
|
{
|
if (x_start > 0 && x_start > points[0].X * 0.9)//放一点余量
|
ptList.Add(new IStation.Model.CurvePoint(x_start, y));
|
}
|
|
//判断是否在后面的延长部分:U型曲线 是前后都有
|
double x_end = IStation.Model.CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y);
|
if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * 1.1)//放一点余量
|
{
|
ptList.Add(new IStation.Model.CurvePoint(x_end, y));
|
}
|
|
if (ptList.Count == 0)
|
return null;
|
return ptList;
|
}
|
|
//获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):会计算延长部分:而且要求points点按照从小到大排序
|
public static IStation.Model.CurvePointList GetInterPointExX(IStation.Model.CurveExpress curve, double y, int interPointNum)
|
{
|
if (curve == null)
|
return null;
|
var points = IStation.Model.FitCurveHelper.GetFitPoints(curve, interPointNum);
|
if (points == null)
|
return null;
|
|
//在范围内
|
double maxY = (from yyy in points select yyy.Y).Max();
|
double minY = (from yyy in points select yyy.Y).Min();
|
if (y > minY && y < maxY)
|
{
|
return GetInterPointX(points, y);
|
}
|
|
IStation.Model.CurvePointList ptList = new IStation.Model.CurvePointList();
|
|
//判断是否在前面的延长部分
|
double x_start = IStation.Model.CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y);
|
if (x_start <= points[0].X)
|
{
|
if (x_start > 0 && x_start > points[0].X * 0.9)//放一点余量
|
ptList.Add(new IStation.Model.CurvePoint(x_start, y));
|
}
|
|
//判断是否在后面的延长部分:U型曲线 是前后都有
|
double x_end = IStation.Model.CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y);
|
if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * 1.1)//放一点余量
|
{
|
ptList.Add(new IStation.Model.CurvePoint(x_end, y));
|
}
|
|
if (ptList.Count == 0)
|
return null;
|
return ptList;
|
}
|
|
//获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点):会计算延长部分:而且要求points点按照从小到大排序
|
public static IStation.Model.CurvePointList GetInterPointExX(IStation.Model.CurveExpress curve, double y, int interPointNum, double extendRatio)
|
{
|
if (curve == null)
|
return null;
|
var points = IStation.Model.FitCurveHelper.GetFitPointsByExtend(curve, extendRatio, interPointNum);
|
if (points == null)
|
return null;
|
|
//在范围内
|
double maxY = (from yyy in points select yyy.Y).Max();
|
double minY = (from yyy in points select yyy.Y).Min();
|
if (y > minY && y < maxY)
|
{
|
return GetInterPointX(points, y);
|
}
|
|
IStation.Model.CurvePointList ptList = new IStation.Model.CurvePointList();
|
|
//判断是否在前面的延长部分
|
double x_start = IStation.Model.CurveLineHelper.GetXbyY(points[0].X, points[0].Y, points[1].X, points[1].Y, y);
|
if (x_start <= points[0].X)
|
{
|
if (x_start > 0 && x_start > points[0].X * 0.9)//放一点余量
|
ptList.Add(new IStation.Model.CurvePoint(x_start, y));
|
}
|
|
//判断是否在后面的延长部分:U型曲线 是前后都有
|
double x_end = IStation.Model.CurveLineHelper.GetXbyY(points[points.Count - 2].X, points[points.Count - 2].Y, points[points.Count - 1].X, points[points.Count - 1].Y, y);
|
if (x_end >= points[points.Count - 1].X && x_end < points[points.Count - 1].X * extendRatio)//放一点余量
|
{
|
ptList.Add(new IStation.Model.CurvePoint(x_end, y));
|
}
|
|
if (ptList.Count == 0)
|
return null;
|
return ptList;
|
}
|
|
//获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
public static IStation.Model.CurvePointList GetInterPointX(List<IStation.Model.CurvePoint> points, double y)
|
{
|
if (points == null)
|
return null;
|
|
IStation.Model.CurvePointList equalPoints = new IStation.Model.CurvePointList();
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((y >= points[i].Y && y <= points[i + 1].Y) || (y <= points[i].Y && y >= points[i + 1].Y))
|
{
|
//直线插值
|
double x;
|
if (Math.Abs(points[i].Y - points[i + 1].Y) < 0.01)
|
x = (points[i].X + points[i + 1].X) * 0.5;
|
else
|
x = points[i].X + (points[i + 1].X - points[i].X) * (y - points[i].Y) / (points[i + 1].Y - points[i].Y);
|
|
equalPoints.Add(new IStation.Model.CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
//获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
//interPointNum数量越多,精度越高,注意如果点在最高点附近,interPointNum值一定要多
|
public static IStation.Model.CurvePointList GetInterPointX(IStation.Model.CurveExpress points, double y, int interPointNum = 50)
|
{
|
if (points == null)
|
return null;
|
|
return GetInterPointX(GetFitPoints(points, interPointNum), y);
|
}
|
|
//获得Y值的坐标位置,可能有多个点,取第一个点(是线形插值,不是曲线上的点)
|
public static bool GetInterPointX(List<IStation.Model.CurvePoint> points, double y, out double x)
|
{
|
x = 0;
|
if (points == null)
|
return false;
|
|
int num = points.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((y >= points[i].Y && y <= points[i + 1].Y) || (y <= points[i].Y && y >= points[i + 1].Y))
|
{//直线插值
|
if (Math.Abs(points[i].Y - points[i + 1].Y) < 0.01)
|
x = (points[i].X + points[i + 1].X) * 0.5;
|
else
|
x = points[i].X + (points[i + 1].X - points[i].X) * (y - points[i].Y) / (points[i + 1].Y - points[i].Y);
|
|
return true;
|
}
|
}
|
|
return true;
|
}
|
|
#endregion 获得X值
|
|
|
|
#region 取Y的最大最小值
|
|
//
|
public static bool GetMinMaxPointY(List<IStation.Model.CurvePoint> points, out double maxY, out double minY)
|
{
|
if (points == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
var fitPoints = GetFitPoints(points, 50);
|
if (fitPoints == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
|
maxY = (from x in fitPoints select x.Y).Max();
|
minY = (from x in fitPoints select x.Y).Min();
|
return true;
|
}
|
|
public static bool GetMinMaxPointY(CurveExpress express, out double maxY, out double minY)
|
{
|
if (express == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
var fitPoints = GetFitPoints(express, 50);
|
if (fitPoints == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
maxY = (from x in fitPoints select x.Y).Max();
|
minY = (from x in fitPoints select x.Y).Min();
|
return true;
|
}
|
|
|
|
//伸长率
|
public static bool GetMinMaxPointY_Ratio(CurveExpress express, double extend_min_ratio, double extend_max_ratio, out double maxY, out double minY)
|
{
|
if (express == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
var fitPoints = GetFitPointsByExtend2(express, extend_min_ratio, extend_max_ratio, 50);
|
if (fitPoints == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
maxY = (from x in fitPoints select x.Y).Max();
|
minY = (from x in fitPoints select x.Y).Min();
|
return true;
|
}
|
//绝对值
|
public static bool GetMinMaxPointY_Range(CurveExpress express, double xRangeMin, double xRangeMax, out double maxY, out double minY)
|
{
|
if (express == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
if (xRangeMin >= xRangeMax)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
var fitPoints = GetFitPointsByRange(express, xRangeMin, xRangeMax, 50);
|
if (fitPoints == null)
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
maxY = (from x in fitPoints select x.Y).Max();
|
minY = (from x in fitPoints select x.Y).Min();
|
return true;
|
}
|
|
|
|
//获取Y值最大值的点
|
public static IStation.Model.CurvePoint GetMaxPoint(CurveExpress express, int pointNumber = 200)
|
{
|
if (express == null)
|
return null;
|
if (express.FitPow <= 0 && express.DefinePoints != null)
|
{
|
return CurvePointList.GetPointOfMaxY(express.DefinePoints);
|
}
|
else if (express.FitType == eCurveFitType.ThroughPoint)
|
{
|
return CurvePointList.GetPointOfMaxY(express.DefinePoints);
|
}
|
else
|
{
|
var points = GetFitPoints(express, pointNumber);
|
return CurvePointList.GetPointOfMaxY(points);
|
}
|
}
|
//绝对值
|
public static IStation.Model.CurvePoint GetMaxPointByRange(CurveExpress express, double range_min, double range_max, int pointNumber = 200)
|
{
|
if (express == null)
|
return null;
|
var points = GetFitPointsByRange(express, range_min, range_max, pointNumber);
|
return CurvePointList.GetPointOfMaxY(points);
|
}
|
|
//取points中Y的最大值(一定在points中)
|
public static IStation.Model.CurvePoint GetMaxPointInPoints(List<IStation.Model.CurvePoint> points)
|
{
|
if (points == null)
|
{
|
return new IStation.Model.CurvePoint(0, 0);
|
}
|
double maxPointX = -10000;
|
double maxPointY = -10000;
|
for (int i = 0; i < points.Count(); i++)
|
{
|
if (points[i].Y > maxPointY)
|
{
|
maxPointX = points[i].X;
|
maxPointY = points[i].Y;
|
}
|
}
|
|
return new IStation.Model.CurvePoint(maxPointX, maxPointY);
|
}
|
|
#endregion 取Y的最大最小值
|
|
|
//冒泡升序排序
|
public static void Sort(ref double[] arrX, ref double[] arrY)
|
{
|
int i, j;
|
double tempX, tempY;
|
bool done = false;
|
j = 1;
|
while ((j < arrX.Length) && (!done))//判断长度
|
{
|
done = true;
|
for (i = 0; i < arrX.Length - j; i++)
|
{
|
if (arrX[i] > arrX[i + 1])
|
{
|
done = false;
|
tempX = arrX[i]; tempY = arrY[i];
|
arrX[i] = arrX[i + 1]; arrY[i] = arrY[i + 1];//交换数据
|
arrX[i + 1] = tempX; arrY[i + 1] = tempY;
|
}
|
}
|
j++;
|
}
|
}
|
|
//曲线方程字符
|
public static string GetCurveFunction(CurveExpress express, string xName = "Q")
|
{
|
if (express == null)
|
return null;
|
return express.GetCurveFunction(xName);
|
}
|
|
public static string GetCurveFunctionRtf(CurveExpress express, string xName = "Q")
|
{
|
if (express == null)
|
return null;
|
|
//0次方
|
double index0 = express.Index0;
|
//1次方
|
double index1 = express.Index1;
|
//2次方
|
double index2 = express.Index2;
|
//3次方
|
double index3 = express.Index3;
|
|
|
#region 拆分系数
|
//double firstCoeff = 0;
|
//int firstIndex = 0;
|
//double secondCoeff = 0;
|
//int secondIndex = 0;
|
double thirdCoeff = 0;
|
int thirdIndex = 0;
|
double lastCoeff = 0;
|
int lastIndex = 0;
|
|
|
|
// GetFuncScientificValue(0, index0, ref firstCoeff, ref firstIndex);
|
|
// GetFuncScientificValue(1, index1, ref secondCoeff, ref secondIndex);
|
|
GetFuncScientificValue(2, index2, ref thirdCoeff, ref thirdIndex);
|
|
GetFuncScientificValue(3, index3, ref lastCoeff, ref lastIndex);
|
|
#endregion
|
|
StringBuilder sb = new StringBuilder();
|
#region 设置系数及运算符号
|
|
sb.Append(index0.ToString("0.0"));
|
sb.Append(" ");
|
|
if (index1 > 0)
|
{
|
sb.Append(" + ");
|
sb.Append(index1.ToString("0.00000"));
|
}
|
else
|
{
|
sb.Append(" - ");
|
sb.Append(Math.Abs(index1).ToString("0.00000"));
|
}
|
|
//sb.Append(@"\'d710\super");
|
//sb.Append(secondIndex);
|
//sb.Append(@"\nosupersub ");
|
sb.Append(@" \'d7 ");
|
sb.Append(xName);
|
sb.Append(" ");
|
|
|
if (thirdCoeff > 0)
|
{
|
sb.Append(" + ");
|
sb.Append(thirdCoeff.ToString("0.0000000000"));
|
}
|
else
|
{
|
sb.Append(" - ");
|
sb.Append(Math.Abs(thirdCoeff).ToString("0.0000000000"));
|
}
|
sb.Append(@" \'d7 10\super ");
|
sb.Append(thirdIndex);
|
sb.Append(@" \nosupersub ");
|
sb.Append(@" \'d7 "); sb.Append(xName);
|
sb.Append(@"\super 2 "); sb.Append(@"\nosupersub ");
|
|
|
if (lastCoeff > 0)
|
{
|
sb.Append(" + ");
|
sb.Append(lastCoeff.ToString("0.00000000000000"));
|
}
|
else
|
{
|
sb.Append(" - ");
|
sb.Append(Math.Abs(lastCoeff).ToString("0.00000000000000"));
|
}
|
|
sb.Append(@" \'d7 10\super ");
|
sb.Append(lastIndex);
|
sb.Append(@" \nosupersub ");
|
sb.Append(@" \'d7 "); sb.Append(xName);
|
sb.Append(@"\super 3 "); sb.Append(@"\nosupersub ");
|
|
#endregion
|
|
return sb.ToString();
|
}
|
private static void GetFuncScientificValue(int FunctionIndex,
|
double FunctionCoeff, ref double signValue, ref int indexValue)
|
{
|
string strList = "";
|
if (FunctionIndex == 0)
|
{
|
strList = FunctionCoeff.ToString("0.000e+000");
|
}
|
else if (FunctionIndex == 1)
|
{
|
strList = FunctionCoeff.ToString("0.0000000e+000");
|
}
|
else if (FunctionIndex == 2)
|
{
|
strList = FunctionCoeff.ToString("#.##########e+000");
|
}
|
else if (FunctionIndex == 3)
|
{
|
strList = FunctionCoeff.ToString("#.#############e+000");
|
}
|
string[] st1 = null;
|
st1 = strList.Split('e');
|
signValue = Convert.ToDouble(st1[0]);
|
indexValue = Convert.ToInt32(st1[1]);
|
}
|
|
public static string GetCurveFunction(List<CurvePoint> pointsInfoList, string xName = "Q")
|
{
|
if (pointsInfoList == null)
|
return null;
|
CurveExpress express = new CurveExpress(pointsInfoList);
|
return express.GetCurveFunction(xName);
|
}
|
|
public static string GetCurveFunctionRtf(List<CurvePoint> pointsInfoList, string xName = "Q")
|
{
|
if (pointsInfoList == null)
|
return null;
|
CurveExpress express = new CurveExpress(pointsInfoList);
|
return GetCurveFunctionRtf(express, xName);
|
}
|
|
|
|
|
|
}
|
}
|