Documente Academic
Documente Profesional
Documente Cultură
Raport
Laboratorul nr.3
Tema: Curbe Bezier. Principiile de lucru cu tastatura.
Principiile de lucru cu mouse-ul.
Chișinău 2019
Sarcina lucrării:
Scrieţi un program care afişază curba Bezier, utilizând funcţiile GDI standarde şi o curbă Bezier,
afişată după calcule prin formule. Una din curbe să poată fi mişcată cu ajutorul tastelor ← (la stânga),
↑(în sus), →(la dreapta), ↓(în jos). De asemenea, trebuie să fie prevăzute taste pentru rotirea acestei
curbe. Modificați curba a doua astfel ca punctele de control să poată fi deplasate, schimbînd forma
curbei în timp real.
Noțiuni teoretice:
O curbă Bezier este definită prin patru puncte - două capete şi două puncte de control. Capetele
curbei sunt ancorate în cele două puncte finale. Punctele de control acţionează ca nişte „magneţi" care
deformează linia dreaptă dintre cele două puncte finale.
Înainte de apariţia sistemului de operare Windows 95, trebuia să creaţi propriile curbe Bezier
folosind funcţia Polyline. De asemenea, trebuia să cunoaşteţi următoarele ecuaţii parametrice ale
curbelor Bezier:
unde (x0, y0) este punctul de început al curbei, (x3, y3) este punctul de sfârşit al curbei, iar cele două
puncte de control sunt (x1, y1) şi (x2, y2). Curba este trasată pentru t având valori de la 0 la 1.
În Windows 95 nu mai este nevoie să ştiţi aceste formule. Pentru trasarea uneia sau a mai multor
curbe Bezier conexe, puteţi să folosiţi instrucţiunea:
sau instrucţiunea:
Fiecare punct poate fi manipulat cu ajutorul a două taste, primul punct cu tasta de sus și dreapta, al
doilea deja jos și stânga. Cu ajutorul săgeților putem modifica poziția punctelor apt[1] și apt[2] iar
tastarea Tab shimbă punctul de referință.
Pentru construcția curbei Bezier cu ajutorul formulelor calculăm fiecare punct al acesteia și cu funcției
SetPixel colorăm pixelul potrivit în culoarea setată.
Codul sursă:
#include <windows.h>
#include <math.h>
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT ("Bezier's Function") ;
HWND hwnd ;
MSG msg ;
WNDCLASS wndclass ;
wndclass.style = CS_HREDRAW | CS_VREDRAW ;
wndclass.lpfnWndProc = WndProc ;
wndclass.cbClsExtra = 0 ;
wndclass.cbWndExtra = 0 ;
wndclass.hInstance = hInstance ;
wndclass.hIcon = LoadIcon (NULL, IDI_APPLICATION) ;
wndclass.hCursor = LoadCursor (NULL, IDC_ARROW) ;
wndclass.hbrBackground = (HBRUSH) GetStockObject (WHITE_BRUSH) ;
wndclass.lpszMenuName = NULL ;
wndclass.lpszClassName = szAppName ;
if (!RegisterClass (&wndclass))
{
MessageBox (NULL, TEXT ("Program requires Windows NT!"), szAppName, MB_ICONERROR) ;
return 0 ;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static POINT apt[4] ;
HDC hdc ;
int cxClient, cyClient ;
PAINTSTRUCT ps ;
RECT rc;
switch (message)
{
case WM_SIZE:
cxClient = LOWORD (lParam) ;
cyClient = HIWORD (lParam) ;
apt[0].x = cxClient / 3 ; apt[0].y = cyClient / 2 ;
apt[1].x = cxClient / 2 ; apt[1].y = cyClient / 3 ;
apt[2].x = cxClient / 2 ; apt[2].y = 2 * cyClient / 3 ;
apt[3].x = 2 * cxClient / 3 ; apt[3].y = cyClient / 2 ;
return 0 ;
case WM_MOUSEMOVE:
if (wParam & MK_LBUTTON || wParam & MK_RBUTTON)
{
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
DrawBezier (hdc, apt) ;
if (wParam & MK_LBUTTON)
{
apt[1].x = LOWORD (lParam) ;
apt[1].y = HIWORD (lParam) ;
}
if (wParam & MK_RBUTTON)
{
apt[2].x = LOWORD (lParam) ;
apt[2].y = HIWORD (lParam) ;
}
SelectObject (hdc, GetStockObject (BLACK_PEN)) ;
DrawBezier (hdc, apt) ;
ReleaseDC (hwnd, hdc) ;
}
return 0 ;
case WM_KEYDOWN:
hdc = GetDC (hwnd) ;
SelectObject (hdc, GetStockObject (WHITE_PEN)) ;
DrawBezier (hdc, apt) ;
if(GetKeyState (VK_TAB))
switch(wParam)
{
case VK_RIGHT:
apt[2].x+=2;
case VK_UP:
apt[2].y-=3;
case VK_LEFT:
apt[2].x-=3;
case VK_DOWN:
apt[2].y+=2;
}
else
switch(wParam)
{
case VK_RIGHT:
apt[1].x+=2;
case VK_UP:
apt[1].y-=3;
case VK_LEFT:
apt[1].x-=3;
case VK_DOWN:
apt[1].y+=2;
}
switch(wParam)
{
case VK_CONTROL:
GetClientRect(hwnd, &rc);
apt[0].x = rc.right / 3 ; apt[0].y = rc.bottom / 2 ;
apt[1].x = rc.right / 2 ; apt[1].y = rc.bottom / 3 ;
apt[2].x = rc.right / 2 ; apt[2].y =2*rc.bottom /3 ;
apt[3].x = 2 * rc.right / 3 ; apt[3].y = rc.bottom/2 ;
break;
case VK_BACK:
GetClientRect(hwnd, &rc);
apt[0].x = rc.right / 2 ; apt[0].y = rc.bottom / 3 ;
apt[1].x = 2 * rc.right / 3 ; apt[1].y = rc.bottom / 2 ;
apt[2].x = rc.right / 3 ; apt[2].y = rc.bottom / 2 ;
apt[3].x = rc.right / 2 ; apt[3].y = 2 * rc.bottom / 3 ;
break;
}
case WM_PAINT:
InvalidateRect (hwnd, NULL, TRUE) ;
hdc = BeginPaint (hwnd, &ps) ;
DrawBezier (hdc, apt) ;
{
int x[4] = {100, 50, 150, 100};
int y[4] = {170, 220, 270, 320};
double xx, yy;
for(double t = 0.0 ; t <= 1.0 ; t += 0.0001)
{
xx = (pow(1-t,3)*x[0]+3*t*pow(1-t,2)*x[1]+3*pow(t,2)*(1-t)*x[2] + pow(t,3)*x[3]);
yy = pow(1-t,3)*y[0]+3*t*pow(1-t,2)*y[1]+3*pow(t,2)*(1-t)*y[2] + pow(t,3)*y[3];
SetPixel(hdc, (int)xx, (int)yy, RGB(144,144,144));
}
}
EndPaint (hwnd, &ps) ;
return 0 ;
case WM_DESTROY:
PostQuitMessage (0) ;
return 0 ;
}