As a slight correction to the answers above, using 3D cross products to compute a 2D line intersection is pretty much the least efficient possible. Cross products do not SIMD optimise at all (unless you go to the lengths of using an SOA data structure, but even than it's an extremely wasteful approach). The best approach is to use good old simultaneous equations.
Starting with our input points that define the line:
line1: [(x1, y1), (x2, y2)]
line2: [(x3, y3), (x4, y4)]
Compute some direction vectors:
// 1st direction
u1 = x2 - x1
v1 = y2 - y1
D1 = [u1, v1]
// 2nd direction
u2 = x4 - x3
v2 = y4 - y3
D2 = [u2, v2]
Now lets reformulate the line equations as rays, and come up with an equation for any point along those rays:
// coords of a point 'd1' distance along the 1st ray
Px = x1 + d1*u1
Py = y1 + d1*v1
// coords of a point 'd2' distance along the 2nd ray
Px = x3 + d2*u2
Py = y3 + d2*v2
Let's assume the lines intersect, which means both P's will be the same, allowing us to state:
x1 + d1*u1 = x3 + d2*u2
y1 + d1*v1 = y3 + d2*v2
I wont go through each step, but re-arrange both equations in terms of d1, and we get:
d1 = x3 + d2*u2 - x1
---------------
u1
d1 = y3 + d2*v2 - y1
---------------
v1
Now we have two equations for d1, so lets do another simultaneous equation to get a value for d2:
x3 + d2*u2 - x1 y3 + d2*v2 - y1
--------------- = ---------------
u1 v1
Rearrange to isolate d2:
d2 = u1(y3 - y1) - v1(x3 - x1)
-------------------------
v1*u2 - u1*v2
If (v1*u2 - u1*v2) happens to be zero, there is no solution for this equation (let's call that the determinant, because it is what it is!). If the determinant is non zero, then simply compute d2 using the above equation, and pump back into one of our earlier equations to find the point value:
Px = x3 + d2*u2
Py = y3 + d2*v2
Some untested C++ code:
bool computeIntersectPoint(
float x1, float y1,
float x2, float y2,
float x3, float y3,
float x4, float y4,
float outPoint[2])
{
// compute direction vectors
// in some cases, it can be worth
// storing the lines as rays as an
// optimisation. (avoids 4 subs)
const float u1 = x2 - x1;
const float v1 = y2 - x1;
const float u2 = x4 - x3;
const float v2 = y4 - x3;
// check to see if we have a solution
// 1 mul, 1 fmsub
float determinant = v1*u2 - u1*v1;
if(determinant == 0)
return false;
// 2 sub, 1 mul, 1 fmsub
float temp = u1 * (y3 - y1) - v1 * (x3 - x1);
// 1 div
float intersectDistance = temp / determinant;
// 2 fma
outPoint[0] = intersectDistance * u2 + x3;
outPoint[1] = intersectDistance * v2 + y3;
return true;
}
Quick desmos proof: https://www.desmos.com/calculator/gtlmnmzn6l
It's worth at this point comparing the instruction count between the two approaches here. A 3d cross product requires 3 mult, and 3 fmsub instructions (or 6 mul + 3 sub if FMA is not available). Since we have 3 of those, we are up to: 9 mul and 9 fmsub ops. Add in the 2 divisions, and we get:
9 mul
9 fmsub
2 div
The approach I've posted would require:
1 div
6 sub
4 fma
2 mul
Although you could save 4 of those subs if you can get away with storing the lines as rays.