Determining if two rays intersect

Given: two rays a, b with starting points (origin vectors) as, bs, and direction vectors ad, bd.

The two lines intersect if there is an intersection point p:

p = as + ad * u
p = bs + bd * v

If this equation system has a solution for u>=0 and v>=0 (the positive direction is what makes them rays), the rays intersect.

For the x/y coordinates of the 2d vectors, this means:

p.x = as.x + ad.x * u
p.y = as.y + ad.y * u
p.x = bs.x + bd.x * v
p.y = bs.y + bd.y * v

Further steps:

as.x + ad.x * u = bs.x + bd.x * v
as.y + ad.y * u = bs.y + bd.y * v

Solving against v:

v := (as.x + ad.x * u - bs.x) / bd.x

Inserting and solving against u:

as.y + ad.y * u = bs.y + bd.y * ((as.x + ad.x * u - bs.x) / bd.x) 
u := (as.y*bd.x + bd.y*bs.x - bs.y*bd.x - bd.y*as.x ) / (ad.x*bd.y - ad.y*bd.x)

Calculate u, then calculate v, if both are positive the rays intersect, else not.


I am sorry to disagree with the answer of Peter Walser. Solving the equations gives on my desk:

u = ((bs.y - as.y) * bd.x - (bs.x - as.x) * bd.y) / (bd.x * ad.y - bd.y * ad.x)
v = ((bs.y - as.y) * ad.x - (bs.x - as.x) * ad.y) / (bd.x * ad.y - bd.y * ad.x)

Factoring out the common terms, this comes to:

dx = bs.x - as.x
dy = bs.y - as.y
det = bd.x * ad.y - bd.y * ad.x
u = (dy * bd.x - dx * bd.y) / det
v = (dy * ad.x - dx * ad.y) / det

Five subtractions, six multiplications and two divisions.

If you only need to know if the rays intersect, the signs of u and v are enough, and these two divisons can be replaced by num*denom<0 or (sign(num) != sign(denom)), depending on what is more efficient on your target machine.

Please note that the rare case of det==0 means that the rays do not intersect (one additional comparison).