以度数旋转一个正方形

1 投票
2 回答
4489 浏览
提问于 2025-04-18 05:22

我有一个正方形,中心点是x0, y0。我想把这个正方形的一个顶点按照给定的角度(theta,单位是度)顺时针旋转,并返回新的旋转后顶点的位置。我正在使用这个方法来旋转每个顶点。

要把点(px, py)围绕点(x0, y0)旋转角度theta,你可以得到:

p'x = cos(theta) * (px-x0) - sin(theta) * (py-y0) + x0
p'y = sin(theta) * (px-x0) + cos(theta) * (py-y0) + y0

where: 
px, py = coordinate of the point
y0, x0, = centre of rotation
theta = angle of rotation

我写了一个Python函数,参数包括:x, y(正方形的中心),正方形的边长,以及theta_degree(旋转角度,单位是度),但是返回的结果是逆时针方向的。

from math import cos, sin

def get_square_plot(x, y, side, theta_degree=0):
    theta = theta_degree * pi/180
    xa = x-side/2
    ya = y+side/2
    xb = x+side/2
    yb = y+side/2
    xc = x+side/2
    yc = y-side/2
    xd = x-side/2
    yd = y-side/2
    xa_new = cos(theta) * (xa - x) - sin(theta) * (ya - y) + x
    ya_new = sin(theta) * (xa - x) - cos(theta) * (ya - y) + y
    xb_new = cos(theta) * (xb - x) - sin(theta) * (yb - y) + x
    yb_new = sin(theta) * (xb - x) - cos(theta) * (yb - y) + y
    xc_new = cos(theta) * (xc - x) - sin(theta) * (yc - y) + x
    yc_new = sin(theta) * (xc - x) - cos(theta) * (yc - y) + y
    xd_new = cos(theta) * (xd - x) - sin(theta) * (yd - y) + x
    yd_new = sin(theta) * (xd - x) - cos(theta) * (yd - y) + y
    return [(xa_new, ya_new),(xb_new, yb_new),(xc_new, yc_new),(xd_new, yd_new)]

get_square_plot(0, 0, 10, 0)
[(-5.0, -5.0), (5.0, -5.0), (5.0, 5.0), (-5.0, 5.0)]

而不是

[(-5.0, 5.0), (5.0, 5.0), (5.0, -5.0), (-5.0, -5.0)]

2 个回答

1

别忘了几何模块哦。它可以处理各种基本形状,还能进行平移、旋转等等。

你可以用RegularPolygon来构建一个正方形。它的原理是根据中心点的位置,找到距离中心一定半径的顶点;如果你想要一个边长为给定值的正方形,就把这个值除以根号2。下面是一个函数,用来把菱形的方向旋转,使得边与坐标轴平行,然后再旋转到你想要的角度,a

>>> Square = lambda c, r, a: RegularPolygon(c, r/sqrt(2), 4, -rad(a) - pi/4)
>>> Square((0,0),10,0).vertices
[Point(5, -5), Point(5, 5), Point(-5, 5), Point(-5, -5)]
>>> [w.n(2) for w in Square((0,0),10,1).vertices]
[Point(4.9, -5.1), Point(5.1, 4.9), Point(-4.9, 5.1), Point(-5.1, -4.9)]

注意,顺时针旋转1度(-rad(1))会让第一个顶点稍微靠近y轴,并且位置稍微低一些,这正是我们所期待的。你也可以输入一个符号来表示角度:

>>> from sympy.utilities.misc import filldedent
>>> print filldedent(Square((0,0),10,a).vertices)

[Point(5*sqrt(2)*cos(pi*a/180 + pi/4), -5*sqrt(2)*sin(pi*a/180 +
pi/4)), Point(5*sqrt(2)*sin(pi*a/180 + pi/4), 5*sqrt(2)*cos(pi*a/180 +
pi/4)), Point(-5*sqrt(2)*cos(pi*a/180 + pi/4), 5*sqrt(2)*sin(pi*a/180
+ pi/4)), Point(-5*sqrt(2)*sin(pi*a/180 + pi/4),
-5*sqrt(2)*cos(pi*a/180 + pi/4))]

你还可以通过旋转一个点来检查你的点旋转公式,-theta(顺时针方向):

>>> var('px py theta x0 y0')
(px, py, theta, x0, y0)
>>> R = Point(px,py).rotate(-theta, Point(x0,y0))
>>> R.x
x0 + (px - x0)*cos(theta) + (py - y0)*sin(theta)
>>> R.y
y0 + (-px + x0)*sin(theta) + (py - y0)*cos(theta)
3

这其实很简单——你的y值公式写错了。

应该是:

ya_new = sin(theta) * (xa - x) + cos(theta) * (ya - y) + y

用加法,而不是减法。

撰写回答