Rotate a 3D rectangle in z axis in C++ when rectangle is described with arrays

I am learning C++. I need a simple example of how rotation can be done (probably using rotation matrix) in C++ language for the 3D rectangle when it is described as arrays where separate arrays hold x, y and z coordinates of rectangle corners.

I would really appreciate a clear example how exactly should I program let's say 50 degrees rotation in Z axis around its center and extract the new coordinates.

1
2
3
  Rectangle3D rect({1.0f, 5.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f},
                   {3.0f, 6.0f, 3.0f, 7.0f, 2.0f, 9.0f, 5.0f, 2.0f},
                   {2.0f, 4.0f, 6.0f, 2.0f, 2.0f, 1.0f, 2.0f, 5.0f});
Forget about C++ for now. What is the math involved? Given a point (x,y,z) and an angle a, what point represents (x,y,z), rotated by "a" radians about the origin?
That's the problem that this type of math is new to me too. I learned only and kinda know that this should be somehow used there:


The quaternion in terms of axis-angle is:

q = cos(a/2) + i ( x * sin(a/2)) + j (y * sin(a/2)) + k ( z * sin(a/2))

where:

a=angle of rotation.
x,y,z = vector representing axis of rotation.

A rectangle is not generally defined by 8-3D coordinates. A cuboid is. A rectangle is defined by 4-3D points and makes life a little easier.

Either way though - for the transforms see
https://en.wikipedia.org/wiki/Rotation_matrix
and by the look of it you need the 3D version and either expand the transform or do some matrix work/multiplication using an array of corners.
That's fine, but I am struggling to find a good example to learn from it. Unfortunately in my current knowledge of programming and rotational maths I could benefit only from well described example.
rotation in Z axis around its center

Points on the axis of rotation do not move.

A quaternion or 3x3 matrix rotates around axis that goes through (0,0,0).

If by "its center" you mean the center of the rectangle, then you should
1. Translate the rectangle so that its center is at (0,0,0)
2. Rotate
3. Translate reactangle so that center returns to its original location

The quaternion ...
x,y,z = vector representing axis of rotation.

The vector has to have unit-length; (0,0,1) and (0,0,42) do not produce the same quaternion.

A quaternion is a convenient way to store a rotation, but the equation to rotate vector with quaternion is not simple. One can also compute 3x3 matrix from quaternion and then rotate vectors with that matrix.

Since you have the axis as (0,0,1), it is simpler to compute the matrix directly.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include <iostream>
#include <iomanip>
#include <vector>
#include <cmath>
#include <cassert>
using namespace std;

using matrix = vector< vector<double> >;
const double PI = 4.0 * atan( 1.0 );

//======================================================================

// Rotation matrix for axis n, rotation angle in radians
// Sense of rotation is right-handed screw when looking in the direction of n
matrix rotationMatrix( vector<double> n, double angle )
{
   double C = cos( angle ), S = sin( angle );

   // Normalise n
   double mag = sqrt( n[0] * n[0] + n[1] * n[1] + n[2] * n[2] );
   n[0] /= mag;   n[1] /= mag;   n[2] /= mag;

   // Create rotation matrix
   matrix R( 3, vector<double>( 3 ) );
   R[0][0] = C + n[0] * n[0] * ( 1.0 - C )           ;
   R[0][1] =     n[0] * n[1] * ( 1.0 - C ) - n[2] * S;
   R[0][2] =     n[0] * n[2] * ( 1.0 - C ) + n[1] * S;
   R[1][1] = C + n[1] * n[1] * ( 1.0 - C )           ;
   R[1][2] =     n[1] * n[2] * ( 1.0 - C ) - n[0] * S;
   R[1][0] =     n[1] * n[0] * ( 1.0 - C ) + n[2] * S;
   R[2][2] = C + n[2] * n[2] * ( 1.0 - C )           ;
   R[2][0] =     n[2] * n[0] * ( 1.0 - C ) - n[1] * S;
   R[2][1] =     n[2] * n[1] * ( 1.0 - C ) + n[0] * S;

   return R;
}

//======================================================================

ostream & operator << ( ostream &out, const vector<double> &V )
{
   out << fixed << setprecision( 4 );
   for ( double e : V ) out << setw( 8 ) << e << ' ';
   return out;
}

//======================================================================

vector<double> matmul( const matrix &M, vector<double> x )
{
   int m = M.size(), n = M[0].size();   assert( n == x.size() );

   vector<double> y( m, 0.0 );
   for ( int i = 0; i < m; i++ )
   {
      for ( int j = 0; j < n; j++ ) y[i] += M[i][j] * x[j];
   }

   return y;
}

//======================================================================


int main()
{
   vector<double> n = { 0.0, 0.0, 1.0 };    // rotation axis (here, z axis)
   double degrees = 50;                     // rotation angle in degrees (anticlockwise seen from +z)

   matrix R = rotationMatrix( n, degrees * PI / 180.0 );
 
   // Set some vertices of a cuboid
   vector< vector<double> > vertices = { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 },
                                         { 0, 0, 1 }, { 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 }  };

   cout << "Points before rotation:\n";
   for ( auto pt : vertices ) cout << pt << '\n';

   cout << "\nPoints after rotation:\n";
   for ( auto pt : vertices ) cout << matmul( R, pt ) << '\n';
}

Points before rotation:
  0.0000   0.0000   0.0000 
  1.0000   0.0000   0.0000 
  1.0000   1.0000   0.0000 
  0.0000   1.0000   0.0000 
  0.0000   0.0000   1.0000 
  1.0000   0.0000   1.0000 
  1.0000   1.0000   1.0000 
  0.0000   1.0000   1.0000 

Points after rotation:
  0.0000   0.0000   0.0000 
  0.6428   0.7660   0.0000 
 -0.1233   1.4088   0.0000 
 -0.7660   0.6428   0.0000 
  0.0000   0.0000   1.0000 
  0.6428   0.7660   1.0000 
 -0.1233   1.4088   1.0000 
 -0.7660   0.6428   1.0000 
Dear all, and especially lastchance,

Big thanks for your contribution and time, I will analyze everything and will try apply for my problem. Really appreciated!
Because the axis of rotation is the z axis, the z coordinate remains unchanged. The transformed (new) coordinates of a corner (x,y,z) for anti-clockwise rotation angle 'a' are:

x' = xCos(a) - ySin(a)
y' = xSin(a) + yCos(a)
z' = z

Remember if you use the <cmath> trig functions, angles are measured in radians where 360 degrees = 2.PI radians.

So for a point (7,8,9) and rotation 50 degrees ( a = 50/360 * (2*PI) )

x' = 7Cos(a) - 8Sin(a)
y' = 7Sin(a) + 8Cos(a)
z' = 9
Last edited on
Thank you , now I have better understanding - thanks again!
Topic archived. No new replies allowed.