4

行列 (x cos θ - y sin θ, x sin θ + y cos θ) を使用して四角形を回転させようとしています。問題は、長方形が小さくなり、時間ごとに原点に到達することです(タイマーを使用しています)。これが私のコードです。

void WINAPI Rotate(POINT arr[5])
{
    static POINT origin = { 400, 400 };
    static int i;
    static const double angle = 0.1;
    for (i = 0; i < 5; ++i)
    {
            // translate
        arr[i].x -= origin.x;
        arr[i].y -= origin.y;
            // rotate
        arr[i].x = arr[i].x * cos(angle) - arr[i].y * sin(angle);
        arr[i].y = arr[i].x * sin(angle) + arr[i].y * cos(angle);
            // translate
        arr[i].x += origin.x;
        arr[i].y += origin.y;
    }
}

arrそのため、回転後にポイントを原点から固定距離にしたいのです。時間ごとに原点に到達したくありません。

最初に:

    arr[0].x = 200;
    arr[0].y = 100;
    arr[1].x = 100;
    arr[1].y = 100;
    arr[2].x = 100;
    arr[2].y = 200;
    arr[3].x = 200;
    arr[3].y = 200;
    arr[4].x = arr[0].x;
    arr[4].y = arr[0].y;

これが回転の間違った方法である場合、サイズに影響を与えずに、原点を中心に長方形を回転させる正しい方法を知っている人はいますか?

回転中のスナップショットは次のとおりです。

ここに画像の説明を入力 ここに画像の説明を入力 ここに画像の説明を入力

4

3 に答える 3

2

あなたのローテーションでは、

arr[i].x = arr[i].x * cos(angle) - arr[i].y * sin(angle);
arr[i].y = arr[i].x * sin(angle) + arr[i].y * cos(angle);

新しい -coordinate を使用して新しい x-coordinate を計算しyますが、古いものを使用する必要があります。それを修正するには、一時的な、

double temp = arr[i].x * cos(angle) - arr[i].y * sin(angle);
arr[i].y = arr[i].x * sin(angle) + arr[i].y * cos(angle);
arr[i].x = temp;
于 2012-10-27T12:31:49.483 に答える
1

原点は (400, 400) に設定されているため、回転はその点を中心に行われます。オブジェクトの中心 (150, 150) を中心にオブジェクトを回転させたい場合は、原点をその点に設定します。

次に、Daniel Fischerが回答で指摘したように、計算で元の位置を使用します。

double old_x = arr[i].x;
double old_y = arr[i].y;

arr[i].x = old_x * cos(angle) - old_y * sin(angle);
arr[i].y = old_x * sin(angle) + old_y * cos(angle);
于 2012-10-27T12:19:18.847 に答える
0

各ポイントについて、次のマトリックスを使用して回転させます。

ここに画像の説明を入力

それはあなたがしていることであり、それは問題ありません。

そして、それを使用して翻訳します

ここに画像の説明を入力

そして、それはあなたがしていることであり、それも問題ありません。

これは、他の人が言及した固定コードを使用したコードです。

#include <Windows.h>
#include <math.h>
#define ID_TIMER 1

LRESULT CALLBACK WndProc(HWND , UINT , WPARAM , LPARAM );
void WINAPI Rotate(POINT arr[5]);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int cmdShow)
{
    TCHAR szAppName[] = TEXT("HelloWin32");
        HWND hWnd;
        MSG msg;
        WNDCLASS wndClass;
        wndClass.style = CS_HREDRAW | CS_VREDRAW;
        wndClass.lpfnWndProc = WndProc;
        wndClass.cbClsExtra = wndClass.cbWndExtra = 0;
        wndClass.hInstance = hInstance;
        wndClass.hIcon = LoadIcon(0, IDI_APPLICATION);
        wndClass.hCursor = LoadCursor(0, IDC_ARROW);
        wndClass.hbrBackground = (HBRUSH) GetStockObject(1);
        wndClass.lpszMenuName = 0;
        wndClass.lpszClassName = szAppName;

        if (!RegisterClass(&wndClass))
        {
                MessageBox(0, TEXT("Failed to register window class"), TEXT("Error"), MB_OK | MB_DEFBUTTON1 | MB_ICONERROR);
                return 1;
        }
        hWnd = CreateWindow(szAppName, TEXT("Hello World Win32!!"), WS_OVERLAPPEDWINDOW,
                CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
                NULL, NULL, hInstance, NULL);
        if (!hWnd)
        {
                MessageBox(NULL, TEXT("Failed to create the window"), TEXT("Win32 Error"), MB_ICONERROR);
                return 1;
        }
        SetTimer(hWnd, ID_TIMER, 400, NULL);

        ShowWindow(hWnd, cmdShow);
        UpdateWindow(hWnd);

        while (GetMessage(&msg, NULL, 0, 0))
        {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
        }
        return msg.wParam;
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM w, LPARAM l)
{
        static HDC hdc;
        static PAINTSTRUCT ps;
        static POINT arr[5];
        static int i;
        static RECT rect;
        switch (message)
        {
        case WM_CREATE:
                GetClientRect(hWnd, &rect);
                arr[0].x = 200;
                arr[0].y = 100;
                arr[1].x = 200;
                arr[1].y = 200;
                arr[2].x = 100;
                arr[2].y = 200;
                arr[3].x = 100;
                arr[3].y = 100;
                arr[4].x = arr[0].x;
                arr[4].y = arr[0].y;
                return 0;
        case WM_TIMER:
                Rotate(arr);
                InvalidateRect(hWnd, &rect, TRUE);
                return 0;
        case WM_DESTROY:
                KillTimer(hWnd, ID_TIMER);
                PostQuitMessage(0);
                return 0;
        case WM_PAINT:
                hdc = BeginPaint(hWnd, &ps);
                MoveToEx(hdc, arr[0].x, arr[0].y, NULL);
                for (i = 1; i < 5; ++i) LineTo(hdc, arr[i].x, arr[i].y);
                EndPaint(hWnd, &ps);
                return 0;
        case WM_SIZE:
                GetClientRect(hWnd, &rect);
                return 0;
        default:
                return DefWindowProc(hWnd, message, w, l);
        }
}

void WINAPI Rotate(POINT arr[5])
{
        static const POINT origin = { 150, 150 };
        static int i;
        static const double angle = 0.3;
        static const int direction = 1; // 1 or -1

        for (i = 0; i < 5; ++i)
        {
             POINT temp;
             arr[i].x -= origin.x;
             arr[i].y -= origin.y;
             temp.x = arr[i].x;
             temp.y = arr[i].y;
             arr[i].x = ceil(arr[i].x * cos(angle)) - ceil(direction * arr[i].y * sin(angle));
             arr[i].y = ceil(direction * temp.x * sin(angle))  + ceil(temp.y * cos(angle));
             arr[i].x += origin.x;
             arr[i].y += origin.y;
        }

}

私が行った変更:

for (i = 0; i < 5; ++i)
        {
             POINT temp;
             arr[i].x -= origin.x;
             arr[i].y -= origin.y;
             temp.x = arr[i].x;
             temp.y = arr[i].y;
             arr[i].x = ceil(arr[i].x * cos(angle)) - ceil(direction * arr[i].y * sin(angle));
             arr[i].y = ceil(direction * temp.x * sin(angle))  + ceil(temp.y * cos(angle));
             arr[i].x += origin.x;
             arr[i].y += origin.y;
        }

そのようなポイントを宣言しながら:

 arr[0].x = 200;
                arr[0].y = 100;
                arr[1].x = 200;
                arr[1].y = 200;
                arr[2].x = 100;
                arr[2].y = 200;
                arr[3].x = 100;
                arr[3].y = 100;
                arr[4].x = arr[0].x;
                arr[4].y = arr[0].y;

それはビジュアルスタジオのwin32プロジェクトです

コメント:

以下を探している人にとっては良い解決策になるかもしれません:

を使用してwin32アプリケーションで長方形を回転させる方法WINAPI

于 2012-10-27T12:16:36.910 に答える