rotation of the cuboid chain

Pages: 12
I asked this question long time before with no success but it was even more complicated situation. I managed to simplify it and the question is now like that:
I have the chain of cuboids and know the coordinates of each individual cuboid.
How to 3d rotate the whole chain in such way that it would not lose its original structure?

Thank you very much.
Picture attached,
https://ibb.co/1d99FkG
You were told one way to do it in your last thread:
http://www.cplusplus.com/forum/beginner/278645/#msg1203051

Create a rotation matrix and just rotate each vertex. If your cubes are stored as centre and orientation vectors then just rotate those instead. If you need to rotate about a point other than the origin then translate-rotate-backtranslate.

You create a SINGLE rotation matrix and rotate all your cubes or other geometry with it: it's as simple as that.

Examples (and theory) were given in that thread. If you choose to ignore it then there's not much else people can do.
Last edited on
Yup, those answers are correct. To rotate a structure about an axis you multiply each point by the appropriate rotation matrix. It really is as simple as that. Read the answers you were given until you understand them.
Last edited on
it simply did not work.
Probably I did not understand. That's not a big problem, much worse that my supervisor did not understand either. In general it means that I have a hard time explaining what exactly I want to do, and you possibly got it wrong (or we just suck in this thing).
I will try to prepare the detail step-by-step workflow to illustrate what I meant. It is not just a simple rotation as all the cubes are intersecting at the particular point and are rotated in respect to each other. As soon as you try to rotate complex geometry like that, the original chain construction is lost. Give me some time please and I will prepare the details.
all the cubes are intersecting at the particular point and are rotated in respect to each other.
There's multiple ways to do this. The specifics depend on how you're representing this structure. How are you storing the cubes?
1. Just the vertices of the cubes in absolute coordinates.
2. Their centroids in absolute coordinates, with the vertices in coordinates relative to the centroids.
3. Something more weird, like the centroids plus a size plus a rotation matrix.
4. Something else entirely.
I would guess (from the funny image in the original post) that the structure consists of
- the chain segments (which probably link opposite cube face centres)
- one side vector normal to the chain segment for each cube.

In this case all you need to do is rotate a set of vectors with the same rotation matrix:
- the start points of each chain;
- each segment of the chain (these are presumably joined end-to-end afterward);
- the side vectors normal to these.
Then you simply draw the cubes again.

What are they supposed to be? Structures of molecules?
Last edited on
It is not yet the detailed explanation I promised, but after 3 month vacation I sat down and looked to this problem again:
- each cuboid bottom face center is the next cuboid top face center and its rotational point. The function that calculates that works well and is tested;
- Rotations of each cube is represented by axis-angle representation. The function that enables rotation, takes axis-angle representation, converts that to quaternions, do the math, gives the new rotation. Works well for the single cuboid in any way, or for the simple geometries. The function is given below;
- and what I noticed FINALLY, that that simple idea of just multiply the old rotation with new rotation works perfectly well if all the axis-angle vector values are positive! It does not work only when it is negative. So it means the unit vector is just opposite and everything must be recalculated, or smth.
So for example, I can rotate around X axis 0.7 rad with {1.0, 0.0, 0.0, 0.7} this structure and it works well:
{{0.79948, 0.504813, 0.325568, 0.0888429},
{ 0.941624, 0.0857279, 0.325568, 6.06663},
{0.940697, 0.0953601, 0.325568, 0.454249}}
But this wont rotate and will turn simply to smth else:
{{-0.79948, 0.504813, 0.325568, 0.0888429},
{ -0.941624, 0.0857279, 0.325568, 6.06663},
{-0.940697, -0.0953601, 0.325568, 0.454249}}

One guy who is good in math (i think so) tried to derive the correct unit vector for negative values and failed (he said it works in the MOST rotation, when I need it to work in ALL rotations). So I am very looking to any kind of solution. Maybe my rotation function that converts axis-angle is not good ? But it works well with negative values for a single cuboid. Really looking for some insights how to solve this. Thank you very much for your time. Main function which does the rotation taking two axis-angle representation is below:
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
void
ExponentialMap::to_quaternion (float& x,
                               float& y,
                               float& z,
                               float& w) const
{
    float s = std::sin(_theta / 2);
    x = _coord_x * s;
    y = _coord_y * s;
    z = _coord_z * s;
    w = std::cos(_theta / 2);
}

void
ExponentialMap::from_quaternion (float& xcoord,
                                 float& ycoord,
                                 float& zcoord,
                                 float& angle,
                                 float x,
                                 float y,
                                 float z,
                                 float w) const
{
    const auto m_pi = getPiValue();
    angle = acosf(w);
    float sinz = sinf(angle);
    if (fabsf(sinz) > 1e-4f) {
        sinz = 1.0f / sinz;
        xcoord = x * sinz;
        ycoord = y * sinz;
        zcoord = z * sinz;
        angle *= 2.0f;
        if (angle > m_pi)
            angle = 2 * m_pi - angle;
    } else {
        angle = 0.0f;
        xcoord = 1.0f;
        ycoord = 0.0f;
        zcoord = 0.0f;
    }
}
ExponentialMap&
ExponentialMap::operator+=(const ExponentialMap& other)
{
    float x0, y0, z0, w0;
    to_quaternion(x0, y0, z0, w0);
    float x1, y1, z1, w1;
    other.to_quaternion(x1, y1, z1, w1);
    auto w2 = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1;
    auto x2 = w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1;
    auto y2 = w0 * y1 + y0 * w1 + z0 * x1 - x0 * z1;
    auto z2 = w0 * z1 + z0 * w1 + x0 * y1 - y0 * x1;
    from_quaternion(_coord_x, _coord_y, _coord_z, _theta, x2, y2, z2, w2);
    return *this;
}
in addition, I have a very poor understanding in this, but somehow believe it is very much related to my problem:


Determining an axis and angle, like determining a quaternion, is only possible up to the sign; that is, (u, θ) and (−u, −θ) correspond to the same rotation matrix, just like q and −q. Additionally, axis–angle extraction presents additional difficulties. The angle can be restricted to be from 0° to 180°, but angles are formally ambiguous by multiples of 360°. When the angle is zero, the axis is undefined. When the angle is 180°, the matrix becomes symmetric, which has implications in extracting the axis. Near multiples of 180°, care is needed to avoid numerical problems: in extracting the angle, a two-argument arctangent with atan2(sin θ, cos θ) equal to θ avoids the insensitivity of arccos; and in computing the axis magnitude in order to force unit magnitude, a brute-force approach can lose accuracy through underflow (Moler & Morrison 1983).
Last edited on
If I got it correctly, possible solution could be the implementation of this :
https://en.m.wikipedia.org/wiki/Rodrigues%27_rotation_formula
That formula is simply how you DERIVE the matrix for a rotation ...
... which you have already been given in your previous thread ...
... and which you seem completely unwilling to look at.

You still haven't told us how you are storing your CUBES.
I don't use any rotation matrix as we use axis-angle representation. You can convert axis-angle to rotation matrix, i believe, just like I did with quaternions, but hereby described process looked quite complex for me: https://en.wikipedia.org/wiki/Rotation_matrix

I just didn't knew about the possibility to make rotation in axis angle notion without conversion. Seems that Rodrigues formula may work. I am checking this now. are you saying you already gave me it in the last thread? sincere apologies, I did not get that then.

That's how typical Polymer chain may look like, i.e. is stored:

1
2
3
4
5
6
7
8
9
10
    Polymer pb({ma, ma, ma, ma, ma, ma, ma, ma, ma}, {"poly2"}, {}, 10.0f, 15.0f, 5.0f,
               {{-0.79948, 0.504813, 0.325568, 0.0888429},
                { -0.941624, 0.0857279, 0.325568, 6.06663},
                {-0.940697, -0.0953601, 0.325568, 0.454249},
                { 0.945361, -0.017274, 0.325568, 0.932644},
                {0.936006, -0.133785, 0.325568, 0.585938},
                {0.0287705, 0.945081, 0.325568, 6.16575},
                {-0.190289, -0.926173, 0.325568, 1.48524},
                {-0.922358, -0.207991, 0.325568, 2.83318},
                { -0.0299494, 0.945044, 0.325568, 2.60525}});

Last edited on
That's how typical Polymer chain may look like, i.e. is stored
OK, that a typical polymer chain storage example. Now, how do YOU store your cubes?
I meant that this is exactly how I store the cubes. "ma" describes length/width/height, and the cube chain is described as stated above: the beginning coordinates, and each cuboid rotational axis and angle.

I tried to recalculate the unit vector using Rodriguez formula, unfortunately again it works only in certain cases, i.e. does not work properly:

1
2
3
4
    float angle = _theta + other._theta;
    Vector3 r = Vector3(other._coord_x, other._coord_y, other._coord_z).normalize();
    Vector3 p = Vector3(_coord_x, _coord_y, _coord_z);
    Vector3 q = (1 - cos(angle)) * p.dot(r) * r + cos(angle) * p + sin(angle) * r.cross(p);
all my rotations are implemented through axis-angle notion:
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
ExponentialMap::ExponentialMap()
    : _coord_x(0.0f)
    , _coord_y(0.0f)
    , _coord_z(0.0f)
    , _theta(0.0f)
{
}

void
ExponentialMap::rotate (float& x,
                       float& y,
                       float& z,
                       const float rx,
                       const float ry,
                       const float rz) const
{
    const float tsin = std::sin(_theta);
    const float tcos = std::cos(_theta);
    x = rx * tcos;
    y = ry * tcos;
    z = rz * tcos;
    const float vx = _coord_y * rz - _coord_z * ry;
    const float vy = _coord_z * rx - _coord_x * rz;
    const float vz = _coord_x * ry  - _coord_y * rx;
    x += tsin * vx;
    y += tsin * vy;
    z += tsin * vz;
    const float fp = _coord_x * rx + _coord_y * ry + _coord_z * rz;
    const float tfact = (1.0f - tcos) * fp;
    x += tfact * _coord_x;
    y += tfact * _coord_y;
    z += tfact * _coord_z;
}
So ok, and I of course get your idea, that with rotational matrix any rotation should be fairly easy?
So probably I need to try to convert axis-angle to rotation matrix...
https://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToMatrix/index.htm
Ok, I was wrong, the problem its not here. Sorry for confusion.

I am not experienced and got into the field where I have a poor understanding.

The problem is not with rotation, the problem is with translation, i.e. each cuboid has a relative position i.e. each cube has depended coordinate system based on the previous cuboid position.

Possible solution is to find a way to rotate the first cube - move the second to it - rotate the second - move the third to it. etc.

Sorry for confusion.
The problem is not with rotation, the problem is with translation
Possible solution is to find a way to rotate the first cube
Well, which is it? Do you need rotation or translation? If you just need to translate the entire structure and every cube has its position relative to a previous cube, all you need is to translate the first cube.
Thank you very much for your attention in this complicated situation. The problem is not trivial at all - this I can guarantee. I just was not able to explain it in the beginning as had poor understanding in it .
So at least finally I can clear the situation up:

- every cuboid has a position dependent on the previous cube;
- every cuboid's rotation is described by its own axis-angle notion, i.e. it has a vector and angle. Important: the point of rotation is the bottom center point of each cube.

And so we have such chain where every cuboid has a different rotation in respect with each other and in the relevant coordinate system. And I want now to rotate the whole structure around the bottom center of the VERY FIRST CUBE.

- I rotate the first cube, no problem;
- I calculate its new position and move the second cube;
- Now, I cannot apply the same rotation as for the first cube - because then the second cube will just rotate about its own bottom center.

and I cannot use just global vertice coordinates - the whole setup must remain as it is, only with relative vector - angle.
As far as I understand it now, I must find a way how to rotate additionally each cube (starting from nr 2) rotation vector, and it should be individual for each cube.
Please find the attached schematics.
Thank you for your attention and patience,
https://ibb.co/cLJ6TLy


- every cuboid has a position dependent on the previous cube;
"Dependent" is rather vague. Can you be more specific?

- every cuboid's rotation is described by its own axis-angle notion, i.e. it has a vector and angle. Important: the point of rotation is the bottom center point of each cube.
What does "bottom" mean?
If rotation is zero, is the cube always axis-aligned, or does its orientation depend on the previous cube?
Last edited on
Pages: 12