namespace IStation.Curve
|
{
|
public static class CurvePoint_Extensions
|
{
|
|
#region Point
|
|
/// <summary>
|
/// 判断是否是0点,用于判断函数是否成功返回
|
/// </summary>
|
public static bool IsZeroPoint(this CurvePoint pt)
|
{
|
if (pt.X < 0.01 && pt.Y < 0.01)
|
return true;
|
else
|
return false;
|
}
|
|
/// <summary>
|
/// 点到线的距离
|
/// </summary>
|
public static double GetDistance(this CurvePoint pt1, List<CurvePoint> CurvePoints)
|
{
|
if (CurvePoints == null)
|
return 10000;
|
|
double min_dis = double.MaxValue;
|
double dis = 0;
|
foreach (CurvePoint pt in CurvePoints)
|
{
|
dis = GetDistance(pt1, pt);
|
if (dis < min_dis)
|
min_dis = dis;
|
}
|
|
return min_dis;
|
}
|
|
/// <summary>
|
/// 两点之间的距离
|
/// </summary>
|
public static double GetDistance(CurvePoint pt1, CurvePoint pt2)
|
{
|
return Math.Sqrt((pt1.X - pt2.X) * (pt1.X - pt2.X) + (pt1.Y - pt2.Y) * (pt1.Y - pt2.Y));
|
}
|
|
|
/// <summary>
|
/// 计算总长度
|
/// </summary>
|
public static double CalcuTotalLength(this List<CurvePoint> ptList)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
double length = 0;
|
for (int i = 1; i < ptList.Count; i++)
|
{
|
length += ptList[i].Distance(ptList[i - 1]);
|
}
|
return length;
|
}
|
|
#endregion
|
|
#region List<CurvePoint>
|
|
/// <summary>
|
/// 获取Y最小的点
|
/// </summary>
|
public static CurvePoint GetPointByMinY(this List<CurvePoint> ptList)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
return ptList.OrderBy(x => x.Y).FirstOrDefault();
|
}
|
|
/// <summary>
|
/// 获取Y最大的点
|
/// </summary>
|
public static CurvePoint GetPointByMaxY(this List<CurvePoint> ptList)
|
{
|
if (ptList == null || !ptList.Any())
|
{
|
return default;
|
}
|
return ptList.OrderBy(x => x.Y).LastOrDefault();
|
}
|
|
/// <summary>
|
/// 获取Y最小的点索引
|
/// </summary>
|
public static int GetPointIndexByMinY(this List<CurvePoint> ptList)
|
{
|
var pt = GetPointByMinY(ptList);
|
return ptList.IndexOf(pt);
|
}
|
|
/// <summary>
|
/// 获取Y最大的点索引
|
/// </summary>
|
public static int GetPointIndexByMaxY(this List<CurvePoint> ptList)
|
{
|
var pt = GetPointByMaxY(ptList);
|
return ptList.IndexOf(pt);
|
}
|
|
/// <summary>
|
/// 根据X 获取点索引
|
/// </summary>
|
public static int GetPointIndexByX(this List<CurvePoint> ptList, double x)
|
{
|
if (ptList == null || !ptList.Any())
|
{
|
return -1;
|
}
|
int index = 0;
|
foreach (var pt in ptList)
|
{
|
if (Math.Abs(pt.X - x) < 0.0001)
|
{
|
return index;
|
}
|
index++;
|
}
|
return -1;
|
}
|
|
/// <summary>
|
/// 获取X方向距离最小的点
|
/// </summary>
|
public static CurvePoint GetClosestPointByX(this List<CurvePoint> ptList, double x)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
var pt = ptList.OrderBy(t => Math.Abs(t.X - x)).FirstOrDefault();
|
return pt;
|
}
|
|
/// <summary>
|
/// 获取X方向距离最小的点索引
|
/// </summary>
|
public static int GetClosestPointIndexByX(this List<CurvePoint> ptList, double x)
|
{
|
var pt = GetClosestPointByX(ptList, x);
|
return ptList.IndexOf(pt);
|
}
|
|
|
/// <summary>
|
/// 获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static List<double> GetInterPointX(this List<CurvePoint> ptList, double y)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
var list = ptList.ToList();
|
var equalPoints = new List<double>();
|
int num = list.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y))
|
{//直线插值
|
double x;
|
if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01)
|
x = (list[i].X + list[i + 1].X) * 0.5;
|
else
|
x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y);
|
|
equalPoints.Add(x);
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 获得Y值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static List<CurvePoint> GetPointsByInterPointX(this List<CurvePoint> ptList, double y)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
var list = ptList.ToList();
|
var equalPoints = new List<CurvePoint>();
|
int num = list.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((y >= list[i].Y && y <= list[i + 1].Y) || (y <= list[i].Y && y >= list[i + 1].Y))
|
{//直线插值
|
double x;
|
if (Math.Abs(list[i].Y - list[i + 1].Y) < 0.01)
|
x = (list[i].X + list[i + 1].X) * 0.5;
|
else
|
x = list[i].X + (list[i + 1].X - list[i].X) * (y - list[i].Y) / (list[i + 1].Y - list[i].Y);
|
|
equalPoints.Add(new CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static List<double> GetInterPointY(this List<CurvePoint> ptList, double x)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
var list = ptList.ToList();
|
var equalPoints = new List<double>();
|
int num = ptList.Count;
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(list[i].X - list[i + 1].X) < 0.01)
|
y = (list[i].Y + list[i + 1].Y) * 0.5;
|
else
|
y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X);
|
|
equalPoints.Add(y);
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static List<CurvePoint> GetPointsByInterPointY(this List<CurvePoint> ptList, double x)
|
{
|
if (ptList == null || ptList.Count < 1)
|
{
|
return default;
|
}
|
var list = ptList.ToList();
|
var equalPoints = new List<CurvePoint>();
|
int num = ptList.Count;
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= list[i].X && x <= list[i + 1].X) || (x <= list[i].X && x >= list[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(list[i].X - list[i + 1].X) < 0.01)
|
y = (list[i].Y + list[i + 1].Y) * 0.5;
|
else
|
y = list[i].Y + (list[i + 1].Y - list[i].Y) * (x - list[i].X) / (list[i + 1].X - list[i].X);
|
|
equalPoints.Add(new CurvePoint(x, y));
|
}
|
}
|
return equalPoints;
|
}
|
|
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点,取第一个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static bool GetInterPointY(this 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>
|
/// ptList 是一个多边形,判断点是否在多边形里
|
/// 原理是 通过p做一个+X方向的射线, 偶数个交点 就是在外部,奇数个就是在内部
|
/// </summary>
|
public static bool IsInPolygon(this IEnumerable<CurvePoint> ptList, CurvePoint p, bool isClosed = true)
|
{
|
if (ptList == null || ptList.Count() < 1)
|
return default;
|
var list = ptList.ToList();
|
int crossNum = 0;
|
|
for (int i = 0; i < list.Count() - 1; i++)
|
{
|
if (p.IsIntersectLineLeft(list[i], list[i + 1]))
|
{
|
crossNum++;
|
}
|
}
|
|
if (isClosed)
|
{
|
if (p.IsIntersectLineLeft(list[list.Count - 1], list[0]))
|
{
|
crossNum++;
|
}
|
}
|
|
if ((crossNum % 2) == 0)
|
return false;
|
else
|
return true;
|
}
|
|
/// <summary>
|
/// 是否完全相同
|
/// </summary>
|
public static bool IsEqualValueX(this List<CurvePoint> ptList, List<CurvePoint> comparerPtList)
|
{
|
if (ptList == null || ptList.Count() == 0)
|
{
|
if (comparerPtList == null || comparerPtList.Count() == 0)
|
{
|
return true;
|
}
|
|
return false;
|
}
|
|
if (comparerPtList == null || comparerPtList.Count() == 0)
|
{
|
if (ptList == null || ptList.Count() == 0)
|
{
|
return true;
|
}
|
|
return false;
|
}
|
|
if (ptList.Count != comparerPtList.Count)
|
{
|
return false;
|
}
|
|
for (int i = 0; i < ptList.Count; i++)
|
{
|
if (Math.Abs(ptList[i].X - comparerPtList[i].X) > 0.001)
|
{
|
return false;
|
}
|
}
|
|
return true;
|
}
|
|
|
#region 获取拟合点
|
|
/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(this List<CurvePoint> ptList, double x)
|
{
|
if (ptList == null)
|
return default;
|
var express = FitHelper.BuildCurveExpress(ptList, eFitType.CubicCurve);
|
if (express == null)
|
return default;
|
return express.GetFitPointY(x);
|
}
|
|
/// <summary>
|
/// 获取拟合点Y
|
/// </summary>
|
public static double GetFitPointY(this List<CurvePoint> ptList, eFitType fitType, double x)
|
{
|
if (ptList == null)
|
return default;
|
var express = FitHelper.BuildCurveExpress(ptList, fitType);
|
if (express == null)
|
return default;
|
return express.GetFitPointY(x);
|
}
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPoints(this List<CurvePoint> ptList, eFitType fitType = eFitType.CubicCurve, int pointNumber = 20)
|
{
|
if (ptList == null)
|
return default;
|
var express = FitHelper.BuildCurveExpress(ptList, fitType);
|
if (express == null)
|
return default;
|
return express.GetFitPoints(pointNumber);
|
}
|
|
|
/// <summary>
|
/// 获取拟合点
|
/// </summary>
|
public static List<CurvePoint> GetFitPointsByExtend(this List<CurvePoint> ptList, eFitType fitType, double ratioExtend, int pointNumber = 20)
|
{
|
if (ptList == null)
|
return default;
|
var fitPow = FitHelper.GetFitPow(fitType);
|
if (ptList.Count < fitPow + 1)
|
return default;
|
var express = FitHelper.BuildCurveExpress(ptList, fitType);
|
return express.GetFitPointsByExtend(ratioExtend, pointNumber);
|
}
|
|
#endregion
|
|
#region 取Y的最大最小值
|
|
|
/// <summary>
|
/// 取Y的最大最小值
|
/// </summary>
|
public static bool GetMinMaxPointY(this List<CurvePoint> ptList, out double maxY, out double minY)
|
{
|
if (ptList == null || !ptList.Any())
|
{
|
maxY = minY = 0;
|
return false;
|
}
|
var fitPoints = ptList.ToList();
|
maxY = fitPoints.Max(x => x.Y);
|
minY = fitPoints.Min(x => x.Y); ;
|
return true;
|
}
|
|
/// <summary>
|
/// 取points中Y的最大值(一定在points中)
|
/// </summary>
|
public static CurvePoint GetMaxPointY(this List<CurvePoint> ptList)
|
{
|
if (ptList == null || !ptList.Any())
|
{
|
return new CurvePoint(0, 0);
|
}
|
return ptList.OrderByDescending(x => x.Y).First();
|
}
|
|
#endregion 取Y的最大最小值
|
|
|
#endregion
|
}
|
}
|