欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【C#】点到线段最短距离的那条直线与线段的交点

程序员文章站 2022-04-01 15:47:51
...
/// <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;
    }