Go to notes and algorithms index. ~ Go to home page.

rotate_2D_with_sine_and_cosine() Rotate a vector.


Integer version.

This routine does a rotation without using matrices. Like rotation matrices it uses sine and cosine to do the job (although if your using a graphics system like direct x that populates rotation matrices for you, you may never realise that rotation matrices are just an automated way of applying sines and cosines).

If you do not have a graphics system like direct x that handles matrices for you, and you just want to do some 2D rotations and not be bothered with setting-up matrix structures or classes and all that, then this method might be a good alternative.

The routine name suggests that it can only do 2D rotations... but actually, thinking about it, you could do 3D rotations with it, but only one axis at a time. To do that: instead of specifying x and y you'll need to specify the appropriate ordinate pair for the particular axis you want to rotate around. so when you specify x and y you are actually doing a rotation about the Z axis. so basically for the axis you want to rotate around you have to specify the ordinate pair that have the remaining two initials. You may have to do some experimenting, for instance by swapping the pair of ordinates, or changing a sign, so that the results match the rotations in your co-ordinate system (e.g. you may find you're getting clockwise rotations for a certain axis whereas you might want anticlockwise rotations).

Basic usage: calculate the sine and cosine for the angle you want to rotate a vector by and pass it along with the vector to this routine.

Note that this is an integer maths routine and so it's only really suitible for usinging in programs that use integer maths where, typically, you'll have sine and cosine represented by values that are multiplied by 256 (left shift 8 bits) or some other "*2 to the power of" value.

If you wanted to use this in an floating point program then best convert it to floating-point, but if you just wanted to try it out you could for example multiply all the values by 256 and copy them into temporary integer variables before passing them and specify p_shift as 8... then copy the result from a temporary integer variable into a float and divide by 256.

VECTOR_2D is just a simple structure of long x and long y which you can replace with your own structure (or you could make it 2 separate parameters).



void rotate_2D_with_sine_and_cosine( VECTOR_2D *p_vector_ptr, short p_sine, short p_cosine, short p_shift )
   {
   // (c) Jon P 2001.
   //
   // This routine will rotate a vector about 0,0 by using the pre-calculated sine
   // and cosine supplied as parameters p_sine and p_cosine.
   //
   // The point of  making the calling code calulate the sine and cosine
   // instead of doing it in this routine is because typically you want
   // to rotate many vectors by the same angle (or many point positions
   // within an object) -- so it would be a wast to do the same sine and
   // cosine look-up many times.
   //
   // 'p_shift' should be specified as the number of bits the the sine and
   // cosine are shifted by (this depends on your integer maths used in the
   // calling code....
   // ....for example if p_sine and p_cosine are between -256 to 256
   //     (where 256 is the sine of 90 degrees) then p_shift should be specified as 8.
   //
   // If you use gradient_8_to_sine_8() and gradient_8_to_cosine_8() to get the
   // p_sine and p_cosine values then specify p_shift as 8.
   //
   long temp, x, y;

   #if DIAGS
      // ### needs checks in here to prevent overflows (especially if p_shift is big)
   #endif

   x = 0 - p_vector_ptr->y;
   x *= p_sine;
   temp = p_vector_ptr->x * p_cosine;
   x += temp;
   x >>= p_shift;
   
   y = p_vector_ptr->y;
   y *= p_cosine;
   temp = p_vector_ptr->x * p_sine;
   y += temp;
   y >>= p_shift;
   
   p_vector_ptr->x = x;
   p_vector_ptr->y = y;
   }