Skip to content

Instantly share code, notes, and snippets.

@rabbl
Forked from LyleScott/rotate_2d_point.py
Created November 2, 2023 07:19
Show Gist options
  • Save rabbl/1fea7928a957e69ef369eeb1607ed5e1 to your computer and use it in GitHub Desktop.
Save rabbl/1fea7928a957e69ef369eeb1607ed5e1 to your computer and use it in GitHub Desktop.
Rotate X,Y (2D) coordinates around a point or origin in Python
"""
Lyle Scott, III // [email protected]
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()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment