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

/// <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;
    }

C#中,判断两条线段是否相交通常涉及到几何学中的向量运算。这里简单概述一种常见的算法,称为"点积法": 1. **确定方向向量**:对于每条线段,找到两个端点形成的向量。例如,设线段A从点P1到点Q1,线段B从点P2到点Q2,那么方向向量可以是(Q1-P1) 和 (Q2-P2)。 2. **计算向量点积**:将这两个方向向量进行点积(也叫内积),记作`dotProduct = dot((Q1 - P1), (Q2 - P2))`。如果结果是正数,说明两线段平行但未交叉;如果是负数,说明两线段反向,同样没有交点。 3. **检查垂直情况下的交点**:如果点积为零,则需要进一步检查这两条线是否是垂直的。这可以通过比较各自的长度(模长)是否接近于0来判断。如果它们很接近0,可以认为是近似垂直,这时需要进行额外的细分测试,比如通过计算延长线的交点。 4. **寻找交点**:当发现点积为零且不是垂直的情况,可以考虑设置临界值ε(一个小的正值)来判断是否真的有交点。假设点积为零,我们可以取每条线的方向向量,然后在各自的一半长度上找一个测试点。如果这两个测试点都在对方线段的范围内,则存在交点。 以下是伪代码示例: ```csharp double dotProduct = Vector3.Dot(line1Direction, line2Direction); if (dotProduct == 0) { // 垂直处理 if (line1Length * line2Length < epsilon) { // 检查延长线交点 // ... } else { return false; } } else if (dotProduct > 0) { return false; // 平行无交点 } // ...(继续检查是否在线段范围内) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值