Home > OS >  Best way to rotate (and translate) a set of points in python
Best way to rotate (and translate) a set of points in python

Time:11-22

I have two sets of points (x,y) that I have plotted with matplotlib

Just visually I can see that it seems there is some kind of rotation between those.

I would like to rotate one set of points around a certain point (would like to try several points of rotation) and plot them again.

What would be the best way to rotate said set of points with python?

I have read that perhaps shapely could be used but a simple example would help me understand how.

CodePudding user response:

Use numpy to store your points

For example, if you have a nx2 array, each line being a point, like this

xy=np.array([[50, 60],
             [10, 30],
             [30, 10]])

You can plot them like this

plt.scatter(xy[:,0], xy[:,1])

And to rotate them, you need a rotation matrix

def rotateMatrix(a):
    return np.array([[np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]])

You can apply this matrix to your xy set of points like this

newxy = xy @ rotateMatrix(a).T

Note that I transpose the rotation matrix, to keep acuracy. But, in this case, because of the specific form of rotation matrix, you could generate directly the transposed one by just passing -a

newxy = xy @ rotateMatrix(-a)

If you need no rotate around a center (x0,y0) other than (0,0), just rotate not xy but xy-(x0,y0) (that is the displacement vector from center to points), and then add that rotated vector to the center.

newxy = (xy-[x0,y0]) @ rotateMatrix(-a)   [x0,y0]

Application

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib
import time

def rotateMatrix(a):
    return np.array([[np.cos(a), -np.sin(a)], [np.sin(a), np.cos(a)]])

xy=np.random.randint(0,100, (200,2))

fig=plt.figure()
plt.plot(xy[:,0], xy[:,1], 'o')
plt.xlim(-30,130)
plt.ylim(-50,110)

plotdata,=plt.plot(xy[:,0], xy[:,1],'o')

x0=20
y0=50

def anim(i):
   newxy=(xy-[x0,y0]) @ rotateMatrix(-2*i*np.pi/180)   [x0,y0]
   plotdata.set_data(newxy[:,0], newxy[:,1])
   return [plotdata]

theAnim=animation.FuncAnimation(fig, anim, interval=40, blit=False, frames=360, repeat=False)
#theAnim.save('rotate.nosync.gif')
plt.show()

enter image description here

  • Related