这个线路交叉如何工作?

时间:2010-11-09 01:36:48

标签: c++ math

我正在建造一个小组游戏,用于课堂学习。为了完成它我需要一个 线交叉算法/代码。我发现一个有效,但我不明白 背后的数学。这是如何工作的?

point* inter( point p1, point p2, point p3, point p4)
{
point* r;

//p1-p2 is the first edge. 
//p3-p4 is the second edge.
r = new point;
float x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x;
float y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y;

//I do not understand what this d represents.
float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);
// If d is zero, there is no intersection
if (d == 0) return NULL;

// I do not understand what this pre and pos means and
// how it's used to get the x and y of the intersection
float pre = (x1*y2 - y1*x2), pos = (x3*y4 - y3*x4);
float x = ( pre * (x3 - x4) - (x1 - x2) * pos ) / d;
float y = ( pre * (y3 - y4) - (y1 - y2) * pos ) / d;

// Check if the x and y coordinates are within both lines
if ( x < min(x1, x2) || x > max(x1, x2) ||
        x < min(x3, x4) || x > max(x3, x4) ) return NULL;
if ( y < min(y1, y2) || y > max(y1, y2) ||
        y < min(y3, y4) || y > max(y3, y4) ) return NULL;

cout << "Inter X : " << x << endl;
cout << "Inter Y : " << y << endl;

// Return the point of intersection
r->x = x;
r->y = y;
return r; 
}

4 个答案:

答案 0 :(得分:5)

确定二维平面中两条线的交点(如果有的话)(它们可以是平行的)是一个经典的数学问题。您找到的算法基于求解具有两个线性方程的系统。这是通过计算行列式(d)来完成的。如果为零,那么线是平行的。否则,计算交点。

有关公式的详细说明,请参阅本教程:http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=geometry2

答案 1 :(得分:3)

他们是determinants

答案 2 :(得分:2)

point* inter( point p1, point p2, point p3, point p4)
{
    point* r;

    //p1-p2 is the first edge. 
    //p3-p4 is the second edge.
    r = new point;

正如其他人已经评论过的那样,上面的内容会泄漏内存。更好地使用智能指针,例如std::auto_ptr

    float x1 = p1.x, x2 = p2.x, x3 = p3.x, x4 = p4.x;
    float y1 = p1.y, y2 = p2.y, y3 = p3.y, y4 = p4.y;

    //I do not understand what this d represents.
    float d = (x1 - x2) * (y3 - y4) - (y1 - y2) * (x3 - x4);

首先,您需要了解两个向量的点积。

设X和Y分别是在x轴和y轴方向上的长度为1的向量。然后定义X * X = 1,Y * Y = 1,X * Y = 0,这是一种乘法(或只是一个操作),产生一个矢量投影到另一个矢量的长度,乘以另一个矢量的长度(或换句话说,矢量长度乘以它们之间角度的余弦的乘积)。然后,如果两个向量a和b是a = ax * X + ay * Y并且b = bx * X +乘* Y,那么a * b = ax * bx + ay * by,因为那些带有X * Y的项是零辍学。

令人惊讶的是,对于任意方向的向量,泛化产生向量的长度乘以它们之间角度的余弦,这意味着对于平行向量,它们的长度和垂直向量的乘积,0: - )

设edge1 = p1-p2,edge2 = p3-p4。然后上面计算edge1.x * edge2.y - edge1.y * edge2.x = [edge1.x,edge1.y] * [edge2.y,-edge2.x]。后一个矢量是edge2旋转90度。现在,如果旋转的edge2垂直于edge1,则edge1和edge2必须平行且不能相交。在这种情况下,此点积为0。

    // If d is zero, there is no intersection
    if (d == 0) return NULL;

    // I do not understand what this pre and pos means and
    // how it's used to get the x and y of the intersection
    float pre = (x1*y2 - y1*x2), pos = (x3*y4 - y3*x4);
    float x = ( pre * (x3 - x4) - (x1 - x2) * pos ) / d;
    float y = ( pre * (y3 - y4) - (y1 - y2) * pos ) / d;


    // Check if the x and y coordinates are within both lines
    if ( x < min(x1, x2) || x > max(x1, x2) ||
            x < min(x3, x4) || x > max(x3, x4) ) return NULL;
    if ( y < min(y1, y2) || y > max(y1, y2) ||
            y < min(y3, y4) || y > max(y3, y4) ) return NULL;

    cout << "Inter X : " << x << endl;
    cout << "Inter Y : " << y << endl;

    // Return the point of intersection
    r->x = x;
    r->y = y;
    return r; 
}
亲爱的,亲爱的。我不想分析那个......但如果它有效,那么它就是在两个未知数中求解两个方程的集合,以确定通过边缘的无限线的交点,然后检查该交点是否在边缘内。

干杯&amp;第h。,

答案 3 :(得分:1)

您基本上计算相对于(与其平行的坐标系)的一条线的斜率。 d为零,它们是平行的。然后计算该坐标系中的交点,然后将其移回基础坐标系。