Xoay một điểm về một điểm khác (2D)


139

Tôi đang cố gắng tạo ra một trò chơi bài nơi những người hâm mộ chơi bài. Ngay bây giờ để hiển thị nó Tôi đang sử dụng API Allegro có chức năng:

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

Vì vậy, với điều này tôi có thể làm cho hiệu ứng quạt của tôi dễ dàng. Vấn đề là sau đó biết thẻ nào ở dưới chuột. Để làm điều này tôi nghĩ làm một bài kiểm tra va chạm đa giác. Tôi chỉ không chắc chắn làm thế nào để xoay 4 điểm trên thẻ để tạo thành đa giác. Tôi về cơ bản cần phải thực hiện các hoạt động tương tự như Allegro.

ví dụ: 4 điểm của thẻ là:

card.x

card.y

card.x + card.width

card.y + card.height

Tôi sẽ cần một chức năng như:

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

Cảm ơn

Câu trả lời:


331

Đầu tiên trừ điểm trục (cx,cy), sau đó xoay nó, sau đó thêm điểm đó một lần nữa.

Chưa được kiểm tra:

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
Câu trả lời tuyệt vời. Đối với bản ghi, bạn đã quay đúng vòng đầu tiên.
n.collins

@syn Syncizer giống hệt nhau, chỉ cần sử dụng các phép trừ / cộng điểm của bạn và hàm ma trận vector * của bạn để xoay.
Nils Pipenbrinck

8
Có thể hữu ích cho việc không muốn đề cập rằng tội lỗi và cos có thể mong đợi góc được thể hiện bằng radian.
15ee8f99-57ff-4f92-890c-b56153

72

Nếu bạn xoay điểm (px, py)xung quanh từng điểm một, (ox, oy)bạn sẽ nhận được:

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

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

đây là một cách dễ dàng để xoay một điểm trong 2D.


7
Bạn cần dịch lại sau khi xoay. vì vậy giải pháp sẽ là: p'x + = ox
hAlE

57

Hệ tọa độ trên màn hình thuận tay trái, tức là tọa độ x tăng dần từ trái sang phải và tọa độ y tăng dần từ trên xuống dưới. Nguồn gốc, O (0, 0) nằm ở góc trên bên trái của màn hình.

nhập mô tả hình ảnh ở đây

Một vòng quay theo chiều kim đồng hồ xung quanh gốc của một điểm có tọa độ (x, y) được cho bởi các phương trình sau:

nhập mô tả hình ảnh ở đây

trong đó (x ', y') là tọa độ của điểm sau khi quay và góc theta, góc quay (cần tính bằng radian, tức là nhân với: PI / 180).

Để thực hiện xoay quanh một điểm khác với điểm gốc O (0,0), giả sử điểm A (a, b) (điểm trục). Đầu tiên, chúng tôi dịch điểm cần quay, tức là (x, y) trở về điểm gốc, bằng cách trừ tọa độ của điểm trục, (x - a, y - b). Sau đó, chúng tôi thực hiện xoay và nhận tọa độ mới (x ', y') và cuối cùng chúng tôi dịch điểm trở lại, bằng cách thêm tọa độ của điểm trục vào tọa độ mới (x '+ a, y' + b).

Theo mô tả ở trên:

2D chiều kim đồng hồ theta độ quay của điểm (x, y) quanh điểm (a, b) là:

Sử dụng nguyên mẫu hàm của bạn: (x, y) -> (px, py); (a, b) -> (cx, cy); theta -> góc:

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

Đối với xoay theo chiều kim đồng hồ:

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

Đối với vòng quay ngược chiều kim đồng hồ:

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

Cái gì cs?
TankorSmash

1
@TankorSmash được xác định ở trênc = cos(angle)
nycynik

2

Đây là câu trả lời của Nils Pipenbrinck, nhưng được thực hiện trong c # fiddle.

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}";
        }
    }
}

Ps: Rõ ràng tôi không thể bình luận, vì vậy tôi bắt buộc phải đăng nó như một câu trả lời ...

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.