交点 - 两线段交点 - 投影法

1) 线段ab的法线上投影

点b的投影为|ob2|,线段cd的端点的投影为:|od2|,|oc2|

1-a) |od2|-|ob2|>0,|oc2|-|ob2|<0

1-b) |od2|-|ob2|>0,|oc2|-|ob2|<0

1-c) |od2|-|ob2|>0,|oc2|-|ob2|>0,肯定不相交

  

 

2) 线段cd的法线上投影

点d的投影为|od1|,线段ab的端点的投影为:|oa1|,|ob1|

2-a) |oa1|-|od1|<0,|ob1|-|od1|>0

2-b) |oa1|-|od1|<0,|ob1|-|od1|>0

2-c) |oa1|-|od1|>0,|ob1|-|od1|>0,肯定不相交

  

 

所以,同时满足1-a)和2-a)才相交,否则不相交 

 

//两线段交点 - 投影法
public static bool IsTwoSegmentIntersect2(Vector2 a, Vector2 b, Vector2 c, Vector2 d, out Vector2 p)
{
    p = Vector2.zero;

    var ab = b - a;
    var cd = d - c;
    var cross = V2Cross(ref ab, ref cd); //|ab|*|cd|*sin(夹角)
    if (Mathf.Approximately(cross, 0)) //两线段平行或共线
        return false;

    var abNM = new Vector2(-ab.y, ab.x); //向量ab的法线(左), 非单位向量
    float distB2 = Vector2.Dot(b, abNM); //多乘了|ab|的
    float distD2 = Vector2.Dot(d, abNM) - distB2;
    float distC2 = Vector2.Dot(c, abNM) - distB2;
    if (distD2 * distC2 > 0)
        return false;

    var cdNM = new Vector2(-cd.y, cd.x); //向量cd的法线(左)
    float distD1 = Vector2.Dot(d, cdNM);
    float distA1 = Vector2.Dot(a, cdNM) - distD1;
    float distB1 = Vector2.Dot(b, cdNM) - distD1;
    if (distA1 * distB1 > 0)
        return false;

    //计算交点坐标
    float len = distD2 / cross;
    p = d - cd * len;
    return true;
}

 

参考

【数学基础】玩法常用几何计算汇总 - 知乎 (zhihu.com)

 

posted @ 2023-11-07 01:21  yanghui01  阅读(24)  评论(0编辑  收藏  举报