两直线判断相交并求交点

本文介绍了如何通过数学方法计算两条线段的交点坐标。利用向量叉乘和消元法,推导出交点参数t和s的计算公式,并给出判断线段是否相交的条件。最后提供了一个具体的实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 给定两条线段\overrightarrow{P_{1}P_{2}}\overrightarrow{P_{3}P_{4}},端点表示为P1(x1,y1),P2(x2,y2),P3(x3,y3)和P4(x4,y4),假设两条线段的交点为P0(x0,y0),且t=\frac{\left | \overline{P_{1}P_{0}} \right |}{\left | \overline{P_{1}P_{2}} \right |}s=\frac{\left | \overline{P_{3} P_{0}} \right |}{\left | \overline{P_{3} P_{4}} \right |},那么P0可以表示为:

\left\{ \begin{aligned} P_{0} & = P_{1} +t*\overrightarrow{ P_{1} P_{2}}, 0\leq t \leq 1 \\ P_{0} & = P_{3} +s*\overrightarrow{ P_{3} P_{4}}, 0\leq s \leq 1 \end{aligned} \right.

t和s在等于0或1时表示两条线段相交在端点,如果为其他值,表示两条线段不相交。将点坐标代入公式得:

\left\{ \begin{aligned} x_{1} + t*(x_{2} - x_{1}) & = x_{3} +s*(x_{4} - x_{3}) \\ y_{1} + t*(y_{2} - y_{1}) & = y_{3} +s*(y_{4} - y_{3})\end{aligned} \right.

 利用公式消元法求得t和s:

t=\frac{(x_{3} - x_{1})(y_{4} - y_{3}) - (y_{3} - y_{1})(x_{4} - x_{3})}{(x_{2} - x_{1})(y_{4} - y_{3}) - (y_{2} - y_{1})(x_{4} - x_{3})}

s=\frac{(x_{3} - x_{1})(y_{2} - y_{1}) - (y_{3} - y_{1})(x_{2} - x_{1})}{(x_{2} - x_{1})(y_{4} - y_{3}) - (y_{2} - y_{1})(x_{4} - x_{3})} 

t和s方程的分子和分母都是向量的叉乘: 

t=\frac{\left | \overrightarrow{P_{3} P_{1} } * \overrightarrow{ P_{4} P_{3} } \right |}{\left | \overrightarrow{P_{2} P_{1} } * \overrightarrow{ P_{4} P_{3} } \right |} 

s=\frac{\left | \overrightarrow{P_{3} P_{1} } * \overrightarrow{ P_{2} P_{1} } \right |}{\left | \overrightarrow{P_{2} P_{1} } * \overrightarrow{ P_{4} P_{3} } \right |} 

如果\overrightarrow{P_{2} P_{1} } * \overrightarrow{P_{4} P_{3}} = 0,表示两条线段平行,如果端点在另一条线段上,则该端点为交点,否则不是。如果t和s有一个没有落在区间内\left [ 0,1 \right ],则两条线段不相交。那么交点P_{0}的坐标为:

\left\{ \begin{aligned} x_{0} = x_{1} + t*(x_{2} - x_{1}) \\ y_{0} = y_{1} + t*(y_{2} - y_{1})\end{aligned} \right.

\left\{ \begin{aligned} x_{0} = x_{3} + s*(x_{4} - x_{3}) \\ y_{0} = y_{1} + s*(y_{4} - y_{3})\end{aligned} \right.

至此,整个求解过程介绍完成。

// 定义一个常量用于浮点数比较的阈值
const double EPSILON = 1.0e-6;

bool Intersection(double x1, double y1, double x2, double y2,
                  double x3, double y3, double x4, double y4,
                  double& x0, double& y0)
{
    // 计算向量差
    double dx1 = x2 - x1;  // 线段1的x方向差
    double dy1 = y2 - y1;  // 线段1的y方向差
    double dx2 = x4 - x3;  // 线段2的x方向差
    double dy2 = y4 - y3;  // 线段2的y方向差
    double dx3 = x3 - x1;  // 线段1起点到线段2起点的x方向差
    double dy3 = y3 - y1;  // 线段1起点到线段2起点的y方向差

    // 计算行列式(判断是否平行或重合)
    double determinant = dx1 * dy2 - dy1 * dx2;

    // 如果行列式接近0,表示两线段平行或重合
    if (std::fabs(determinant) < EPSILON)
    {
        return false;  // 无法计算交点
    }

    // 计算参数t和s,用于判断交点是否在线段范围内
    double t = (dy2 * dx3 - dx2 * dy3) / determinant;
    double s = (dy1 * dx3 - dx1 * dy3) / determinant;

    // 检查t和s是否在[0, 1]范围内
    if (t < 0 || t > 1 || s < 0 || s > 1)
    {
        return false;  // 交点不在两条线段的范围内
    }

    // 计算交点坐标
    x0 = x1 + t * dx1;
    y0 = y1 + t * dy1;

    return true;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值