The points reach the starting point, and the rotation

I'm trying to rotate a rectangle using a matrix (x cos? Theta; - y sin? Theta ;, x sin? Theta; + y cos? Theta;). The problem is that the rectangle gets attenuated and reaches the start point at a time (I use a timer). Here is my code.

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

Therefore, I want the points in arr be fixed at a distance from the starting point after rotation. I do not want them to reach the starting point at a time.

Initially:

  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; 

If this is the wrong way to rotate, does anyone know the correct method to rotate a rectangle around its beginning without affecting its size?

Here are snapshots when they rotate:

enter image description hereenter image description hereenter image description here

+4
source share
3 answers

During rotation

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

you use the new x coordinate to calculate the new y coordinate, but you must use the old one. To fix this, use a temporary

 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; 
+2
source

The origin is set to (400, 400), so the rotation takes place around this point. If you want the object to rotate around the center of the object, which is (150, 150), set the beginning of this point.

Then, as Daniel Fisher noted in his answer , use the starting position in the calculations:

 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); 
+1
source

For each rotate point using this matrix:

enter image description here

this is what you do and everything is fine.

And translate it using

enter image description here

And that’s what you do, and that’s normal.

This is your fixed code, mentioned by others:

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

The changes I made:

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

declaring such points:

  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; 

This is a win32 project in visual studio.

A comment:

May be a pleasant solution for those who are looking for:

How to rotate a rectangle in a win32 application using WINAPI

0
source

Source: https://habr.com/ru/post/1442472/


All Articles