给出n行的所有线段交叉点的算法

时间:2015-11-20 06:03:29

标签: algorithm geometry computational-geometry intersection line-segment

我正在寻找一种算法来找到给定n个线段的所有交点。 以下是https://support.microsoft.com/en-us/kb/917607

中的伪代码

输入S [1 .. n]是一个行数组 段。 label [i]是第i个最左端点的标签。

sort the endpoints of S from left to right
create an empty label sequence
for i ← 1 to 2n
    line ← label[i]
    if isLeftEndPoint[i]
        Insert(line)
        if Intersect(S[line], S[Successor(line)])
            return TRUE
        if Intersect(S[line], S[Predecessor(line)])
            return TRUE
    else
        if Intersect(S[Successor(line)], S[Predecessor(line)])
            return TRUE
        Delete(label[i])

return FALSE

将算法应用于下面的行集,仅检查一个交叉点。我该怎么做才能知道其他2个交叉点的存在? http://jeffe.cs.illinois.edu/teaching/373/notes/x06-sweepline.pdf

  1. 第[1]行进入
  2. 第[2]行进入,检查第[1]行和第[2]行之间的交点。
  3. 行[3]进入,行[2]和行[3]之间的交叉点被检查。
  4. 行[4]进入,检查行[4]和行[1]之间的交点。找到了交叉口A.
  5. line [4]离开,没有检查任何内容。
  6. 行[1]离开,没有检查任何内容。
  7. 行[2]离开,没有检查任何内容。
  8. line [3]离开,没有检查任何内容。

1 个答案:

答案 0 :(得分:0)

标准线方程 AX + = C

由等式的标准线定义的线的斜率(m)是

m = - (A / B)

点 - 斜线方程 的y Y1 =米(X-X1)

在点 - 斜率线方程中代入m =( - A / B) y2-y1 =(A / -B)*(x2-x1)

(y2-y1)/(x2-x1)= A / -B

因此:

A = y2-y1
B = x1-x2 C = Ax + By

x =(C-By)/ A

y =(C-Ax)/ B

给出两行等式 A1x1 + B1y1 = C1和A2x2 + B2y2 = C2 然后指定线之间的交叉点 通过使得A1x + B1y-C1 = A2x + B2y-C2

的点

A1X + B1Y = C1
A2X + B2Y = C2

A1B2x + B1B2y = B2C1(将第一个等式乘以B2)
A1B2x + B1B2y-B2C1 = 0

A2B1x + B1B2y = B1C2(将第二个等式乘以B1)
A2B1x + B1B2y-B1C2 = 0

将两个等式等同起来 A1B2x + B1B2y-B2C1 = A2B1x + B1B2y-B1C2
A1B2x + B1B2y-B2C1-A2B1x-B1B2y + B1C2 = 0
A1B2x-B2C1-A2B1x + B1C2 = 0
A1B2x-A2B1x = B2C1-B1C2
X(A1B2-A2B1)= B2C1-B1C2

x =(B2C1-B1C2)/ A1B2-A2B1

A1X + B1Y = C1
A2X + B2Y = C2

A1A2x + A2B1y = A2C1(将第一个等式乘以A2)
A1A2x + A2B1y-A2C1 = 0

A1A2x + A1B2y = A1C2(将第二个等式乘以A1)
A1A2x + A1B2y-A1C2 = 0

等同于两个方程式

A1A2x + A2B1y-A2C1 = A1A2x + A1B2y-A1C2
A1A2x + A2B1y-A2C1-A1A2x-A1B2y + A1C2 = 0
A1C2-A2C2 = A1B2y-A2B1y
A1B2y-A2B1y = A1C2-A2C2
Y(A1B2-A2B1)= A1C2-A2C1
Y(A1B2-A2B1)= A1C2-A2C1
y =(A1C2-A2C1)/(A1B1-A2B1)

y和x中的分母是相同的 分母= A1B1-A2B1

因此:

x =(B2C1-B1C2)/分母
y =(A1C2-A2C1)/分母

这些是两条线的交点的x和y坐标,其中点(x1,y1),(x2,y2)
和(x3,y3),(x4,y4)

现在对于线段,它是相同的,但我们需要检查x或y坐标是否在两个段中。这意味着在两个具有较小值的分段的x坐标和具有较大值的两个分段的x坐标之间

这是一个C ++程序,如果段相交则返回true,否则返回false。如果段相交,则将交叉点存储在变量i中。

struct Point
{
    float x, y;
};

//p1 and p2 are the points of the first segment
//p3 and p4 are the points of the second segment
bool intersection(Point p1, Point p2, Point p3, Point p4, Point &i)
{
    float max1; //x-coordinate with greater value in segment 1
    float min1; //x-coordinate with lesse value in segment 1
    float max2; //x-coordinate with greater value in segment 2
    float min2; //x-coordinate with lesser value in segment 2
    float A1 = p2.y - p1.y;
    float B1 = p1.x - p2.x;
    float C1 = A1 * p1.x + B1 * p1.y;
    float A2 = p4.y - p3.y;
    float B2 = p3.x - p4.x;
    float C2 = A2 * p3.x + B2 * p3.y;
    float denom = A1 * B2 - A2 * B1;

if (denom == 0.0) //When denom == 0, is because the lines are parallel
    return false; //Parallel lines do not intersect

i.x = (C1 * B2 - C2 * B1) / denom;
i.y = (A1 * C2 - A2 * C1) / denom;

if (p1.x > p2.x)
{
    max1 = p1.x;
    min1 = p2.x;

}
else
{
    max1 = p2.x;
    min1 = p1.x;
}

if (p3.x > p4.x)
{
    max2 = p3.x;
    min2 = p4.x;

}
else
{
    max2 = p4.x;
    min2 = p3.x;
}

//check if x coordinate is in both segments
if (i.x >= min1 && i.x <= max1 &&
    i.x >= min2 && i.x <= max2)
    return true;
return false; //Do no intersect, intersection of the lines is not between the segments

}

现在你只需要在一个循环上比较所有的段并将交叉点存储在数组上。

相关问题