+2  A: 

Calculate angle(V1), angle(V2) and angle(v3) (a1, a2, a3).

Modify a2 and a3 (add 2*pi if needed) so that

a1 <= a2 < a1 + 2*pi
a1 <= a3 < a1 + 2*pi

Now you simply have to compare a2 and a3. V3 is between V1 and V2 is resulting a3 is inferior to a2.

Benoît
your answer is right, but I could not select two answers as my final answer,even I hardly can say which is the better: yours or gnovice's answer....
Kamran
I will evaluate to see which answer is faster tomorrow...thanks
Kamran
A: 

To test this condition you have to calculate the winding of two triangles:

  1. The triangle formed by V1, the origin and V3. This triangle must be counter-clockwise.

  2. The triangle formed by V3, the origin and V2. This triangle must be counter-clockwise as well.

To test the winding of a triangle it's enough to check the sign of the 2D cross-product of the vertices.

The test looks like this (sorry - C-code):

int IsBetween (vector v1, vector v2, vector v3)
{
  float winding1 = (v1.x * v3.y - v1.y * v3.x);
  float winding2 = (v3.x * v2.y - v3.y * v2.x);

  // this test could be exactly the wrong way around. This depends
  // on how you define your coordinate system (e.g. is Y going up or down?)

  if ((winding1 <0) && (winding2 < 0))
  {
    printf ("V3 is between them\n");
  }
  else
  {
    printf ("it's not\n");
  }
}
Nils Pipenbrinck
I don't think this method works. for examplse, consider these vectors: angle(V1) = 10, angle(V2)= -10, V3 = 180. V3 is between V1 and V2 when we move around counterclockwise but your method says it isn't.
Kamran
Kamran, could you draw a picture or give cartesian coordinates for your points?
Nils Pipenbrinck
thanks but as you may see in the picture, V1*V3 is positive and V3*V2 also is positive and V3 is between V1 and V2. but according to your method, it isn't between them!
Kamran
+4  A: 

Since you are doing this in MATLAB, here is one solution that should work:

crossProds = [V1(1)*V2(2)-V1(2)*V2(1) ...
              V1(1)*V3(2)-V1(2)*V3(1) ...
              V3(1)*V2(2)-V3(2)*V2(1)];
if (all(crossProds >= 0) || ...
    (crossProds(1) < 0) && ~all(crossProds(2:3) < 0)),
  disp("V3 is between V1 and V2");
else
  disp("out of the interval");
end

EXPLANATION:

The cross product between the 2-D vectors V1 and V2 is stored in the first element of crossProds. This value will be greater than or equal to zero if the counter-clockwise angle between V1 and V2 is between 0 and 180 degrees, inclusive. In this case, when V3 is between V1 and V2 in the counter-clockwise direction then the cross products (V1,V3) and (V3,V2) are also greater than or equal to zero. This explains the first logical check:

all(crossProds >= 0)

If the counter-clockwise angle between V1 and V2 is greater than 180 degrees, then the cross product of these two vectors will be less than zero. In this case, when V3 is between V1 and V2 in the clockwise direction then the cross products (V1,V3) and (V3,V2) are also less than zero. Therefore, if these cross products are not both less than zero then V3 must be between V1 and V2 in the counter-clockwise direction. This explains the next two logical checks:

(crossProds(1) < 0) && ~all(crossProds(2:3) < 0)

The above logical checks should cover all possible situations. The operators || and && are short circuit operators in MATLAB: they will skip the second statements if they are not necessary. For example, if the first statement in an OR is true, there is no reason to check the second statement since only one argument in an OR needs to be true for the result to be true.

gnovice
thanks, but it seems your methos is winding method. as I said to Nils Pipenbrinck, this method did not work.
Kamran
I believe my method is quite different than Nils'. It involves cross products, but has different logical checks.
gnovice
why did you tag it as homework?
Kamran
I didn't tag it as homework, Dinah did. I tagged it as matlab.
gnovice
oh, yes ,excuse me
Kamran
It seems to be working! but could you please explain more about it?
Kamran
Sure, I'll update my answer with a detailed explanation soon.
gnovice
your method works extermely effective...I tested it in hundreds of complicated situations...I uesd it to determine whether a diagonal of a concave polygone is in or out of it. thanks very much...
Kamran
@gnovice what if I am not knowing whether it is clockwise or counterclockwise???
Himadri
@Himadri: When the code given above displays "V3 is between V1 and V2", then V3 is between V1 and V2 when we go from V1 to V2 in a *counter-clockwise* direction. When the code displays "out of the interval", then V3 is between V1 and V2 when we go from V1 to V2 in a *clockwise* direction.
gnovice
@gnovice Yes, I got it. Thanks for your reply.
Himadri
+1  A: 

V1 is a red herring. You're just going to confuse yourself thinking about 3 angles at once.

  1. Rotate everything clockwise by angle(V1)
  2. Normalize the remaining two angles to [0,360)

Now the question is simply to compare norm(angle(V2)-angle(V1)) and norm(angle(V3)-angle(V1)).

related questions