我正在寻找一种算法来找到给定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
答案 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
}
现在你只需要在一个循环上比较所有的段并将交叉点存储在数组上。