'How to recalculate the coordinates of a point after scaling and rotation?

I have the coordinates of 6 points in an image

(170.01954650878906, 216.98866271972656)
(201.3812255859375, 109.42137145996094)
(115.70114135742188, 210.4272918701172)
(45.42426300048828, 97.89037322998047)
(167.0367889404297, 208.9329833984375)
(70.13690185546875, 140.90538024902344)

I have a point as center [89.2458, 121.0896]. I am trying to re-calculate the position of points in python using 4 rotation degree (from 0,90,-90,180) and 6 scaling factor (0.5,0.75,1,1.10,1.25,1.35,1.5).
My question is how can I rotate and scale the abovementioned points relative to the center point and get the new coordinates of those 6 points?

Your help is really appreciated.



Solution 1:[1]

Mathematics

A mathematical approach would be to represent this data as vectors from the center to the image-points, translate these vectors to the origin, apply the transformation and relocate them around the center point. Let's look at how this works in detail.

Representation as vectors

We can show these vectors in a grid, this will produce following image

Representation of the given points as vectors around the center point

This image provides a nice way to look at these points, so we can see our actions happening in a visual way. The center point is marked with a dot at the beginning of all the arrows, and the end of each arrow is the location of one of the points supplied in the question.

A vector can be seen as a list of the values of the coordinates of the point so

my_vector = [point[0], point[1]]

could be a representation for a vector in python, it just holds the coordinates of a point, so the format in the question could be used as is! Notice that I will use the position 0 for the x-coordinate and 1 for the y-coordinate throughout my answer.

I have only added this representation as a visual aid, we can look at any set of two points as being a vector, no calculation is needed, this is only a different way of looking at those points.

Translation to origin

The first calculations happen here. We need to translate all these vectors to the origin. We can very easily do this by subtracting the location of the center point from all the other points, for example (can be done in a simple loop):

point_origin_x = point[0] - center_point[0] # Xvalue point - Xvalue center
point_origin_y = point[1] - center_point[1] # Yvalue point - Yvalue center

The resulting points can now be rotated around the origin and scaled with respect to the origin. The new points (as vectors) look like this:

The same vectors as above, but translated around the origin

In this image, I deliberately left the scale untouched, so that it is clear that these are exactly the same vectors (arrows), in size and orientation, only shifted to be around (0, 0).

Why the origin

So why translate these points to the origin? Well, rotations and scaling actions are easy to do (mathematically) around the origin and not as easy around other points.

Also, from now on, I will only include the 1st, 2nd and 4th point in these images to save some space.

Scaling around the origin

A scaling operation is very easy around the origin. Just multiply the coordinates of the point with the factor of the scaling:

scaled_point_x = point[0] * scaling_factor
scaled_point_y = point[1] * scaling_factor

In a visual way, that looks like this (scaling all by 1.5):

Scaled vectors and original vectors

Where the blue arrows are the original vectors and the red ones are the scaled vectors.

Rotating

Now for rotating. This is a little bit harder, because a rotation is most generally described by a matrix multiplication with this vector.

The matrix to multiply with is the following

rotation matrix

(from wikipedia: Rotation Matrix)

So if V is the vector than we need to perform V_r = R(t) * V to get the rotated vector V_r. This rotation will always be counterclockwise! In order to rotate clockwise, we simply need to use R(-t).

Because only multiples of 90° are needed in the question, the matrix becomes a almost trivial. For a rotation of 90° counterclockwise, the matrix is:

Rotation matrix for 90° counterclockwise

Which is basically in code:

rotated_point_x = -point[1]    # new x is negative of old y
rotated_point_y = point[0]     # new y is old x

Again, this can be nicely shown in a visual way:

rotation 90° counterclockwise

Where I have matched the colors of the vectors.

A rotation 90° clockwise will than be

rotated_counter_point_x = point[1]    # x is old y
rotated_counter_point_y = -point[0]   # y is negative of old x

A rotation of 180° will just be taking the negative coordinates or, you could just scale by a factor of -1, which is essentially the same.

As last point of these operations, might I add that you can scale and/or rotated as much as you want in a sequence to get the desired result.

Translating back to the center point

After the scaling actions and/or rotations the only thing left is te retranslate the vectors to the center point.

retranslated_point_x = new_point[0] + center_point_x
retranslated_point_y = new_point[1] + center_point_y

And all is done.

Just a recap

So to recap this long post:

  1. Subtract the coordinates of the center point from the coordinates of the image-point
  2. Scale by a factor with a simply multiplication of the coordinates
  3. Use the idea of the matrix multiplication to think about the rotation (you can easily find these things on Google or Wikipedia).
  4. Add the coordinates of the center point to the new coordinates of the image-point

I realize now that I could have just given this recap, but now there is at least some visual aid and a slight mathematical background in this post, which is also nice. I really believe that such problems should be looked at from a mathematical angle, the mathematical description can help a lot.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Community