Determining if one 2D vector is to the right or left of another

16,909

Solution 1

You can achieve this using a dot product. dot(a, b) == a.x*b.x + a.y*b.y can be used to find whether vectors are perpendicular:

var dot = a.x*b.x + a.y*b.y
if(dot > 0)
    console.log("<90 degrees")
else if(dot < 0)
    console.log(">90 degrees")
else
    console.log("90 degrees")

Put another way. dot > 0 tells you if a is "in front of" b.


Assume b is on the right of a. Rotating b 90 degrees counterclockwise puts it in front of a.
Now assume b is on the left of a. Rotating b 90 degrees counterclockwise puts it behind a.

Therefore, the sign of dot(a, rot90CCW(b)) tells you whether b is on the right or left of a, where rot90CCW(b) == {x: -b.y, y: b.x}.

Simplyifying:

var dot = a.x*-b.y + a.y*b.x;
if(dot > 0)
    console.log("b on the right of a")
else if(dot < 0)
    console.log("b on the left of a")
else
    console.log("b parallel/antiparallel to a")

Solution 2

In the clarification in a comment from @Eric, "if A points forward, which side of it is B on?"

In this formulation the answer is dead-simple. "A" points forward, as in the example, when its x-coordinate is zero. With this assumption, "B" is on the right when its x-coordinate is positive, is on the left when negative, and is neither when zero.

Extending this clarification to "A" in general position means introducing a new coordinate system, as follows: "In a coordinate system where A points forward, ...". The simplest new coordinate system is the one where the basis vectors are A and (1,0). (If A is a multiple of (1,0), then it's just a 90 degree rotation of the basic situation.) The coordinate transform is L : P = (P_x, P_y) --> P' = (P'_x, P'_y) = (A_y * P_x - A_x * P_y, P_y). This kind of linear transformation is called a skew transformation. The test is the sign of the coordinate P'_x. Check that L takes A to the vector (0,1) in the new coordinate system. This method uses the same arithmetic as the other answer.

I wrote this up so that the deeper geometric content may be illuminating.

Share:
16,909
Eric
Author by

Eric

Roboticist, engineer, and web developer Part of the NumPy development team

Updated on September 19, 2022

Comments

  • Eric
    Eric over 1 year

    Given two 2D vectors, how can you tell whether the second is to the right (clockwise) of the first, or to the left (counter-clockwise)?

    For instance, in these diagram B is to the right (counter-clockwise) of A

    A   B   .       .----> A
    ^  ¬    |\      |   
    | /     | \     |  
    |/      V  \    V 
    .       B   A   B
    
  • eh9
    eh9 over 11 years
    I should point out that if you take your example with 'A' and 'B' as given and instead look at '-A' and '-B', so that each is pointing the opposite way, then -B is to the left of -A. But the dot product is the same, which means your code gives the opposite answer. The way you've defined the problem, your answer is more than just the sign of the dot product.
  • Eric
    Eric over 11 years
    @eh9; no, B should still be on the right if you reverse both. I guess the question is "if A points forward, which side of it is b on"
  • O. Jones
    O. Jones over 9 years
    Welcome to Stack Overflow. You should consider putting this answer in a comment, as it is partly commentary. Otherwise, you should tidy it up and make it a fully usable answer.
  • Eric
    Eric over 9 years
    No, b is on the right (clockwise) of a here, assuming a right-handed coordinate system
  • mfnx
    mfnx over 5 years
    Wouldn't it be easier just using the cross product directly? You start with the dot product, but you finally end up with a cross product (or at least its norm).
  • Eric
    Eric almost 3 years
    Note that the dot product approach is computing dot(a, rot90CCW(b)) not dot(a, b), so it does work when the vectors are orthogonal. But you're correct, another way to write this is det([A, B]).
  • plebmatician
    plebmatician almost 3 years
    Ah, my mistake. +1