编辑:今天早上我重新考虑了一下,因为多边形是三角形,所以还有另一种方法可以做到这一点。而且数学可能更容易理解,每个点的计算量也更少。
设Cx和Cy为内切于三角形的圆的圆心。我们可以使用参数方程描述一个圆的方程:
F(t) = { x = Cx + r * cos(t)
{ y = Cy + r * sin(t)
这个公式中,r
代表圆的半径,t
表示沿圆的角度。
使用这个公式,我们可以用接触圆的点来描述三角形,本例中我们使用 t = { 0, 3 * pi / 4, 5 * pi / 4 }
作为我们的点。
我们还需要计算旋转三角形所需的角度,以便将在 t = (0)
时的点移到从 (Cx, Cy)
到鼠标位置的直线上。两个(标准化的)向量之间的夹角可以通过以下公式计算:
t = acos(v1 . v2) = acos(<x1, y1> . <x2, y2>) = acos(x1 * x2 + y1 * y2)
这里,.
代表点积,acos
是反余弦函数(arccos
或cos^-1
)。
通过这两个方程,我们可以轻松创建一个Python函数,该函数接受三角形/圆的中心、圆的半径和鼠标位置,并返回表示三角形x-y坐标的元组列表。 (对于示例,中心和鼠标位置都是(x,y)
格式的元组)
def get_points(center, radius, mouse_position):
length = math.hypot(mouse_position[0] - center[0], mouse_position[1] - center[1])
angle_vector_x = (mouse_position[0] - center[0]) / length
angle = math.acos(angle_vector_x)
triangle = [0, (3 * math.pi / 4), (5 * math.pi / 4)]
result = list()
for t in triangle:
x = center[0] + radius * math.cos(t + angle)
y = center[1] + radius * math.sin(t + angle)
result.append((x, y))
return result
调用此函数的方式如下:
from pprint import pprint
center = (0,0)
radius = 10
mouse_position = (50, 50)
points = get_points(center, radius, mouse_position)
pprint(points)
产生:
[(7.071067811865475, 7.0710678118654755),
(-10.0, 1.2246467991473533e-15),
(-1.8369701987210296e-15, -10.0)]
这是三角形的三个点坐标(x,y)。
以下是原始方法,因为现代计算机图形系统(OpenGL,DirectX等)使用此方法。
绕任意多边形的重心旋转是通过三个不同的矩阵操作序列实现的,即将对象平移,使重心位于原点(0,0),应用旋转并返回到原始位置。
对于任意n-gon计算重心可能超出了这里的答案范围(谷歌将显示许多选项),但可以使用方格纸手工完成。将该点称为 C
。
为了简化操作并使所有变换都能使用简单的矩阵乘法应用,我们使用所谓的齐次坐标,其形式为:
[ x ]
p = | y |
[ 1 ]
对于2D坐标,请使用以下格式。
让我们用代码来说明。
[ Cx ]
C = | Cy |
[ 1 ]
翻译矩阵的一般形式为:
[ 1 0 Vx ]
T = | 0 1 Vy |
[ 0 0 1 ]
其中<Vx,Vy>
表示翻译向量。由于翻译的目标是将质心C
移动到原点,所以Vx = -Cx
并且Vy = -Cy
。反向翻译T'
就是Vx = Cx,Vy = Cy
接下来需要旋转矩阵。设r
为所需的顺时针旋转角度,R
为旋转矩阵的一般形式。那么,
[ cos(r) sin(r) 0 ]
R = | -sin(r) cos(r) 0 |
[ 0 0 1 ]
因此,最终变换矩阵如下:
[ 1 0 -Cx ] [ cos(r) sin(r) 0 ] [ 1 0 Cx ]
TRT' = | 0 1 -Cy | * | -sin(r) cos(r) 0 | * | 0 1 Cy |
[ 0 0 1 ] [ 0 0 1 ] [ 0 0 1 ]
这可以简化为:
[ cos(r) sin(r) cos(r)*Cx-Cx+Cy*sin(r) ]
|-sin(r) cos(r) cos(r)*Cy-Cy-Cx*sin(r) |
[ 0 0 1 ]
将此应用于点
p = (x,y)
,我们得到以下方程:
p' = { x' = Cx*cos(r)-Cx+Cy*sin(r)+x*cos(r)+y*sin(r)
{ y' = -Cx*sin(r)+Cy*cos(r)-Cy-x*sin(r)+y*cos(r)
在Python中:
def RotatePoint(c, p, r):
x = c[0]*math.cos(r)-c[0]+c[1]*math.sin(r)+p[0]*math.cos(r)+p[1]*math.sin(r)
y = -c[0]*math.sin(r)+c[1]*math.cos(r)-c[1]-p[0]*math.sin(r)+p[1]*math.cos(r)
return (x, y)
在输入了所有内容后,我意识到您的对象可能已经居中于原点,此时上述函数简化为
x=p[0]*math.cos(r)+p[1]*math.sin(r)
和
y=p[0]*math.sin(r)+p[1]*math.cos(r)
。
我在这里对Wolfram Alpha有些信任,而不是手动算出所有内容。如果有人发现任何问题,请随意进行编辑。