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

jma*_*erx 123 c++ algorithm

我正在尝试制作纸牌游戏.现在显示它我使用具有功能的Allegro API:

al_draw_rotated_bitmap(OBJECT_TO_ROTATE,CENTER_X,CENTER_Y,X
        ,Y,DEGREES_TO_ROTATE_IN_RADIANS);
Run Code Online (Sandbox Code Playgroud)

所以有了这个,我可以轻松地让我的粉丝效果.问题在于知道哪个卡在鼠标下面.为此,我想到做多边形碰撞测试.我只是不确定如何旋转卡上的4个点来构成多边形.我基本上需要和Allegro做同样的操作.

例如,卡的4个点是:

card.x

card.y

card.x + card.width

card.y + card.height
Run Code Online (Sandbox Code Playgroud)

我需要一个像以下的功能:

POINT rotate_point(float cx,float cy,float angle,POINT p)
{
}
Run Code Online (Sandbox Code Playgroud)

谢谢

Nil*_*nck 300

哦,这很简单..首先减去枢轴点(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;
}
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案.为了记录,你第一次获得正确的旋转. (42认同)
  • 对于那些无意识的人来说,可能会有所帮助,因为罪过和余弦可能期望角度以弧度表示。 (3认同)
  • 我是否正确地期望 _angle_ 的正值将执行向右(顺时针)旋转,而提供负值将执行向左(逆时针)旋转?或者逆时针是一个更复杂的操作(即计算反角,然后顺时针旋转该角度)?我见过大量的页面给出了相同的公式,但似乎没有人认为适合谈论与输入/输出值相关的方向性...... (2认同)
  • 旋转角度为逆时针方向。对于顺时针旋转,请使用“角度”的负值。 (2认同)

小智 65

如果你围绕角度θ 旋转点(px, py),(ox, oy)你会得到:

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

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

这是在2D中旋转点的简单方法.

  • 你需要在轮换后翻译.所以解决方案是:p'x + = ox (6认同)
  • `ox` 和 `oy` 被添加回每行的末尾。 (4认同)

Zie*_*ezi 46

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

在此输入图像描述

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

在此输入图像描述

其中(x',y')是旋转后的点的坐标和角度θ,旋转角度(需要以弧度表示,即乘以:PI/180).

要围绕不同于原点O(0,0)的点执行旋转,假设点A(a,b)(轴点).首先,我们通过减去枢轴点的坐标(x - a,y - b)将要旋转的点(即(x,y))转换回原点.然后我们执行旋转并获得新坐标(x',y'),最后我们通过将枢轴点的坐标添加到新坐标(x'+ a,y'+ b)来将点转换回来.

按照上面的描述:

(a,b)周围的点(x,y)的2D顺时针θ旋转是:

使用你的函数原型:(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);
}
Run Code Online (Sandbox Code Playgroud)


小智 25

float s = sin(angle); // angle is in radians
float c = cos(angle); // angle is in radians
Run Code Online (Sandbox Code Playgroud)

顺时针旋转:

float xnew = p.x * c + p.y * s;
float ynew = -p.x * s + p.y * c;
Run Code Online (Sandbox Code Playgroud)

对于逆时针旋转:

float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
Run Code Online (Sandbox Code Playgroud)

  • @TankorSmash 在上面定义了 `c = cos(angle)` (2认同)

gen*_*ser 5

这是 Nils Pipenbrinck 的答案,但在 c# fiddle 中实现。

\n\n

https://dotnetfiddle.net/btmjlG

\n\n
using System;\n\npublic class Program\n{\n    public static void Main()\n    {   \n        var angle = 180 * Math.PI/180;\n        Console.WriteLine(rotate_point(0,0,angle,new Point{X=10, Y=10}).Print());\n    }\n\n    static Point rotate_point(double cx, double cy, double angle, Point p)\n    {\n        double s = Math.Sin(angle);\n        double c = Math.Cos(angle);\n        // translate point back to origin:\n        p.X -= cx;\n        p.Y -= cy;\n        // rotate point\n        double Xnew = p.X * c - p.Y * s;\n        double Ynew = p.X * s + p.Y * c;\n        // translate point back:\n        p.X = Xnew + cx;\n        p.Y = Ynew + cy;\n        return p;\n    }\n\n    class Point\n    {\n        public double X;\n        public double Y;\n\n        public string Print(){\n            return $"{X},{Y}";\n        }\n    }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

PS:显然我可以\xe2\x80\x99t评论,所以我\xe2\x80\x99m有义务将其发布为答案......

\n