How to wrap around a range

后端 未结 7 835
夕颜
夕颜 2020-12-05 04:39

Angles in my program are expressed in 0 to 2pi. I want a way to add two angles and have it wrap around the 2pi to 0 if the result is higher than 2pi. Or if I subtracted an a

7条回答
  •  一生所求
    2020-12-05 05:29

    Depending on your use case there are some efficient special cases if you have the luxury of choosing your own representation of an angle. (Note that having 0 as the lower bound is already a special case allowing for efficiency.)

    Expressing angles as unit vectors

    If you are able to represent angles as values between [0 and 1) instead of [0 and 2π) then you merely need to take the fractional part:

    float wrap(float angle) {
        // wrap between [0 and 2*PI)
        return angle - floor(angle);
    }
    

    Negative angles just work.

    You can also normalize, wrap, then scale back to radians with some loss of precision and efficiency.

    This can be useful in code that works similar to a lot of shader code, and especially in an "everything is a unit vector" environment.

    Expressing angles as unsigned integers limited at a power of two

    If you are able to represent angles as values between [0 and 2^n) instead of [0 and 2π) then you can wrap them to within a power of two with a bitwise and operation:

    unsigned int wrap(unsigned int angle) {
        // wrap between [0 and 65,535)
        return angle & 0xffff;
    }
    

    Even better, if you can choose a power of two that's equal to the size of an integer type, the numbers just wrap naturally. A uint16_t always wraps to within [0 and 2^16) and a uint32_t always wraps to within [0 and 2^32). Sixty five thousand headings should be enough for anyone right? (-:

    I used this in game and demo type things in the 8-bit days and even for texture mapping before 3D graphics cards. I suppose it would still be useful in code for emulators and retrogaming but perhaps even on tiny microcontrollers?

提交回复
热议问题