Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Rotate X,Y (2D) coordinates around a point or origin in Python
"""
Lyle Scott, III // lyle@ls3.io
Multiple ways to rotate a 2D point around the origin / a point.
Timer benchmark results @ https://gist.github.com/LyleScott/d17e9d314fbe6fc29767d8c5c029c362
"""
from __future__ import print_function
import math
import numpy as np
def rotate_via_numpy(xy, radians):
"""Use numpy to build a rotation matrix and take the dot product."""
x, y = xy
c, s = np.cos(radians), np.sin(radians)
j = np.matrix([[c, s], [-s, c]])
m = np.dot(j, [x, y])
return float(m.T[0]), float(m.T[1])
def rotate_origin_only(xy, radians):
"""Only rotate a point around the origin (0, 0)."""
x, y = xy
xx = x * math.cos(radians) + y * math.sin(radians)
yy = -x * math.sin(radians) + y * math.cos(radians)
return xx, yy
def rotate_around_point_lowperf(point, radians, origin=(0, 0)):
"""Rotate a point around a given point.
I call this the "low performance" version since it's recalculating
the same values more than once [cos(radians), sin(radians), x-ox, y-oy).
It's more readable than the next function, though.
"""
x, y = point
ox, oy = origin
qx = ox + math.cos(radians) * (x - ox) + math.sin(radians) * (y - oy)
qy = oy + -math.sin(radians) * (x - ox) + math.cos(radians) * (y - oy)
return qx, qy
def rotate_around_point_highperf(xy, radians, origin=(0, 0)):
"""Rotate a point around a given point.
I call this the "high performance" version since we're caching some
values that are needed >1 time. It's less readable than the previous
function but it's faster.
"""
x, y = xy
offset_x, offset_y = origin
adjusted_x = (x - offset_x)
adjusted_y = (y - offset_y)
cos_rad = math.cos(radians)
sin_rad = math.sin(radians)
qx = offset_x + cos_rad * adjusted_x + sin_rad * adjusted_y
qy = offset_y + -sin_rad * adjusted_x + cos_rad * adjusted_y
return qx, qy
def _main():
theta = math.radians(90)
point = (5, -11)
print(rotate_via_numpy(point, theta))
print(rotate_origin_only(point, theta))
print(rotate_around_point_lowperf(point, theta))
print(rotate_around_point_highperf(point, theta))
if __name__ == '__main__':
_main()
@Ajk4

This comment has been minimized.

Copy link

@Ajk4 Ajk4 commented Feb 25, 2020

AFAIK signs in

    qx = offset_x + cos_rad * adjusted_x + sin_rad * adjusted_y
    qy = offset_y + -sin_rad * adjusted_x + cos_rad * adjusted_y

are incorrect. Please refer to rotation matrix in https://en.wikipedia.org/wiki/Rotation_matrix

@NicolasCaous

This comment has been minimized.

Copy link

@NicolasCaous NicolasCaous commented Mar 25, 2020

@Ajk4
They are not incorrect if you are rotating clockwise. But, if the intention is to rotate in the counterclockwise direction, you are right.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment