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(); } } }