I've tried searching for a javascript function that will detect if two lines intersect each other.
The function will take the x,y values of both the start end points for each line (we'll call them line A and line B).
Is to return true if they intersect, otherwise false.
Example of the function. I'm happy if the answer uses a vector object instead.
Function isIntersect (lineAp1x, lineAp1y, lineAp2x, lineAp2y, lineBp1x, lineBp1y, lineBp2x, lineBp2y)
{
// JavaScript line intersecting test here.
}
Some background info: this code is for a game I'm trying to make in html5 canvas, and is part of my collision detection.
Explanation: (vectors, a matrix and a cheeky determinant)
Lines can be described by some initial vector, v, and a direction vector, d:
We use one point
(a,b)
as the initial vector and the difference between them(c-a,d-b)
as the direction vector. Likewise for our second line.If our two lines intersect, then there must be a point, X, that is reachable by travelling some distance, lambda, along our first line and also reachable by travelling gamma units along our second line. This gives us two simultaneous equations for the coordinates of X:
These equations can be represented in matrix form. We check that the determinant is non-zero to see if the intersection X even exists.
If there is an intersection, then we must check that the intersection actually lies between both sets of points. If lambda is greater than 1, the intersection is beyond the second point. If lambda is less than 0, the intersection is before the first point.
Hence,
0<lambda<1 && 0<gamma<1
indicates that the two lines intersect!The wiki page I found the answer from.
Here's a version based on this gist with some more concise variable names, and some Coffee.
JavaScript version
CoffeeScript version
Although it is useful to be able to find the intersection point, testing for whether line segments intersect is most often used for polygon hit-testing, and given the usual applications of that, you need to do it fast. Therefore I suggest you do it like this, using only subtraction, multiplication, comparison and AND.
Turn
computes the direction of the change in slope between the two edges described by the three points: 1 means counter-clockwise, 0 means no turn and -1 means clockwise.This code expects points expressed as GLatLng objects but can be trivially rewritten to other systems of representation. The slope comparison has been normalised to epsilon tolerance to damp floating point errors.
I've rewritten Peter Wone's answer to a single function using x/y instead of lat()/long()
Peter Wone's answer is a great solution, but it lacks an explanation. I spent the last hour or so understanding how it works and think I understand enough to explain it as well. See his answer for details: https://stackoverflow.com/a/16725715/697477
I've also included a solution for the co-linear lines in the code below.
Using Rotational Directions to check for intersection
To explain the answer, let's look at something common about every intersection of two lines. Given the picture below, we can see that P1 to IP to P4 rotates counter clockwise. We can see that it's complimentary sides rotate clockwise. Now, we don't know if it intersects, so we don't know the intersection point. But we can also see that P1 to P2 to P4 also rotates counter clockwise. Additionally, P1 to P2 to P3 rotates clock wise. We can use this knowledge to determine whether two lines intersect or not.
Intersection Example
You'll notice that intersecting lines create four faces that point opposite directions. Since they face opposite directions, we know that the direction of P1 to P2 to P3 rotates a direction different than P1 to P2 to P4. We also know that P1 to P3 to P4 rotates a different direction than P2 to P3 to P4.
Non-Intersection Example
In this example, you should notice that following the same pattern for the intersection test, the two faces rotate the same direction. Since they face the same direction, we know that they do not intersect.
Code Sample
So, we can implement this into the original code supplied by Peter Wone.