我在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
}
答案 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
.
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}}下找到”每行给定两个点“下的解释