namespace IStation.Curve
{
///
/// 曲线直线
///
public class CurveLine : ICloneable
{
///
///
///
public CurveLine() { }
///
///
///
public CurveLine(double x1, double y1, double x2, double y2)
{
this.Point0 = new CurvePoint(x1, y1);
this.Point1 = new CurvePoint(x2, y2);
}
///
///
///
public CurveLine(CurvePoint pt1, CurvePoint pt2)
{
this.Point0 = pt1;
this.Point1 = pt2;
}
///
///
///
public CurveLine(List pts)
{
if (pts == null || pts.Count < 2)
{
throw new Exception("参数错误,无法解析出直线!");
}
this.Point0 = pts[0];
this.Point1 = pts[1];
}
///
///
///
public CurveLine(CurveLine rhs)
{
this.Point0 = new CurvePoint(rhs.Point0);
this.Point1 = new CurvePoint(rhs.Point1);
}
///
/// 第一个点
///
public CurvePoint Point0 { get; set; }
///
/// 第二个点
///
public CurvePoint Point1 { get; set; }
///
/// 获取插值Y
///
public double GetInsertY(double x)
{
if (Math.Abs(this.Point1.X - this.Point0.X) < 0.000001)
{
return 0;
}
if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001)
{
return 0;
}
return this.Point0.Y + (this.Point1.Y - this.Point0.Y) / (this.Point1.X - this.Point0.X) * (x - this.Point0.X);
}
///
/// 是否一个点向x轴的射线穿透线段,有交点且在线的左边
///
public bool IsIntersectLeft(CurvePoint pt)
{
double maxY = this.Point0.Y > this.Point1.Y ? this.Point0.Y : this.Point1.Y;
double minY = this.Point0.Y > this.Point1.Y ? this.Point1.Y : this.Point0.Y;
if (Math.Abs(this.Point1.Y - this.Point0.Y) < 0.000001)
{
if (Math.Abs(pt.Y - this.Point0.Y) < 0.000001)
return true;
return false;
}
bool IsInLine = false;
if (pt.Y < maxY && pt.Y >= minY)
{
if (pt.X <= (this.Point0.X + (this.Point1.X - this.Point0.X) * (pt.Y - this.Point0.Y) / (this.Point1.Y - this.Point0.Y)))
{
IsInLine = true;
}
}
return IsInLine;
}
///
/// 获取内部点
///
public CurvePoint GetInnerPoint(double ratio)
{
var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X);
var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y);
return new CurvePoint(x, y);
}
///
/// 获取内部X坐标
///
public double GetInnerX(double ratio)
{
var x = this.Point0.X + ratio * (this.Point1.X - this.Point0.X);
return x;
}
///
/// 获取内部Y坐标
///
public double GetInnerY(double ratio)
{
var y = this.Point0.Y + ratio * (this.Point1.Y - this.Point0.Y);
return y;
}
///
/// 返回直线的k和b y=kx+b
///
public bool GetKandB(out double k, out double b, double ignore = 0.000001)
{
k = b = 0;
if (Math.Abs(this.Point0.X - this.Point1.X) < ignore)
{//竖直
k = 100000000;
b = this.Point0.X;
return false;
}
if (Math.Abs(this.Point0.Y - this.Point1.Y) < ignore)
{//平行
k = 0;
b = this.Point0.X;
return true;
}
k = (this.Point0.Y - this.Point1.Y) / (this.Point0.X - this.Point1.X);// Math.Atan((pt1.Y - pt2.Y) / (pt1.X - pt2.X)) * 180 / Math.PI;
b = this.Point0.Y - k * this.Point0.X;
return true;
}
///
/// 通过 X 获取 Y
///
public double GetYByX(double x)
{
if (!GetKandB(out double k, out double b))
{
return this.Point0.Y;
}
return k * x + b;
}
///
/// 通过 Y 获取 X
///
public double GetXByY(double y)
{
if (!GetKandB(out double k, out double b))
{
return this.Point0.X;
}
return (y - b) / k;
}
///
/// 获取中间点
///
public CurvePoint GetMiddlePoint()
{
return new CurvePoint((this.Point0.X + this.Point1.X) * 0.5, (this.Point0.Y + this.Point1.Y) * 0.5);
}
///
/// 通过 X 判断是否为内部点
///
public bool IsInnerByX(double x)
{
if (x >= this.Point0.X && x <= this.Point1.X)
return true;
if (x >= this.Point1.X && x <= this.Point0.X)
return true;
return false;
}
///
/// 通过 Y 判断是否为内部点
///
public bool IsInnerByY(double y)
{
if (y >= this.Point0.Y && y <= this.Point1.Y)
return true;
if (y >= this.Point1.Y && y <= this.Point0.Y)
return true;
return false;
}
///
/// 三个点在同一条直线上,输入(X1,Y1),(X2,Y2)以及沿(X2,Y2)侧延长Length,得到的点(X3,Y3)
///
public CurvePoint GetExtendPoint(double length)
{
double betweenLength = this.Point0.Distance(this.Point1);
if (betweenLength < 0.01)
return this.Point0;
var extPt = new CurvePoint();
extPt.X = (this.Point1.X - this.Point0.X) * length / betweenLength + this.Point1.X;
extPt.Y = (this.Point1.Y - this.Point0.Y) * length / betweenLength + this.Point1.Y;
return extPt;
}
///
/// 求直线外一点到该直线的投影点
///
public CurvePoint GetProjectivePoint(CurvePoint pOut)
{
if (!GetKandB(out double k, out double b))
return default;
return GetProjectivePoint(this.Point0, k, pOut);
}
///
/// 点到线的距离, 注意不一定是垂直距离,点只在(line_start和line_end之间
///
public double Distance(CurvePoint pt)
{
var project_pt = GetProjectivePoint(pt);
if (IsInnerByX(pt.X))
return project_pt.Distance(pt);
var dis1 = this.Point0.Distance(pt);
var dis2 = this.Point1.Distance(pt);
if (dis1 < dis2)
return dis1;
else
return dis2;
}
///
/// 求直线外一点到该直线的投影点
///
/// 线上任一点
/// 直线斜率
/// 线外指定点
public static CurvePoint GetProjectivePoint(CurvePoint pl, double k, CurvePoint pout)
{
CurvePoint pProject = new CurvePoint();
if (k == 0) //垂线斜率不存在情况
{
pProject.X = pout.X;
pProject.Y = pout.Y;
}
else
{
pProject.X = (float)((k * pl.X + pout.X / k + pout.Y - pl.Y) / (1 / k + k));
pProject.Y = (float)(-1 / k * (pProject.X - pout.X) + pout.Y);
}
return pProject;
}
///
///
///
public CurveLine Clone()
{
return new CurveLine(this);
}
///
///
///
object ICloneable.Clone()
{
return this.Clone();
}
}
}