How can I check if two segments intersect?
The equation of a line is:
f(x) = A*x + b = y
For a segment, it is exactly the same, except that x is included on an interval I.
If you have two segments, defined as follow:
Segment1 = {(X1, Y1), (X2, Y2)}
Segment2 = {(X3, Y3), (X4, Y4)}
The abcisse Xa of the potential point of intersection (Xa,Ya) must be contained in both interval I1 and I2, defined as follow :
I1 = [min(X1,X2), max(X1,X2)]
I2 = [min(X3,X4), max(X3,X4)]
And we could say that Xa is included into :
Ia = [max( min(X1,X2), min(X3,X4) ),
min( max(X1,X2), max(X3,X4) )]
Now, we need to check that this interval Ia exists :
if (max(X1,X2) < min(X3,X4)):
return False # There is no mutual abcisses
So, we have two line formula, and a mutual interval. Your line formulas are:
f1(x) = A1*x + b1 = y
f2(x) = A2*x + b2 = y
As we got two points by segment, we are able to determine A1, A2, b1 and b2:
A1 = (Y1-Y2)/(X1-X2) # Pay attention to not dividing by zero
A2 = (Y3-Y4)/(X3-X4) # Pay attention to not dividing by zero
b1 = Y1-A1*X1 = Y2-A1*X2
b2 = Y3-A2*X3 = Y4-A2*X4
If the segments are parallel, then A1 == A2 :
if (A1 == A2):
return False # Parallel segments
A point (Xa,Ya) standing on both line must verify both formulas f1 and f2:
Ya = A1 * Xa + b1
Ya = A2 * Xa + b2
A1 * Xa + b1 = A2 * Xa + b2
Xa = (b2 - b1) / (A1 - A2) # Once again, pay attention to not dividing by zero
The last thing to do is check that Xa is included into Ia:
if ( (Xa < max( min(X1,X2), min(X3,X4) )) or
(Xa > min( max(X1,X2), max(X3,X4) )) ):
return False # intersection is out of bound
else:
return True
In addition to this, you may check at startup that two of the four provided points are not equals to avoid all that testing.
User @i_4_got points to this page with a very efficent solution in Python. I reproduce it here for convenience (since it would have made me happy to have it here):
def ccw(A,B,C):
return (C.y-A.y) * (B.x-A.x) > (B.y-A.y) * (C.x-A.x)
# Return true if line segments AB and CD intersect
def intersect(A,B,C,D):
return ccw(A,C,D) != ccw(B,C,D) and ccw(A,B,C) != ccw(A,B,D)