Angle A is a degree angle that keeps increasing by increments and Angle B is the stopping point of Angle A (think ‘Spin-the-bottle’ where Angle A is the current angle of the bottle Angle B is the angle needed to point to your crush and the bottle spins at a fixed rate clock-wise).
To do this, I’ve been trying to compare Angle A and Angle B with inequalities. If Angle A is 60 degrees and Angle B is 80 degrees, this is no problem. If Angle A is 350 degrees and Angle B is 10 degrees however, the inequality thinks that Angle A has crossed Angle B even though it hasn’t.
How do I compare angles when they wraparound at 360 degrees?
This is some pseudo-code for what I have so far:
int AngleB = 30;
int AngleA = 300;
void Update() {
AngleA += 13;
if (AngleA > AngleB) {
AngleA = AngleB;
}
}
Update: Here’s my new method that wraps Angle A relative to Angle B:
double GetAngleDifference(double from, double to)
{
double difference = to - from;
while (difference < -180) double += 360;
while (difference > 180) double-= 360;
return difference;
}
3
Any angle is equivalent to the angle + 360 degrees.
So if you are increasing a
, but a > b
(numerically), then add 360 to b
at the start. Now a < b
works for your loop.
e.g.
a = 270
b = 45
b += 360 // = 405
while (a < b)
a += ... // 270 up to 405
If you are decreasing a
but b > a
(numerically), then add 360 to a
at the start. Now a > b
works for your loop.
e.g.
a = 10
b = 310
a += 360 // = 370
while (a > b)
a -= ... // 370 down to 310
That’s not the full pseudocode, but illustrates the two cases where you need to worry about “crossing” the 360 mark.
1
If the question is How do I detect whether A has crossed B? you might use the following logic:
a := A mod 360.
b := B mod 360.
prev := a > b.
A := A + 13.
a := A mod 360.
current := a > b.
Return: current not = prev
The pseudo-code above returns with TRUE if, and only if, A has crossed B. This means that you should update the position of A and, at the same time, find out whether the cross just happened.
3
I don’t completely understand the problem being posed, but I suspect that it would be useful to find the smallest angle between AngleA and AngleB, where the smallest angle is in the range -180 to 180. This can be done with modulo arithmetic.
Most programming languages have some form of a modulo function, but their behavior varies, see wikipedia page. In order to find the smallest angle, you actually want to use a modulo function that rounds to the nearest integer. It turns out this isn’t very common. However, it is rather simple to implement (as described at link):
double ModNearestInt(double a, double b) {
return a - b * round(a / b);
}
The has the nice property that the remainder returned is
- always in the interval [-b/2, +b/2]
- always the shortest distance to zero
So, to find the smallest angle between AngleA and AngleB, you could do:
double smallestAngle = ModNearestInt(AngleA - AngleB, 360.0);
To detect A crossing B in the positive direction if it is known that AngleA is increasing, it is sufficient to check to see that smallestAngle changes sign from negative to positive. When the sign of smallestAngle changes from positive to negative and AngleA is increasing, this corresponds to A crossing (B + 180). Similarly, if it is known that AngleA is decreasing, then A crosses B when the sign of smallestAngle changes from positive to negative.
How do deal with angle wraparounds when comparing them?
Given, AngleA, AngleB
there is more than one difference. Below the differences are 270 and -90 depending if we move clock-wise or counter clock-wise.
int AngleA = 30;
int AngleB = 300;
Possible conventions:
1) Angle with the smaller magnitude: -90.
2) Smaller of the 2 magnitudes: 90.
3) In a fixed rotation: e.g. clockwise 270.
4) Both: -90, 270.
Let us continue with #3 or 270 degrees given OP’s double from, double to
code.
How do I compare angles when they wraparound at 360 degrees?
First consideration is what is the domain of from,to
?
Could they be any value or are they restricted to [-360…360] or [0…360) or what?
Let us assume [-360…360].
Next, consider type:
For int
, use %
, the remainder operator.
For double
, use fmod
, the remainder function.
Remainder differs from mod.
When the goal is for the answer to lie in [0…360)….
With integers, this is simple.
int GetAngleDifferenceClockwise_int(int from, int to) {
int diff = (from - to)%360; // diff now in (-360 ... 360) range
if (diff < 0) diff += 360; // diff now in [ 0 ... 360) range
return diff;
}
With double
, this more interesting. To preserve precision, usually the target range is [-180 … 180) rather than [0 … 360).
double GetAngleDifferenceClockwise_double(double from, double to) {
double diff = fmod(from - to, 360.0); // diff now in (-360.0 ... 360.0) range
if (diff >= 180.0) diff -= 360.0; // diff now in (-360.0 ... 180.0) range
else if (diff < -180.0) diff += 360.0;// diff now in [-180.0 ... 180.0) range
return diff;
}