判断线段是否相交并求交点

36 篇文章 32 订阅

判断线段是否相交并求交点

公式推导

设两条线段ABCD,其端点分别为 ( x a , y a ) , ( x b , y b ) ( x c , y c ) , ( x d , y d ) (x_a,y_a),(x_b,y_b) (x_c,y_c),(x_d,y_d) (xa,ya),(xb,yb)(xc,yc),(xd,yd).需要判断2条线段是否相交,若相交求交点。

两条直线所在的参数方程为:

{ x = x a + α ( x b − x a ) y = y a + α ( y b − y a ) { x = x c + β ( x d − x c ) y = y c + β ( y d − y c ) (1) \left\{ \begin{aligned} x = x_a + \alpha(x_b-x_a) \\ y = y_a + \alpha(y_b-y_a) \\ \end{aligned} \right. \left\{ \begin{aligned} x = x_c + \beta(x_d-x_c) \\ y = y_c + \beta(y_d-y_c) \end{aligned} \right. \tag{1} {x=xa+α(xbxa)y=ya+α(ybya){x=xc+β(xdxc)y=yc+β(ydyc)(1)

若两线段相交,则交点坐标满足以下方程:
{ x = x a + α ( x b − x a ) = x c + β ( x d − x c ) y = y a + α ( y b − y a ) = y = y c + β ( y d − y c ) (2) \left\{ \begin{aligned} x = x_a + \alpha(x_b-x_a)=x_c + \beta(x_d-x_c) \\ y = y_a + \alpha(y_b-y_a)=y = y_c + \beta(y_d-y_c) \end{aligned} \right. \tag{2} {x=xa+α(xbxa)=xc+β(xdxc)y=ya+α(ybya)=y=yc+β(ydyc)(2)

即:
{ α ( x b − x a ) − β ( x d − x c ) = x c − x a α ( y b − y a ) − β ( y d − y c ) = y c − y a (3) \left\{ \begin{aligned} \alpha(x_b-x_a) - \beta(x_d-x_c) = x_c - x_a \\ \alpha(y_b-y_a) - \beta(y_d-y_c) = y_c - y_a \end{aligned} \right. \tag{3} {α(xbxa)β(xdxc)=xcxaα(ybya)β(ydyc)=ycya(3)

求行列式,上面方程存在解的条件是:

Δ = ∣ x b − x a − ( x d − x c ) y b − y a − ( y d − y c ) ∣ (4) \Delta = \begin{vmatrix} x_b-x_a & -(x_d-x_c) \\ y_b-y_a & -(y_d-y_c) \end{vmatrix} \tag{4} Δ=xbxaybya(xdxc)(ydyc)(4)
Δ = 0 \Delta=0 Δ=0,则方程无解。意味着线段重合或平行。如果 Δ ≠ 0 \Delta\neq0 Δ=0,则可求出交点对应的两个参数值:
{ α = 1 Δ ∣ x c − x a − ( x d − x c ) y c − y a − ( y d − y c ) ∣ β = 1 Δ ∣ x b − x a x c − x a y b − y a y c − y a ∣ (5) \left\{ \begin{aligned} \alpha = \frac{1}{\Delta} \begin{vmatrix} x_c-x_a & -(x_d-x_c) \\ y_c-y_a & -(y_d-y_c) \end{vmatrix} \\ \beta = \frac{1}{\Delta} \begin{vmatrix} x_b-x_a & x_c-x_a \\ y_b-y_a & y_c-y_a \end{vmatrix} \end{aligned} \right. \tag{5} α=Δ1xcxaycya(xdxc)(ydyc)β=Δ1xbxaybyaxcxaycya(5)

需要注意,只有 0 ⩽ α ⩽ 1 , 0 ⩽ β ⩽ 1 0\leqslant \alpha \leqslant 1,0\leqslant \beta \leqslant 1 0α1,0β1时两线段才真正相交。否则,交点在两线段或其中某一条线段的延长线上,这时仍然认为是两线段不相交。
将式(5)代入式(1)即可解得两条线段交点。(或者两条线段所在直线的交点)

代码实现

根据上面公式可以很方便求解出线段的交点(或线段所在直线的交点)。由于项目开发经常使用OpenCV,因此给出一份基于OpenCV数据结构的代码实现.

//判断线段是否相交,并求交点
//Input Param:pa,pb--line segment a's 2 points;
//            pc,pd--line segments b's 2 points;
//Output Param:crossP--cross point
//Return:   true:line a, b intersect;false:none;
bool GetLineIntersect(const cv::Point2f &pa, const cv::Point2f &pb,
        const cv::Point2f &pc, const cv::Point2f &pd,cv::Point2f &crossP)
{
    //1°构造行列式.并求解
    cv::Point2f dpa = pb-pa;
    cv::Point2f dpd = pc-pd;
    auto delta = dpa.cross(dpd);//(xb-xa)*(yc-yd) - (xc-xd)*(yb-ya)
    if(std::abs(delta)<0.0001)//delta=0,重合或平行
        return false;

    delta = 1.0/delta;

    //2°求交点对应参数值
    cv::Point2f dp = pc-pa;

    auto alpha = delta*(dp.cross(dpd));
    auto beta = delta*(dpa.cross(dp));

    crossP = pa + alpha*dpa;//交点

    return (0<=alpha && alpha<=1) && (0<=beta && beta<=1 );
}

上面代码利用OpenCV中点(向量)的叉乘来代替行列式的求解。建议对照数学公式进行理解!

上面函数返回值用来判断两条线段是否相交,线段相交返回值为true;线段不相交,但线段所在直线相交,代码同样求出两条直线的交点

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值