Sunteți pe pagina 1din 9

Ministerul Educației, Culturii Și Cercetării al Republicii Moldova

Universitatea Tehnică a Moldovei


Departamentul ISA

Raport
Laboratorul nr.3
Tema: Curbe Bezier. Principiile de lucru cu tastatura.
Principiile de lucru cu mouse-ul.

A realizat: st.gr Baranov Oleg TI-172


A verificat: Potlog M.

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:

x(t) = (1-t)3x0 + 3t(1-t)2x1 + 3t2(1-t)x2 + t3x3

y(t) = (1-t)3y0 + 3t(1-t)2y1 + 3t2(1-t)y2 + t3y3

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:

PolyBezier (hdc, pt, iCount) ;

sau instrucţiunea:

PolyBezierTo (hide, pt, iCount) ;

În ambele cazuri, pt este o matrice de structuri POINT.


Mersul lucrării:
Pentru construcția curbei utilizăm funcția PolyBezier cu fixarea punctelor:

Figura 1. Punctele de reper ale curbei Bezier

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ță.

Figura 2. Tastele de manipulare a punctelor


Pentru manipularea acestora cu ajutorul mouselui folosim mesajul WM_MOUSEMOVE:

Figura 3. Manipularea punctelor cu ajutorul mouselui

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ă.

Figura 4. Curba Bezier cu ajutorul funcțiilor


Figura 5. Fereastra inițială

Figura 6. Modificarea cu ajutorul mouselui

Figura 6. Modificarea cu ajutorul tastaturii


Concluzie:
Scopul propus de această lucrare de laborator este preponderent ințelegerea si implementarea
evenimentelor legate de mouse și tastatură. Pe lângă altele este necesară și lucrul cu curbele Bezier.
Afișarea și manipularea curbelor Bezier este destulă pentru a face o introducere în evenimente.
In cadrul sarcinei principale a servit crearea curbelor Bezier atât cu ajutorul formulelor, cât și cu
ajutorul funcțiilor predefinite șiafișarea acestora în zona Client. Manipularea cu acestea are loc cu
mousel și tastatura.
In timpul scrierii programului au aparut unele probleme cu manipularea legate de tastatură, cât ți
de afișarea curbelor în zona client, dar prin implementarea noilor idei acestea au fost rezolvate.
Datorita acestei lucrari de laboratori am înțeles cum se implementează și cum lucrează cu mousul
și tastatura la manipularea cu unele părți ale zonei Client.

Codul sursă:
#include <windows.h>
#include <math.h>

LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM) ;

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

hwnd = CreateWindow (szAppName, TEXT ("Bezier"),


WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL) ;

ShowWindow (hwnd, iCmdShow) ; UpdateWindow (hwnd) ;

while (GetMessage (&msg, NULL, 0, 0))


{
TranslateMessage (&msg) ;
DispatchMessage (&msg) ;
}
return msg.wParam ;
}

void DrawBezier (HDC hdc, POINT apt[])


{
PolyBezier (hdc, apt, 4) ;
MoveToEx (hdc, apt[0].x, apt[0].y, NULL) ;
LineTo (hdc, apt[1].x, apt[1].y) ;
MoveToEx (hdc, apt[2].x, apt[2].y, NULL) ;
LineTo (hdc, apt[3].x, apt[3].y) ;
}

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

SelectObject (hdc, GetStockObject (BLACK_PEN)) ;


DrawBezier (hdc, apt) ;
ReleaseDC (hwnd, hdc) ;
return 0;

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

return DefWindowProc (hwnd, message, wParam, lParam) ;


}

S-ar putea să vă placă și