线段交叉点

时间:2015-05-24 09:31:07

标签: geometry intersection lines

我在raywenderlich.com上找到了这段代码片段,但解释的链接不再有效。我将答案“翻译”到Swift中,我希望你能理解,即使不懂语言也很容易。任何人都可以解释一下到底发生了什么?谢谢你的帮助。

class func linesCross(#line1: Line, line2: Line) -> Bool {
    let denominator = (line1.end.y - line1.start.y) * (line2.end.x - line2.start.x) -
        (line1.end.x - line1.start.x) * (line2.end.y - line2.start.y)

    if denominator == 0 { return false } //lines are parallel

    let ua = ((line1.end.x - line1.start.x) * (line2.start.y - line1.start.y) -
        (line1.end.y - line1.start.y) * (line2.start.x - line1.start.x)) / denominator
    let ub = ((line2.end.x - line2.start.x) * (line2.start.y - line1.start.y) -
        (line2.end.y - line2.start.y) * (line2.start.x - line1.start.x)) / denominator

    //lines may touch each other - no test for equality here
    return ua > 0 && ua < 1 && ub > 0 && ub < 1
}

3 个答案:

答案 0 :(得分:2)

您可以找到详细的分段交叉算法 在书中Computational Geometry in C,Sec。 7.7。 这里描述的SegSegInt代码可用here。 我建议避免斜率计算。

有几个&#34;退化&#34;需要注意的案例:共线段 重叠与否,其他段内部的一个段端点, 我编写了代码来返回这些特殊情况的指示。

答案 1 :(得分:1)

This is what the code is doing.

Every point P in the segment AB can be described as:

P = A + u(B - A)

for some constant 0 <= u <= 1. In fact, when u=0 you get P=A, and you getP=B when u=1. Intermediate values of u will give you intermediate values of P in the segment. For instance, when u = 0.5 you will get the point in the middle. In general, you can think of the parameter u as the ratio between the lengths of AP and AB.

enter image description here

Now, if you have another segment CD you can describe the points Q on it in the same way, but with a different u, which I will call v:

Q = C + v(D - C)

Again, keep in mind that Q lies between C and D if, and only if, 0 <= v <= 1 (same as above for P).

To find the intersection between the two segments you have to equate P=Q. In other words, you need to find u and v, both between 0 and 1 such that:

A + u(B - A) = C + v(D - C)

So, you have this equation and you have to see if it is solvable within the given constraints on u and v.

Given that A, B, C and D are points with two coordinates x,y each, you can open the equation above into two equations:

ax + u(bx - ax) = cx + v(dx - cx)
ay + u(by - ay) = cy + v(dy - cy)

where ax = A.x, ay = A.y, etc., are the coordinates of the points.

Now we are left with a 2x2 linear system. In matrix form:

|bx-ax  cx-dx| |u| = |cx-ax|
|by-ay  cy-dy| |v|   |cy-ay|

The determinant of the matrix is

det = (bx-ax)(cy-dy) - (by-ay)(cx-dx)

This quantity corresponds to the denominator of the code snippet (please check).

Now, multiplying both sides by the cofactor matrix:

|cy-dy  dx-cx|
|ay-by  bx-ax|

we get

det*u = (cy-dy)(cx-ax) + (dx-cx)(cy-ay)
det*v = (ay-by)(cx-ax) + (bx-ax)(cy-ay)

which correspond to the variables ua and ub defined in the code (check this too!)

Finally, once you have u and v you can check whether they are both between 0 and 1 and in that case return that there is intersection. Otherwise, there isn't.

答案 2 :(得分:0)

对于给定的线,斜率为

m=(y_end-y_start)/(x_end-x_start)

如果两个斜率相等,则线是平行的

m1=m1

(y1_end-y_start)/(x1_end-x1_start)=(y2_end-y2_start)/(x2_end-x2_start)

这相当于检查分母不为零,

关于其余代码,请在“{3}}下找到”每行给定两个点“下的解释