Last active
October 7, 2024 08:05
-
-
Save LyleScott/e36e08bfb23b1f87af68c9051f985302 to your computer and use it in GitHub Desktop.
Rotate X,Y (2D) coordinates around a point or origin in Python
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
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() |
@Ajk4
They are not incorrect if you are rotating clockwise. But, if the intention is to rotate in the counterclockwise direction, you are right.
thank you :D
i always forget how to rotate things
so having this is very handy
Thank you! The best and most insightful source in the web! I will print and frame it.
Hi,
thank you for this code!
In the meantime return float(m.T[0]), float(m.T[1])
throws a DeprecationWarning.
Using return m.T[0].item(), m.T[1].item()
instead solves it.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
AFAIK signs in
are incorrect. Please refer to rotation matrix in https://en.wikipedia.org/wiki/Rotation_matrix