围绕另一个点旋转一个点(2D)


139

我正在尝试制作纸牌散开的纸牌游戏。现在使用具有功能的Allegro API来显示Im:

al_draw_rotated_bitmap(OBJECT_TO_ROTATE,CENTER_X,CENTER_Y,X
        ,Y,DEGREES_TO_ROTATE_IN_RADIANS);

因此,我可以轻松制作自己的歌迷效果。然后问题是知道鼠标在哪个卡下面。为此,我想到了进行多边形碰撞测试。我只是不确定如何旋转卡上的4个点以构成多边形。我基本上需要执行与Allegro相同的操作。

例如,卡的4点是:

card.x

card.y

card.x + card.width

card.y + card.height

我需要一个类似的功能:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
}

谢谢

Answers:


331

首先减去枢轴点(cx,cy),然后旋转它,然后再次添加该点。

未经测试:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
  float s = sin(angle);
  float c = cos(angle);

  // translate point back to origin:
  p.x -= cx;
  p.y -= cy;

  // rotate point
  float xnew = p.x * c - p.y * s;
  float ynew = p.x * s + p.y * c;

  // translate point back:
  p.x = xnew + cx;
  p.y = ynew + cy;
  return p;
}

45
极好的答案。作为记录,您第一次获得了正确的轮换。
n.collins

@synchronizer完全相同,只需使用点减/加例程和vector * matrix函数进行旋转即可。
Nils Pipenbrinck '17

8
对于那些无意识的人来说,可能会有所帮助,因为罪过和cos可能期望角度以弧度表示。
18ee18f99-57ff-4f92-890c-b56153 '18

72

如果(px, py)围绕(ox, oy)角度theta逐点旋转,您将获得:

p'x = cos(theta) * (px-ox) - sin(theta) * (py-oy) + ox

p'y = sin(theta) * (px-ox) + cos(theta) * (py-oy) + oy

这是在2D中旋转点的简便方法。


7
旋转后需要平移。因此解决方案将是:p'x + = ox
hAlE

57

屏幕上的坐标系是左手的,即x坐标从左到右增加,而y坐标从上到下增加。原点O(0,0)在屏幕的左上角。

在此处输入图片说明

顺时针旋转围绕原点与坐标(x,y)被由下式给定的一个点的:

在此处输入图片说明

其中(x',y')是旋转后的点的坐标和角度theta(旋转角度)(需要以弧度为单位,即乘以PI / 180)。

为了绕不同于原点O(0,0)的点进行旋转,我们说点A(a,b)(枢轴点)。首先,我们通过减去枢轴点(x-a,y-b)的坐标,将要旋转的点(即(x,y))平移回原点。然后我们执行旋转并获取新坐标(x',y'),最后通过将枢轴点的坐标添加到新坐标(x'+ a,y'+ b)将点平移回去。

按照上面的描述:

(x,y)绕点(a,b)的2D顺时针theta度旋转是:

使用函数原型:(x,y)->(px,py); (a,b)->(cx,cy); theta->角度:

POINT rotate_point(float cx, float cy, float angle, POINT p){

     return POINT(cos(angle) * (p.x - cx) - sin(angle) * (p.y - cy) + cx,
                  sin(angle) * (p.x - cx) + cos(angle) * (p.y - cy) + cy);
}

29
float s = sin(angle); // angle is in radians
float c = cos(angle); // angle is in radians

对于顺时针旋转:

float xnew = p.x * c + p.y * s;
float ynew = -p.x * s + p.y * c;

对于逆时针旋转:

float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;

什么cs
TankorSmash

1
@TankorSmash其定义如上c = cos(angle)
nycynik

2

这是Nils Pipenbrinck的答案,但使用c#小提琴实现。

https://dotnetfiddle.net/btmjlG

using System;

public class Program
{
    public static void Main()
    {   
        var angle = 180 * Math.PI/180;
        Console.WriteLine(rotate_point(0,0,angle,new Point{X=10, Y=10}).Print());
    }

    static Point rotate_point(double cx, double cy, double angle, Point p)
    {
        double s = Math.Sin(angle);
        double c = Math.Cos(angle);
        // translate point back to origin:
        p.X -= cx;
        p.Y -= cy;
        // rotate point
        double Xnew = p.X * c - p.Y * s;
        double Ynew = p.X * s + p.Y * c;
        // translate point back:
        p.X = Xnew + cx;
        p.Y = Ynew + cy;
        return p;
    }

    class Point
    {
        public double X;
        public double Y;

        public string Print(){
            return $"{X},{Y}";
        }
    }
}

附言:显然我无法发表评论,所以我有义务将其发布为答案...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.