I have 3 angles a b c
a=315 b=20 c=45
ok so would like to know giving all three if b is in between a and c
i have the long way of doing this adding a
I personally had the same problem recently and found counterexamples for all the answers posted yet, so I will share my own approach.
Let a
be the start angle and b
the end angle and we are checking whether c
is between them clockwise, that means when you go from a
to b
you must pass c
. The approach of checking whether c
is in the range from a
to b
gives you false positives when b
is greater than a
numerically. For example:
a=80°, b=320° and c=150°: a <= c <= b
which would mean that c
is between a
and b
.
But it isn't.
The approach that's working is to subtract 360 from b
if it is greater than a
and also subtract 360 from c
if c
is greater than a
. Then check whether a <= c <= b
.
In Java:
public static boolean isBetween(double c, double a, double b) {
if (b > a) b -= 360;
if (c > a) c -= 360;
return a <= c && c <= b;
}
This assumes that a, b and c are in range 0 to 360.
Some example:
isBetween(150, 80, 320) => false
isBetween(30, 80, 320) => true
isBetween(340, 80, 320) => true
isBetween(140, 0, 160) => true
isBetween(180, 0, 160) => false
Assuming a > c
, you would actually use:
( b < a ) && ( b > c )
This is the same as checking if a value is between a lower and upper bound. Them being angles makes no difference, unless you want to take into account the fact that as you go round a circle, an angle of 405
is the same as an angle of 45
. In which case you can just use a % 360
to get the angle betweeen 0
and 360
.
1st off, every angle is between 2 other angles, what you're really asking is:
You can just go ahead and define a as the leftmost angle and b as the rightmost angle or you can solve for that, for example if either of these statements are true a is your leftmost angle:
For simplicity let's say that your leftmost angle is l and your rightmost angle is r and you're trying to find if g is between them.
The problem here is the seem. There are essentially 3 positive cases that we're looking for:
If you're just defining a to be leftmost and b to be rightmost you're done here and your condition will look like:
a <= g && g <= b ||
a <= g && b < a ||
g <= b && b < a
If however you calculated the l and r you'll notice there is an optimization opportunity here in doing both processes at once. Your function will look like:
if(a <= b) {
if(b - a <= PI) {
return a <= g && g <= b;
} else {
return b <= g || g <= a;
}
} else {
if(a - b <= PI) {
return b <= g && g <= a;
} else {
return a <= g || g <= b;
}
}
Or if you need it you could expand into this nightmare condition:
a <= b ?
(b - a <= PI && a <= g && g <= b) || (b - a > PI && (b <= g || g <= a)) :
(a - b <= PI && b <= g && g <= a) || (a - b > PI && (a <= g || g <= b))
Note that all this math presumes that your input is in radians and in the range [0 : 2π].
Live Example
I had a similar problem. I got it. All the calculations are in degrees. I needed to calculate id a gps location is inside a rectangle.
Or, I needed to see if an angle x
is between angle check+r
and angle check-r
.
check-r<x<check+r
.
If you need a<x<b
, find the angle check
in the middle of a
and b
and then the distance (r
) of check
from a
or b
.
The method normalize, changes the angles from -infinity...infinity to -180...180.
The method check, takes the arguments
x
: the angle that we need to see if it is between the angles check-r and check+r.
check
: the angle to check with.
r
: the radius around angle check.
private static double normalize(double x) {
x = x % 360;
if (x>=180) {
return x-360;
}
if (x<-180) {
return x+360;
}
return x;
}
public static boolean check(double x, double check, double r) {
x = x - check;
x = normalize(x);
return x<r && x>-r;
}