我正在尝试使用矩阵旋转矩形(xcosθ - ysinθ,xsinθ+ycosθ)。问题是矩形越来越小并且每次都到达原点(我正在使用计时器)。这是我的代码。
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;
如果这是一种错误的旋转方式,是否有人知道一种正确的方法来旋转矩形的原点而不影响它的大小?
以下是旋转时的快照:
答案 0 :(得分: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);
您使用 new x
- 坐标来计算新的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;
答案 1 :(得分:1)
原点设置为(400,400),因此旋转发生在该点附近。如果希望对象围绕对象的中心旋转,即(150,150),请将原点设置为该点。
然后,在Daniel Fischer中注明his 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);
答案 2 :(得分:0)
对于每个点rotate,使用此矩阵:
这就是你正在做的事情,没关系。
使用
翻译它
你正在做的事情也没关系。
这是您使用固定代码的代码,其他人提到:
#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