I'm working on a simple rotate routine which normalizes an objects rotation between 0 and 360 degrees. My C# code seems to be working but I'm not entirely happy with it. Can anyone improve on the code below making it a bit more robust?
public void Rotate(int degrees)
{
this.orientation += degrees;
if (this.orientation < 0)
{
while (this.orientation < 0)
{
this.orientation += 360;
}
}
else if (this.orientation >= 360)
{
while (this.orientation >= 360)
{
this.orientation -= 360;
}
}
}
I prefer to avoid loops, conditionals, arbitrary offsets (3600), and
Math.____()
calls:formula for re-orienting circular values i.e to keep angle between 0 and 359 is:
generalized formula for shifting angle orientation can be:
in which value of shift represent circular shift for e.g I want values in -179 to 180 then it can be represented as: angle + Math.ceil( (-angle-179) / 360 ) * 360
Function that comes handy when normalizing angles (degrees) into interval [0, 360> :
This can be simplified to the following.
C# follows the same rules as C and C++ and
i % 360
will give you a value between-359
and359
for any integer, then the second line is to ensure it's in the range 0 through 359 inclusive.If you wanted to be shifty, you could get it down to one line:
which would keep it positive under all conditions but that's a nasty hack for saving one line of code, so I wouldn't do it, but I will explain it.
From
degrees % 360
you will get a number between-359
and359
. Adding360
will modify the range to between1
and719
. Iforientation
is already positive, adding this will guarantee it still is, and the final% 360
will bring it back to the range0
through359
.At a bare minimum, you could simplify your code since the
if
s andwhile
s can be combined. For example, the result of the conditions in these two lines:is always the same, hence you don't need the surrounding
if
.So, to that end, you could do:
but I'd still go for the modulus version since it avoids loops. This will be important when a user enters 360,000,000,000 for the rotation (and they will do this, believe me) and then find they have to take an early lunch while your code grinds away :-)
Add any multiple of 360 degrees between which your possible input values could be (to take it above zero), and just take the remaining with %, like this
The case above can take input angles down to -3600. You can add any number (multiple of 360) crazily high that would make the input value positive first.
Usually during an animation, your previous frame/step value would probably be already normalized by the previous step, so you'll be good to go by just adding 360:
Use modulo arithmetic: