【C#】點到線段最短距離的那條直線與線段的交點
阿新 • • 發佈:2018-12-24
/// <summary> /// 點到線段最短距離的那條直線與線段的交點,{x=...,y=...} /// </summary> /// <param name="x">線段外的點的x座標</param> /// <param name="y">線段外的點的y座標</param> /// <param name="x1">線段頂點1的x座標</param> /// <param name="y1">線段頂點1的y座標</param> /// <param name="x2">線段頂點2的x座標</param> /// <param name="y2">線段頂點2的y座標</param> /// <returns></returns> public Vector2 PointForPointToABLine(float x, float y, float x1, float y1, float x2, float y2) { Vector2 reVal = new Vector2(); // 直線方程的兩點式轉換成一般式 // A = Y2 - Y1 // B = X1 - X2 // C = X2*Y1 - X1*Y2 float a1 = y2 - y1; float b1 = x1 - x2; float c1 = x2 * y1 - x1 * y2; float x3, y3; if (a1 == 0) { // 線段與x軸平行 reVal = new Vector2(x, y1); x3 = x; y3 = y1; } else if (b1 == 0) { // 線段與y軸平行 reVal = new Vector2(x1, y); x3 = x1; y3 = y; } else { // 普通線段 float k1 = -a1 / b1; float k2 = -1 / k1; float a2 = k2; float b2 = -1; float c2 = y - k2 * x; // 直線一般式和二元一次方程的一般式轉換 // 直線的一般式為 Ax+By+C=0 // 二元一次方程的一般式為 Ax+By=C c1 = -c1; c2 = -c2; // 二元一次方程求解(Ax+By=C) // a=a1,b=b1,c=c1,d=a2,e=b2,f=c2; // X=(ce-bf)/(ae-bd) // Y=(af-cd)/(ae-bd) x3 = (c1 * b2 - b1 * c2) / (a1 * b2 - b1 * a2); y3 = (a1 * c2 - c1 * a2) / (a1 * b2 - b1 * a2); } // 點(x3,y3)作為點(x,y)到(x1,y1)和(x2,y2)組成的直線距離最近的點,那(x3,y3)是否在(x1,y1)和(x2,y2)的線段之內(包含(x1,y1)和(x2,y2)) if (((x3 > x1) != (x3 > x2) || x3 == x1 || x3 == x2) && ((y3 > y1) != (y3 > y2) || y3 == y1 || y3 == y2)) { // (x3,y3)線上段上 reVal = new Vector2(x3, y3); } else { // (x3,y3)線上段外 float d1_quadratic = (x - x1) * (x - x1) + (y - y1) * (y - y1); float d2_quadratic = (x - x2) * (x - x2) + (y - y2) * (y - y2); if (d1_quadratic <= d2_quadratic) { reVal = new Vector2(x1, y1); } else { reVal = new Vector2(x2, y2); } } return reVal; }