Question

I have coordinates (x,y,z) of the center of spheres stored in a numpy array. I want be able to rotate the spheres with respect to the z-axis but am getting weird results. My code does the rotation but it seems to also be moving it up and right. Maybe this is an intended result from the rotation, but I don't think it is. Here is my code:

theta = math.pi/6
ct = math.cos(theta)
st = math.sin(theta)
z = np.array([[ct, -st, 0], [st, ct, 0], [0, 0, 1]])
self.atoms = np.array([[90,100, 1], [140,100, 1]])
self.atoms = self.atoms.dot(z)

Here is what the image looked like before the rotation:

enter image description here

and here is what it looks like after:

enter image description here

Was it helpful?

Solution

You have to translate the entire system so that the center of the rotation is the center of the system.

The equations used for rotation that you use work only if rotating around the origin.

For the translation you can also multiply with a matrix having the direction of translation as the last row.

Anyway, the entire transformation is P' = inv(T) * R * T * P (where P is each point of the figure and P' is where it will be in the final result, see example) For the inverse of the translation matrix simply negate the sign of the translation components.

Edit (worked out example -- you might have to transpose everything -- switch rows with columns):

You start with the points placed at:

atoms =
    90   140
   100   100
     1     1

which is presented in

Two horizontal points

Then you apply a rotation with matrix

R =
   0.86603  -0.50000   0.00000
   0.50000   0.86603   0.00000
   0.00000   0.00000   1.00000

and get a result of

R * atoms =
    27.9423    71.2436
   131.6025   156.6025
     1.0000     1.0000

which translates into (as you observed, the red points are the new ones)

Rotated but not ok

The problem is that by doing R * atoms we rotate around the origin. In the following figure, the angle between the two blue lines is exactly pi/6

Rotated

Now, we'd like to obtain the blue circles in:

Final result

To do this we need several steps:

  • Build a translation matrix to convert the points such that the center of the rotation is the center of the axes:

    T =
     1     0  -115
     0     1  -100
     0     0     1
    

    (the -115 and -100 are the negatives of the center of the atoms)

  • Translate the points such that the two centers overlap (and we get the red atoms)

    T * atoms =
      -25   25
        0    0
        1    1
    

    (observe that our new two points are symmetrical around the origin)

  • Rotate the new points (and we get the green circles)

    R * T * atoms
      -21.6506   21.6506
      -12.5000   12.5000
        1.0000    1.0000
    
  • Finally, translate everything back

    inv(T) * R * T * atoms =        
        93.3494   136.6506
        87.5000   112.5000
         1.0000     1.0000
    

Final remarks:

  1. The output that you've obtained is explicable due to the fact that my origin is in the lower corner/middle of the figure while yours is in the upper corner.

  2. Because of this you might have to also reverse the order of the multiplications: point * translation * rotation * translation. Check what works properly.

  3. I cheated a little and did the transformation on both points at the same time. Luckily, the results are the same as if doing the transformation on each point in turn.

  4. Every 2D/3D transform can be written in term of matrices. We use 3x3 matrices for 2D and 4x4 for 3D for this. Basically, we work with Homogenous coordinates

  5. Finally, see Transformation matrix for more examples and details.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top