python - 如何旋转三角形pygame

标签 python pygame trigonometry

我在pygame中有这个三角形

triangle = pygame.draw.polygon(window, (210,180,140), [[x, y], [x -10, y -10], [x + 10, y - 10]], 5)

我需要向鼠标方向旋转,非常像这个 gif 中的中心箭头:http://i.stack.imgur.com/yxsV1.gif . Pygame 没有用于旋转多边形的内置函数,因此我需要手动将三个点移动到一个圆圈中,最低点 [x,y] 指向鼠标的坐标。我的变量是:

三角形的中心和我希望它旋转的圆之间的距离(即半径)

中心到鼠标坐标的距离

三角形[x,y]的最低点和其他两条边的坐标

根据这些信息,如何使用三角函数旋转三角形的所有三个边,使底点始终朝向鼠标位置?

编辑:这是我到目前为止所得到的,但它只能设法沿着对角线来回移动三角形而不是旋转。

    def draw(self):
        curx,cury = cur
        #cur is a global var that is mouse coords
        angle = math.atan2(self.x - curx, self.y - cury)
        distance = math.sqrt(200 - (200 * math.cos(angle)))
        x = self.x + distance
        y = self.y + distance
        triangle = pygame.draw.polygon(window, (210,180,140), [[x, y], [x - 10,y - 10], [x + 10,y - 10]], 5)

最佳答案

编辑:今天早上再次考虑这个问题,还有另一种方法可以做到这一点,因为多边形是三角形。此外,数学可能更容易理解,并且每个点需要的计算更少。

设 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是反余弦( arccoscos^-1 )。

从这两个等式我们可以很容易地创建一个 python 函数,给定三角形/圆的中心、圆的半径和鼠标的位置,返回表示三角形 x-y 坐标的元组列表. (例如,中心和鼠标位置是 (x, y) 形式的元组)

def get_points(center, radius, mouse_position):
    # calculate the normalized vector pointing from center to mouse_position
    length = math.hypot(mouse_position[0] - center[0], mouse_position[1] - center[1])
    # (note we only need the x component since y falls 
    # out of the dot product, so we won't bother to calculate y)
    angle_vector_x = (mouse_position[0] - center[0]) / length

    # calculate the angle between that vector and the x axis vector (aka <1,0> or i)
    angle = math.acos(angle_vector_x)

    # list of un-rotated point locations
    triangle = [0, (3 * math.pi / 4), (5 * math.pi / 4)]

    result = list()
    for t in triangle:
        # apply the circle formula
        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 边形的质心可能不在此处的答案范围内(谷歌将揭示许多选项),但它可以完全通过方格纸手动完成。调用那个点C .

为了简化操作,并使所有转换都可以使用简单的矩阵乘法来应用,我们使用所谓的 Homogeneous coordinates ,其形式为:

    [ x ]
p = | y |
    [ 1 ]

对于二维坐标。

    [ Cx ]
C = | Cy |
    [ 1  ]

平移矩阵的一般形式为:

    [ 1  0  Vx ]
T = | 0  1  Vy |
    [ 0  0  1  ]

在哪里<Vx, Vy>表示平移向量。由于平移的目标是移动质心 C到原点,Vx = -CxVy = -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 有一定的信心,而不是手动将所有内容相乘。如果有人注意到任何问题,请随时进行编辑。

关于python - 如何旋转三角形pygame,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32572267/

相关文章:

python - 使用 PdfPages 添加文本 - matplotlib

python - Pygame,RPG 游戏的高效碰撞处理?

math - 如何计算沿圆柱体切片的两点之间的 SVG 路径弧

python - Pygame:玩家 Sprite 与墙壁碰撞时动画不正确

python - Pygame中通过点击按钮调用函数

java - 点到线距离 (2D) 和交点坐标

algorithm - 沃克三角学谜题

python - CentOS下安装idle-python2.7

python - SQLAlchemy column_property 基础知识

python - 字符识别的最佳算法