2012-10-27 62 views
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; 

如果這是旋轉走錯了路,沒有人知道旋轉關於它的起源長方形,而不影響其大小正確的方法是什麼?

這裏是快照,而它旋轉:

enter image description hereenter image description hereenter image description here

+0

問題是什麼?把輸出?角度是弧度還是度數?你記住了嗎?代碼看起來合理 – 0x90

+0

角度無關緊要。它每次都達到原點並逐漸變小,直至消失 – user1234524521

+0

what ?????把輸出... – 0x90

回答

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); 

您使用x - 協調到計算新的y -coordinate,但你應該使用舊的。要修復它,請使用臨時的,

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; 
+0

很好的接收,但數學是錯誤的! :-)保存'old_x'並使用_that_進行計算。 –

+0

喔,老鼠也太快樂了。當然應該在命名中使用'arr [i] .x'。 –

+0

當我這樣做時, :-)我已經添加了一個替代我自己的答案,我希望這會更容易理解。 –

0

對於每個點rotate它通過使用這個矩陣:

enter image description here

這是你在做什麼,它沒問題。

,並通過使用

enter image description here

而且,你在做什麼,這是確定以及翻譯。

那是你的代碼與固定代碼,由其他人所說:

#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; 

這是在Visual Studio中的Win32項目

評論:

可能是人誰尋求很好的解決方案:

如何旋轉使用WINAPI在Win32應用程序矩形

+0

我已經將輸出添加到問題 – user1234524521

+0

如何運行你的代碼?我想測試它 – 0x90

+0

這是它:http://ideone.com/bWtQcZ。這是Win32項目 – user1234524521

1

原點設置爲(400,400),所以旋轉發生在該點附近。如果您希望對象圍繞對象的中心旋轉(150,150),請將原點設置爲該點。

然後,Daniel Fischerhis answer指出,使用位置的計算:

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); 
+0

謝謝。旋轉之前它仍然變小,直到它最終消失。 – user1234524521

+0

我已經添加了輸出 – user1234524521