using System;
|
using System.Collections.Generic;
|
using System.Linq;
|
|
namespace IStation.Model
|
{
|
public class CurvePointList : List<CurvePoint>, ICloneable
|
{
|
#region 构造函数
|
|
public CurvePointList()
|
{
|
}
|
public CurvePointList(IEnumerable<CurvePoint> points)
|
{
|
if (points == null || points.Count() == 0)
|
return;
|
foreach (CurvePoint item in points)
|
this.Add(item.Clone());
|
}
|
public CurvePointList(List<CurvePoint> points)
|
{
|
if (points == null || points.Count() == 0)
|
return;
|
foreach (CurvePoint item in points)
|
this.Add(item.Clone());
|
}
|
public CurvePointList(CurvePoint point)
|
{
|
if (point == null)
|
return;
|
|
this.Add(point.Clone());
|
}
|
public CurvePointList(CurvePointList rhs)
|
{
|
if (rhs == null)
|
return;
|
foreach (CurvePoint item in rhs)
|
this.Add(item.Clone());
|
}
|
|
|
public void ResetCurve(List<CurvePoint> points)
|
{
|
this.Clear();
|
foreach (CurvePoint item in points)
|
this.Add(item.Clone());
|
}
|
|
object ICloneable.Clone()
|
{
|
return this.Clone();
|
}
|
|
public CurvePointList Clone()
|
{
|
return new CurvePointList(this);
|
}
|
|
|
#endregion
|
|
//获得X值的坐标位置,可能有多个点(是线形插值,不是曲线上的点)
|
public List<double> GetInterPointY(double x)
|
{
|
if (this.Count == 0)
|
return null;
|
|
List<double> equalPoints = new List<double>();
|
int num = this.Count();
|
for (int i = 0; i < num - 1; i++)//少一个点
|
{
|
if ((x >= this[i].X && x <= this[i + 1].X) || (x <= this[i].X && x >= this[i + 1].X))
|
{//直线插值
|
double y;
|
if (Math.Abs(this[i].X - this[i + 1].X) < 0.01)
|
y = (this[i].Y + this[i + 1].Y) * 0.5;
|
else
|
y = this[i].Y + (this[i + 1].Y - this[i].Y) * (x - this[i].X) / (this[i + 1].X - this[i].X);
|
|
equalPoints.Add(y);
|
}
|
}
|
return equalPoints;
|
}
|
|
/// <summary>
|
/// 计算总长度
|
/// </summary>
|
/// <param name="points"></param>
|
/// <returns></returns>
|
public static double CalcToltalLength(List<CurvePoint> points)
|
{
|
double length = 0;
|
for (int i = 1; i < points.Count; i++)
|
{
|
double len = Math.Sqrt((points[i].X - points[i - 1].X) * (points[i].X - points[i - 1].X) + (points[i].Y - points[i - 1].Y) * (points[i].Y - points[i - 1].Y));
|
length += len;
|
}
|
|
return length;
|
}
|
public double TotalLength()
|
{
|
double length = 0;
|
for (int i = 1; i < this.Count; i++)
|
{
|
double len = Math.Sqrt((this[i].X - this[i - 1].X) * (this[i].X - this[i - 1].X) + (this[i].Y - this[i - 1].Y) * (this[i].Y - this[i - 1].Y));
|
length += len;
|
}
|
|
return length;
|
}
|
//结束的点序号
|
public double TotalLength(int EndPointIndex)
|
{
|
double length = 0;
|
int index_max = Math.Min(this.Count, EndPointIndex);
|
for (int i = 1; i < index_max; i++)
|
{
|
double len = Math.Sqrt((this[i].X - this[i - 1].X) * (this[i].X - this[i - 1].X) + (this[i].Y - this[i - 1].Y) * (this[i].Y - this[i - 1].Y));
|
length += len;
|
}
|
|
return length;
|
}
|
|
|
/// <summary>
|
/// 获取Y最大的点
|
/// </summary>
|
/// <returns></returns>
|
public IStation.Model.CurvePoint GetPointOfMaxY()
|
{
|
if (this.Count() == 0)
|
return null;
|
if (this.Count() == 1)
|
return this.First();
|
var maxY = (from x in this select x.Y).Max();
|
var pt = (from x in this where x.Y == maxY select x).FirstOrDefault();
|
if (pt == null)
|
return this.Last();
|
else
|
return pt;
|
}
|
/// <summary>
|
/// 获取Y最大的点
|
/// </summary>
|
/// <returns></returns>
|
public static IStation.Model.CurvePoint GetPointOfMaxY(IEnumerable<CurvePoint> points)
|
{
|
if (points == null)
|
return null;
|
if (points.Count() == 0)
|
return null;
|
if (points.Count() == 1)
|
return points.First();
|
var maxY = (from x in points select x.Y).Max();
|
var pt = (from x in points where x.Y == maxY select x).FirstOrDefault();
|
if (pt == null)
|
return points.Last();
|
else
|
return pt;
|
}
|
|
public static IStation.Model.CurvePoint GetMaxPointY(List<IStation.Model.CurvePoint> points)
|
{
|
if (points == null)
|
{
|
return new IStation.Model.CurvePoint(0, 0);
|
}
|
double maxPointX = points[0].X;
|
double maxPointY = points[0].Y;
|
for (int i = 1; i < points.Count(); i++)
|
{
|
if (points[i].Y > maxPointY)
|
{
|
maxPointX = points[i].X;
|
maxPointY = points[i].Y;
|
}
|
}
|
|
return new IStation.Model.CurvePoint(maxPointX, maxPointY);
|
}
|
/// <summary>
|
/// 获取Y最小的点的坐标
|
/// </summary>
|
/// <returns></returns>
|
public IStation.Model.CurvePoint GetPointOfMinY()
|
{
|
if (this.Count() == 0)
|
return null;
|
if (this.Count() == 1)
|
return this.First();
|
var minY = (from x in this select x.Y).Min();
|
var pt = (from x in this where x.Y == minY select x).FirstOrDefault();
|
if (pt == null)
|
return this.Last();
|
else
|
return pt;
|
}
|
/// <summary>
|
/// 获取Y最小的点的序号
|
/// </summary>
|
/// <returns></returns>
|
public int GetPointIndexOfMinY()
|
{
|
if (this.Count() == 0)
|
return 0;
|
if (this.Count() == 1)
|
return 0;
|
var minY = (from x in this select x.Y).Min();
|
var pt = (from x in this where x.Y == minY select x).FirstOrDefault();
|
if (pt == null)
|
return 0;
|
else
|
return this.IndexOf(pt);
|
}
|
|
/// <summary>
|
/// 序号
|
/// </summary>
|
/// <param name="x"></param>
|
/// <returns></returns>
|
public int IndexOfX(double x)
|
{
|
int index = 0;
|
foreach (var p in this)
|
{
|
if (Math.Abs(p.X - x) < 0.0001)
|
return index;
|
index++;
|
}
|
|
return -1;
|
}
|
|
|
|
|
/// <summary>
|
///
|
/// </summary>
|
/// <param name="index"></param>
|
/// <param name="relativePos"></param>
|
/// <returns></returns>
|
public int Move(int index, int relativePos)
|
{
|
if (index < 0 || index >= Count)
|
return -1;
|
|
CurvePoint graphObj = this[index];
|
this.RemoveAt(index);
|
|
index += relativePos;
|
if (index < 0)
|
index = 0;
|
if (index > Count)
|
index = Count;
|
|
Insert(index, graphObj);
|
return index;
|
}
|
|
|
|
|
|
|
|
|
/// <summary>
|
/// 判断X是否都一致
|
/// </summary>
|
/// <param name="point1"></param>
|
/// <param name="point2"></param>
|
/// <returns></returns>
|
public static bool IsEqualValueX(List<IStation.Model.CurvePoint> point1, List<IStation.Model.CurvePoint> point2)
|
{
|
if (point1 == null || point1.Count() == 0)
|
{
|
if (point2 == null || point2.Count() == 0)
|
{
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
if (point2 == null || point2.Count() == 0)
|
{
|
if (point1 == null || point1.Count() == 0)
|
{
|
return true;
|
}
|
else
|
{
|
return false;
|
}
|
}
|
if (point1.Count != point2.Count)
|
{
|
return false;
|
}
|
for (int i = 0; i < point1.Count; i++)
|
{
|
if (Math.Abs(point1[i].X - point2[i].X) > 0.001)
|
return false;
|
}
|
|
return true;
|
}
|
|
/// <summary>
|
/// CurvePointList 是一个多边形,判断点是否在多边形里
|
// 原理是 通过pt做一个+X方向的射线, 偶数个交点 就是在外部,奇数个就是在内部
|
/// </summary>
|
/// <param name="pt"></param>
|
/// <param name="isClose"></param>
|
/// <returns></returns>
|
public bool IsInPolygon(CurvePoint pt, bool isClose = true)
|
{
|
int crossNum = 0;
|
|
for (int i = 0; i < this.Count - 1; i++)
|
{
|
if (IsIntersectLeft(pt, this[i], this[i + 1]))
|
{
|
crossNum++;
|
}
|
}
|
|
if (isClose)
|
{
|
if (IsIntersectLeft(pt, this[this.Count - 1], this[0]))
|
{
|
crossNum++;
|
}
|
}
|
|
if ((crossNum % 2) == 0)
|
return false;
|
else
|
return true;
|
}
|
|
/// <summary>
|
/// 是否一个点向x轴的射线穿透线段,有交点且在线的左边
|
/// </summary>
|
/// <param name="basePoint"></param>
|
/// <param name="pt1"></param>
|
/// <param name="pt2"></param>
|
/// <returns></returns>
|
public static bool IsIntersectLeft(CurvePoint basePoint, CurvePoint pt1, CurvePoint pt2)
|
{
|
return IsIntersectLeft(basePoint.X, basePoint.Y, pt1.X, pt1.Y, pt2.X, pt2.Y);
|
}
|
|
public static bool IsIntersectLeft(double x, double y, double x1, double y1, double x2, double y2)
|
{
|
double maxY = y1 > y2 ? y1 : y2;
|
double minY = y1 > y2 ? y2 : y1;
|
|
if (Math.Abs(y2 - y1) < 0.0001)
|
{
|
if (Math.Abs(y - y1) < 0.0001)
|
return true;
|
else
|
return false;
|
}
|
|
|
bool IsInLine = false;
|
if (y < maxY && y >= minY)
|
{
|
if (x <= (x1 + (x2 - x1) * (y - y1) / (y2 - y1)))
|
{
|
IsInLine = true;
|
}
|
}
|
return IsInLine;
|
}
|
|
//获取X方向距离最小的点
|
public static CurvePoint GetClosestPointX(List<CurvePoint> points, double x)
|
{
|
if (points == null || points.Count() == 0)
|
return null;
|
IStation.Model.CurvePoint close_pt = points.FirstOrDefault();
|
double min_dis = Math.Abs(close_pt.X - x);
|
|
foreach (var pt in points)
|
{
|
var min_dis_current = Math.Abs(pt.X - x);
|
if (min_dis_current < min_dis)
|
{
|
min_dis = min_dis_current;
|
close_pt = pt;
|
}
|
}
|
|
return close_pt;
|
}
|
|
//获取X方向距离最小的点
|
public static int GetClosestPointX_Index(List<CurvePoint> points, double x)
|
{
|
if (points == null || points.Count() == 0)
|
return -1;
|
int index = 0;
|
double min_dis = Math.Abs(points[index].X - x);
|
|
for (int i = 0; i < points.Count; i++)
|
{
|
var pt = points[i];
|
var min_dis_current = Math.Abs(pt.X - x);
|
if (min_dis_current < min_dis)
|
{
|
min_dis = min_dis_current;
|
index = i;
|
}
|
}
|
|
return index;
|
}
|
}
|
}
|