using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
|
namespace IStation.Model
|
{
|
/// <summary>
|
/// 曲线点列表拓展类
|
/// </summary>
|
public static class CurvePointList_Extensions
|
{
|
#region IEnumerable<CurvePoint>
|
|
/// <summary>
|
/// 获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
/// </summary>
|
public static List<double> GetInterPointY(this IEnumerable<CurvePoint> src_list, double x)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return default;
|
var list = src_list.ToList();
|
var equalPoints = new List<double>();
|
int num = src_list.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>
|
/// 计算总长度
|
/// </summary>
|
public static double CalcuTotalLength(this IEnumerable<CurvePoint> src_list)
|
{
|
if (src_list == null || src_list.Count() < 2)
|
return default;
|
var list = src_list.ToList();
|
double length = 0;
|
for (int i = 1; i < list.Count(); i++)
|
{
|
double len = Math.Sqrt((list[i].X - list[i - 1].X) * (list[i].X - list[i - 1].X) + (list[i].Y - list[i - 1].Y) * (list[i].Y - list[i - 1].Y));
|
length += len;
|
}
|
return length;
|
}
|
|
/// <summary>
|
/// 计算总长度 count(计算的点数量)
|
/// </summary>
|
public static double CalcuTotalLength(this IEnumerable<CurvePoint> src_list, int count)
|
{
|
if (src_list == null || src_list.Count() < 2)
|
return default;
|
var list = src_list.ToList();
|
int count_min = Math.Min(src_list.Count(), count);
|
double length = 0;
|
for (int i = 1; i < count_min; i++)
|
{
|
double len = Math.Sqrt((list[i].X - list[i - 1].X) * (list[i].X - list[i - 1].X) + (list[i].Y - list[i - 1].Y) * (list[i].Y - list[i - 1].Y));
|
length += len;
|
}
|
return length;
|
}
|
|
/// <summary>
|
/// 根据总长度获取点 超越总长度返回NULL
|
/// </summary>
|
public static CurvePoint GetPointByLength(this IEnumerable<CurvePoint> src_list, double length_from_start)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return default;
|
if (length_from_start < 0.0001)
|
{
|
return src_list.FirstOrDefault();
|
}
|
var list = src_list.ToList();
|
double length = 0;
|
for (int i = 1; i < list.Count; i++)
|
{
|
double len_line = Math.Sqrt((list[i].X - list[i - 1].X) * (list[i].X - list[i - 1].X) + (list[i].Y - list[i - 1].Y) * (list[i].Y - list[i - 1].Y));
|
length += len_line;
|
|
if (length >= length_from_start)
|
{
|
var extPt = new CurvePoint();
|
extPt.X = (list[i - 1].X - list[i].X) * (length - length_from_start) / len_line + list[i].X;
|
extPt.Y = (list[i - 1].Y - list[i].Y) * (length - length_from_start) / len_line + list[i].Y;
|
return extPt;
|
}
|
}
|
if (length >= length_from_start * 0.9999)
|
{
|
return list.LastOrDefault();
|
}
|
return default;
|
}
|
|
/// <summary>
|
/// 获取Y最大的点
|
/// </summary>
|
public static CurvePoint GetPointByMaxY(this IEnumerable<CurvePoint> src_list)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return default;
|
var y_max = src_list.Max(x => x.Y);
|
return (from x in src_list where x.Y == y_max select x).FirstOrDefault();
|
}
|
|
/// <summary>
|
/// 获取Y最小的点
|
/// </summary>
|
public static CurvePoint GetPointByMinY(this IEnumerable<CurvePoint> src_list)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return default;
|
var y_min = src_list.Min(x => x.Y);
|
return (from x in src_list where x.Y == y_min select x).FirstOrDefault();
|
}
|
|
/// <summary>
|
/// 获取Y最大的点索引
|
/// </summary>
|
public static int GetPointIndexByMaxY(this IEnumerable<CurvePoint> src_list)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return -1;
|
var y_max = src_list.Max(x => x.Y);
|
return src_list.ToList().FindIndex(x => x.Y == y_max);
|
}
|
|
/// <summary>
|
/// 获取Y最小的点索引
|
/// </summary>
|
public static int GetPointIndexByMinY(this IEnumerable<CurvePoint> src_list)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return -1;
|
var y_min = src_list.Min(x => x.Y);
|
return src_list.ToList().FindIndex(x => x.Y == y_min);
|
}
|
|
/// <summary>
|
/// 根据X 获取点索引
|
/// </summary>
|
public static int GetPointIndexByX(this IEnumerable<CurvePoint> src_list, double x)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return -1;
|
int index = 0;
|
foreach (var item in src_list)
|
{
|
if (Math.Abs(item.X - x) < 0.0001)
|
return index;
|
index++;
|
}
|
return -1;
|
}
|
|
/// <summary>
|
/// 转化为存储字符串
|
/// </summary>
|
public static string ToDsString(this IEnumerable<CurvePoint> src_list)
|
{
|
return CurvePoint.ToDsString(src_list);
|
}
|
|
/// <summary>
|
/// 移动点返回新的集合
|
/// </summary>
|
public static int MovePoint(this IEnumerable<CurvePoint> src_list, int index, int relative)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return -1;
|
if (index < 0 || index >= src_list.Count())
|
return -1;
|
var list = src_list.ToList();
|
var p = list.ElementAt(index);
|
list.RemoveAt(index);
|
index += relative;
|
if (index < 0)
|
index = 0;
|
if (index > list.Count)
|
index = list.Count;
|
list.Insert(index, p);
|
src_list = list;
|
return index;
|
}
|
|
/// <summary>
|
/// 获取X方向距离最小的点
|
/// </summary>
|
public static CurvePoint GetClosestPointByX(this IEnumerable<CurvePoint> list, double x)
|
{
|
if (list == null || list.Count() < 1)
|
return default;
|
CurvePoint p = null;
|
double min = double.MaxValue;
|
foreach (var item in list)
|
{
|
var min_temp = Math.Abs(item.X - x);
|
if (min_temp < min)
|
{
|
min = min_temp;
|
p = item;
|
}
|
}
|
return p;
|
}
|
|
/// <summary>
|
/// 获取X方向距离最小的点索引
|
/// </summary>
|
public static int GetClosestPointIndexByX(this IEnumerable<CurvePoint> list, double x)
|
{
|
if (list == null || list.Count() < 1)
|
return default;
|
int index = 0;
|
double min = double.MaxValue;
|
for (int i = 0; i < list.Count(); i++)
|
{
|
var item = list.ElementAt(i);
|
var min_temp = Math.Abs(item.X - x);
|
if (min_temp < min)
|
{
|
min = min_temp;
|
index = i;
|
}
|
}
|
return index;
|
}
|
|
/// <summary>
|
/// src_list 是一个多边形,判断点是否在多边形里
|
/// 原理是 通过p做一个+X方向的射线, 偶数个交点 就是在外部,奇数个就是在内部
|
/// </summary>
|
public static bool IsInPolygon(this IEnumerable<CurvePoint> src_list, CurvePoint p, bool isClosed = true)
|
{
|
if (src_list == null || src_list.Count() < 1)
|
return default;
|
var list = src_list.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;
|
}
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
}
|