确定从点开始的无限直线(单向)是否与 2D 中的线段相交

Determine whether an infinite straight line (one direction) from a point intersects with a line segment in 2D

本文关键字:是否 2D 段相交 单向 开始 无限      更新时间:2023-10-16

我正在尝试找到一种针对查找(无限)线和线段之间是否存在交集而优化的算法。

在SO和其他网站上,我看到了许多线段 - 线段相交和线 - 线相交算法,但是为一条无限线(从一个方向上的点)和线段找到一个"更简单?"的版本是非常困难的。

我目前有类似的东西(线段 - 线段交点):

bool lineSegmentsIntersect(float pX, float pY, float p2X, float p2Y, float qX, float qY, float q2X, float q2Y)
{
    // p and p2 define the first line segment
    Point2D p(pX, pY);
    Point2D p2(p2X, p2Y);
    // q and q2 define the second line segment
    Point2D q(qX, qY);
    Point2D q2(q2X, q2Y);
    Point2D r = p2 - p;
    Point2D s = q2 - q;
    float uNumerator = (q-p)*r;
    float denominator = r*s;
    if (uNumerator == 0 && denominator == 0) {
        // co-linear, so do they overlap?
        return ((q.x - p.x < 0) != (q.x - p2.x < 0) != (q2.x - p.x < 0) != (q2.x - p2.x < 0)) ||
            ((q.y - p.y < 0) != (q.y - p2.y < 0) != (q2.y - p.y < 0) != (q2.y - p2.y < 0));
    }
    if (denominator == 0) {
        // lines are parallel
        return false;
    }
    float u = uNumerator / denominator;
    float t = ((q-p)*s) / denominator;
    return (t >= 0) && (t <= 1) && (u >= 0) && (u <= 1);
}

其中 * 运算符定义为:

float Point2D::operator*(const Point2D &rhs)
{
    return x*rhs.y - y*rhs.x;
}

虽然我正在寻找更简单/更快的东西。我正在尝试检查一个点是否在闭合形状内(形状由一些点和它们之间的(线性插值)直线定义。

从我向预定义方向发射光线的那一刻开始。

最好是 [1, 0] 或 [0, 1](这可以用作给定的常数),如果这会使数学更容易,我认为它可能。

然后我检查光线是否与每个线段相交,如果这是一个奇数,则它在形状内。

我正在考虑的一些事情:

如果我们决定总是直接向上射出一条射线,那么如果线段的两个点都低于我们已经知道它不相交的点。

参见Hormann和Agathos,"任意多边形的多边形问题中的点",计算几何20(2001)131-144。 用于绕组算法的高效实现。