Sunteți pe pagina 1din 22

Transformări grafice bidimensionale (1)

În procesul de sinteză a imaginilor se folosesc frecvent diverse transformări.


Transformările grafice permit reprezentarea desenelor la scara dorită, efectuarea operaţiilor de
detaliere şi micşorare asupra imaginilor, realizarea animaţiei, etc.
Transformările grafice pot fi privite din două puncte de vedere, complementare unul
altuia. De exemplu, sistemul de ecuaţii care descrie transformarea coordonatelor unui punct
P( x, y ) :

x′ = x + d
, (1.1)
y′ = y

poate fi interpretat în două moduri:


a) Punctul din plan P( x , y ) a fost translatat spre dreapta cu distanţa d (fig. 1.1a);
b) Axa y a sistemului de coordonate cartezian 2D a fost translatată cu distanţa d spre
stânga (fig. 1.1b).

y y′ y

P( x, y ) P ′( x ′, y ′) P ′( x ′, y ′)

d d

O x O′ O x
a) b)
Figura 1.1

Prin urmare, există două interpretări ale unei transformări grafice a unui punct:
a) se efectuează transformări asupra coordonatelor unui punct, păstrând acelaşi
sistem de coordonate;
b) se efectuează transformări asupra sistemului de coordonate.
Prima interpretare corespunde transformării unui punct raportat la un sistem de coordonate fix
şi se formulează matematic ca o transformare geometrică aplicată punctului. În acest caz,
( x ′, y ′) sunt coordonatele punctului care rezultă din transformarea lui P . Cea de-a doua
interpretare corespunde unei transformări a sistemului de coordonate, ( x ′, y ′) reprezentând
coordonatele punctului P în noul sistem de coordonate. Această interpretare este utilizată mai
ales în exprimarea operaţiilor de vizualizare a obiectelor 2D şi 3D care, de obicei, sunt definite
într-un sistem de coordonate propriu aplicaţiei grafice, în timp ce reprezentarea lor pe
suprafaţa de afişare a unui echipament grafic este raportată la un sistem de coordonate propriu
suprafeţei.

1. Transformări geometrice
Se consideră un sistem de coordonate carteziene în plan. Orice obiect poate fi descris
printr-un set de atribute geometrice (coordonate), atribute topologice şi atribute de aspect. De
exemplu, pentru un segment de dreaptă este suficient să se specifice coordonatele capetelor
sale (atributele geometrice), ( x1 , y1 ) , ( x2 , y 2 ) , şi atributele de aspect (culoarea, tipul liniei
etc.). Pentru un desen mai complicat, cum ar fi planul unei case, nu este suficientă cunoaşterea
punctelor caracteristice trebuind să se specifice şi legăturile existente între punctele respective,
adică atributele topologice.
Transformarea geometrică a unui obiect constă în transformarea individuală a fiecărui
punct din reprezentarea obiectului. De exemplu, pentru reducerea la o anumită scară a planului
casei, se aplică aceeaşi transformare tuturor punctelor prin care este specificată, atributele
topologice şi cele de aspect nefiind afectate de transformare. Este deci suficient să se cunoască
formulările matematice ale transformărilor geometrice pentru un punct din plan.

1.1. Translaţia
Translaţia este transformarea prin care un obiect este deplasat din poziţia sa, cu o distanţă dată,
după o direcţie dată. Matematic, translaţia în plan este specificată printr-un vector:
r r r
v = tx i + t y j . (1.2)

Dacă ( x, y ) sunt coordonatele unui punct P al unui obiect, atunci prin translaţia obiectului cu
r r
o distanţă egală cu mărimea vectorului v , în direcţia vectorului v , punctul P se transformă în
P ′( x ′, y ′) (fig. 1.2), unde x ′ şi y ′ sunt definite astfel:

y r P ′( x ′, y ′)
v
ty
tx
P ( x, y )
x
O
Figura 1.2
x' = x + t x
. (1.3)
y' = y + t y

Exemplu:
r r
r r
v = 2i + j , P = (5, 5) . Prin translaţia lui P cu vectorul v se va obţine punctul P ′ = (7, 6) .

Observaţie. Obiectul este deplasat fără să se modifice forma, dimensiunea şi orientarea.

1.2. Scalarea
Scalarea este transformare prin care un obiect este mărit sau micşorat. În cazul 2D
scalarea este specificată prin două numere, numite factorul de scalare pe axa x , respectiv
factorul de scalare pe axa y .Un factor de scalare supraunitar specifică o mărire, iar unul
subunitar o micşorare.

a) Scalarea faţă de origine

Scalarea unui punct P( x, y ) cu factorii s x , s y faţă de origine înseamnă scalarea vectorului


poziţie OP , care uneşte originea cu punctul P . Vectorul rezultat din scalare, OP ′ are
componentele x , y date de:

x' = s x ⋅ x
(1.4)
y' = s y ⋅ y

Dacă s x = s y , atunci scalarea este uniformă (nu produce deformarea obiectului transformat).
În caz contrar, scalarea este neuniformă (obiectul este deformat).
Exemplu: Fie pătratul cu vârfurile (1,1) , (3,1) , (3,3) , (1,3) (fig. 1.3a). Prin scalarea faţă de
origine cu factorii s x = 2 , s y = 3 se va obţine dreptunghiul cu vârfurile: (2,3) , (6,3) , (6,9) ,
(2,9) (fig. 1.3b).

b) Scalarea faţă de un punct din plan

Se consideră F ( x f , y f ) punctul din plan faţă de care se face scalarea unui punct P( x, y ) .
Punctul F se numeşte punct fix al transformării, deoarece nu se modifică prin aplicarea
transformării. Scalarea punctului P faţă de F cu factorii de scalare s x , s y înseamnă scalarea
vectorului FP . Componentele vectorului scalat FP ′ sunt:
(
x'− x f = s x ⋅ x − x f )
= s y ⋅ (y − y f )
.
y '− y f

Din relaţiile anterioare rezultă:

x' = x ⋅ s x + x f − x f ⋅ sx
. (1.5)
y' = y ⋅ s y + y f − y f ⋅ s y

Exemplu: Prin scalarea pătratului din fig.1.3a cu aceiaşi factori de scalare s x = 2 , s y = 3 ,


faţă de punctul (1,1) , se obţine dreptunghiul din figura 1.3c.

y y 2,6 4,6 y

1,4 3,4

2,1 2,2 2,3 4,3

1,1 2,1 1,1 3,1


O x O x O x
a) b) c)
Figura 1.3

1.3. Rotaţia
a) Rotaţia faţă de origine

Rotaţia este o transformare specificată printr-un unghi. Dacă unghiul este pozitiv,
atunci rotaţia este efectuată în sensul trigonometric (invers faţă de sensul de rotaţie al acelor de
ceas). Dacă dorim să efectuăm rotaţia în sens invers trigonometric, unghiul va fi negativ.
Coordonatele punctului P ′( x ′, y ′) , obţinut prin rotaţia cu α a punctului P în jurul originii se
obţin uşor utilizând legătura dintre coordonatele carteziene şi cele polare ale lui P , respectiv
P ′ (fig. 1.4).
Pentru punctul P putem scrie:

x = r cosθ
, (1.6)
y = r sin θ

iar pentru punctul P ′ :

x′ = r cos (α + θ )
, (1.7)
y′ = r sin (α + θ )
unde r reprezintă lungimea vectorului de poziţie OP , iar θ , unghiul său cu orizontala. (fig.
1.3a). Înlocuind cos(α + θ ) şi sin(α + θ ) cu expresiile lor trigonometrice şi ţinând cont de
relaţia (1.6) se obţine:

x′ = x cos α − y sin α
. (1.8)
y′ = x sin α + y cos α

y y P ′( x ′, y ′)

P ′( x ′, y ′)
r
α P( x, y )
r P ( x, y )
α
θ F(x f , y f )
O x O x
a) b)

Figura 1.4

b) Rotaţia faţă de un punct oarecare din plan

Fie P( x , y ) punctul din plan care se roteşte în jurul unui punct F ( x f , y f ) . La fel ca în cazul
scalării, punctul F nu este afectat de transformare. Coordonatele punctului P ′ , rezultat din
rotaţia punctului P în jurul lui F cu un unghi α , se obţin din expresiile care calculează
componentele vectorului FP ′ (fig. 1.4b):

x′ − x f = ( x − x f ) cos u − ( y − y f ) sin u
. (1.9)
y′ − y f = ( x − x f ) sin u + ( y − y f ) cos u

De fapt relaţiile (1.9) pot fi scrise direct din relaţiile (1.8) după ce schimbăm originea
sistemului în punctul F , printr-o translaţie cu x f , respectiv y f . Din relaţiile (1.9) rezultă:

x′ = x cos u − y sin u + x f − x f cos u + y f sin u


(1.10)
y′ = x sin u + y cos u + y f − x f sin u − y f cos u
1.4. Formularea matricială a transformărilor

În cele mai multe cazuri, transformarea care trebuie aplicată unui obiect la un moment
dat este compusă din mai multe transformări elementare. În aceste cazuri, formula oricărei
transformări compuse se poate obţine uşor folosind expresiile matriciale ale transformărilor
elementare. Coordonatele punctelor se pot reprezenta prin vectori de linie P = [ x, y ] sau
vectori coloană P T = [x y ]T . Notăm cu M matricea de transformare rezultată. Dacă se
folosesc vectori linie, atunci se efectuează înmulţire la dreapta cu matricea de transformare
M , iar pentru vectori coloană înmulţirea se face la stânga cu M T .
Observaţie: În OpenGL se folosesc vectori coloană.
În continuare se utilizează vectori coloană. Dacă sunt de efectuat mai multe transformări
înseamnă că se efectuează compunerea de matrici.

Translaţia

Translaţia nu poate fi exprimată ca un produs matricial. Relaţiile (1.3) pot fi scrise ca o


adunare de vectori, în coordonate carteziene neexistând o matrice de transformare pentru
translaţie.
tx 
P ′ = M + P , unde vectorul M este M =   . (1.11)
 ty 

Scalarea faţă de origine

Relaţiile (1.4) pot fi scrise matricial astfel:

 x ′  s x 0   x
 y ′ =  0 ⇔ P′ = S P , (1.12)
   s y   y 

S fiind matricea transformării de scalare.

Rotaţia faţă de origine

Relaţiile (1.8) scrise matricial devin:

 x ′ cos α − sin α   x 
 y ′ =  sin α ⇔ P′ = R P , (1.13)
   cos α   y 

unde prin R s-a notat matricea transformării de rotaţie.


Observaţie: Pentru vectori linie relaţia (1.13) devine:

cos α sin α 
[x ′, y ′] = [x, y ]  . (1.14)
 − sin α cos α 
Coordonate omogene

Deoarece pentru translaţie, în coordonate carteziene, nu există o matrice de


transformare, pentru a uniformiza notaţiile se folosesc coordonate omogene. Acest sistem de
coordonate permite reprezentarea tuturor transformărilor ca produs de matrici. Unui punct 2D
din plan, ( x , y ) , îi corespunde, în coordonate omogene un triplet ( x, y , w) , în care:
x
x= w
w . (1.15)
yw
y=
w

Observaţie: Dacă w = 0 , atunci pentru [a, b, 0] , punctul se consideră la infinit pe dreapta:

a y−bx =0 (1.16)

Exemple:
1) [1,0,0] – punctul de la infinit pe axa Ox pozitivă;
2) [1,1,0] – punctul de la infinit în direcţia [1,1].
3) Punctul P ( 2,1) în coordonate plane carteziene, devine în coordonate omogene (2,1,1) sau
(4,2,2), etc.
În grafică se utilizează w = 1 , ceea ce înseamnă că:

Pcoord.cart eziene ( x, y ) → Pcoord.omogene ( x, y ,1) . (1.17)

Dacă în urma unor transformări se obţine w ≠ 1, se efectuează împărţirea cu w. În general,


transformările geometrice primitive conservă valoarea lui w şi deci dacă se alege w = 1
împărţirea nu mai este necesară.
Cele trei transformări elementare examinate anterior, într-un sistem omogen de
coordonate se exprimă astfel:

Translaţia

Relaţiile (1.11) devin:

 x ′ 1 0 t x   x 
 y ′ = 0 1 t   y  ⇔ P′ = T P , (1.18)
   y  
 1  0 0 1   1 
unde
x  x ′ 1 0 t x 
P =  y , P ′ =  y ′ , T = 0 1 t y  , (1.19)
     
1   1  0 0 1 

T fiind matricea de translaţie.


Scalarea faţă de origine

 x ′  s x 0 0  x 
 y ′ =  0 sy 0  y  ⇔ P' = S P , (1.20)
    
 1   0 0 1  1 

matricea de scalare faţă de origine fiind:

sx 0 0
S = 0 sy 0 . (1.21)
 
 0 0 1

Rotaţia faţă de origine

 x ′ cos α − sin α 0  x 
 y ′ =  sin α cos α 0  y  ⇔ P' = R P , (1.22)
    
 1   0 0 1  1 

matricea transformării de rotaţie faţă de origine fiind:

cos α − sin α 0
R (α ) =  sin α cos α 0 . (1.23)
 
 0 0 1

Observaţie: La aplicarea a două transformări asupra unui punct trebuie avut în vedere că
produsul matricial nu e comutativ. Excepţie fac transformările de acelaşi tip.
Expresiile matematice ale scalării şi rotaţiei faţă de un punct oarecare se pot obţine prin
compunerea următoarelor transformări:
1. – translaţia prin care punctul fix al transformării ajunge în origine
2. – scalarea/rotaţia faţă de origine
3. – translaţia inversă celei de la punctul 1.
Considerăm F ( x f , y f ) punctul fix al transformării, α unghiul de rotaţie şi s x , respectiv s y
factorii de scalare.

Scalarea faţă de un punct fix

Conform celor afirmate anterior, coordonatele punctului P ′ sunt date de:


P ′ = T ( x f , y f ) ⋅ S ( s x , s y ) ⋅ T ( − x f ,− y f ) ⋅ P , (1.24)

 x ′  1 0 x f   s x 0 0  1 0 − x f   x 
 y ′ = 0 1 y  ⋅  0 sy 0 ⋅  0 1 − y f  ⋅  y 
   f       
 1  0 0 1   0 0 1 0 0 1   1 
(1.25)

Observaţie:
 x ′  1 0 x f  s x 0 − sx x f   x 
 y ′ = 0 1 y f  ⋅  0 s y − s y y f  ⋅  y =
       
 1  0 0 1   0 0 1   1 
sx 0 − s x x f + x f   x   x sx + x f − sx x f 
=  0 sy − s y y f + y f  ⋅  y  =  y s y + y f − s y y f  ,
 0 0 1   1   1 
adică am obţinut relaţiile (1.5).

Rotaţia faţă de un punct fix

Coordonatele punctului P ′ le obţinem din:

P ′ = T ( x f , y f ) ⋅ R(α ) ⋅ T ( − x f ,− y f ) ⋅ P (1.26)

 x ′  1 0 x f  cos α − sin α 0 1 0 − x f   x 
 y ′ = 0 1 y f  ⋅  sin α cos α 0 ⋅  0 1 − y f  ⋅  y 
         
 1  0 0 1   0 0 1 0 0 1   1 
(1.27)

1.5. Transformări geometrice inverse


Fiecare dintre transformările geometrice elementare are o inversă, adică o transformare
care exprimă operaţia opusă celei corespunzătoare transformării.
Se pot verifica uşor următoarele relaţii:

[T (t x , t y )]−1 = T (−t x ,−t y ) (1.28)


[S ( s x , s y )]−1 = S (1 s x ,1 s y ) (1.29)
[R(α )]−1 = R(α ) (1.30)
De exemplu, pentru relaţia (1.28) avem:
1 0 t x  1 0 − t x  1 0 0
T (t x , t y ) ⋅ T ( −t x ,−t y ) = 0 1 t y  ⋅ 0 1 − t y  = 0 1 0 q.e.d.
     
0 0 1  0 0 1  0 0 1

1.6. Alte transformări simple


Oglindirea (Reflexia)

Faţă de axa x (figura 1.5a):


 x ′   1 0 0  x 
x′ = x  y ′ = 0 − 1 0 ⋅  y  ,
,
y′ = − y      
1  0 0 1 1 

y y

O x O x

a) b)

O x

c)
Figura 1.5

deci matricea de oglindire faţă de axa x este:


1 0 0
O x =  0 − 1 0 . (1.31)
 
0 0 1

Faţă de axa y (figura 1.5b):

 x ′   − 1 0 0  x 
x′ = − x  y ′ =  0 1 0 ⋅  y  ,
,
y′ = y      
1   0 0 1 1 

deci matricea de oglindire faţă de axa y este:

 − 1 0 0
O y =  0 1 0 (1.32)
 
 0 0 1

Faţă de origine (figura 1.5c)

 x ′   − 1 0 0  x 
x′ = − x  y ′ =  0 − 1 0 ⋅  y  ,
,
y′ = − y      
1   0 0 1 1 

rezultă că matricea de oglindire faţă de origine este:

 − 1 0 0
Oo =  0 − 1 0 (1.33)
 
 0 0 1

Oglindirea faţă de o dreaptă oarecare

Fie dreapta y = ax + b (fig. 1.6). Se poate exprima oglindirea faţă de dreapta y = ax + b , ca o


transformare compusă din următoarele transformări elementare:
1. O translaţie astfel încât o dreaptă să treacă prin origine T (0,−b) ;
2. O rotaţie a dreptei pentru a o alinia cu una din axele de coordonate, de exemplu cu axa
Ox , R ( − arctan( a )) ;
3. Oglindirea faţă de axa pe care a fost suprapusă, în cazul nostru Ox ;
4. Rotaţie inversă celei de la punctul 2, R (arctan(a )) ;
5. Translaţie inversă celei de la punctul 1, T (0, b) .
y P ′( x ′, y ′)

P( x, y )

b
−b a
O x

Fig. 1.6 Oglindirea faţă de o dreaptă oarecare

Prin urmare, matricea transformării este:

M = T ( a , b) ⋅ R(arctan( a )) ⋅ O x ⋅ R ( − arctan( a )) ⋅ T ( a, b) . (1.34)

De exemplu, coordonatele punctului P ′( x ′, y ′) din figura 1.6, care este simetricul lui P ( x, y )
faţă de dreapta y = ax + b , sunt date de P′ = M ⋅ P .

Observaţii:
1) Ordinea de acţionare a matricilor care compun transformarea este de la dreapta la
stânga în cazul vectorilor coloană (cazul considerat) şi de la stânga la dreapta în cazul
vectorilor linie.
2) Pentru două transformări de acelaşi tip avem:

T1 ⋅ T2 = T2 ⋅ T1 ,
R1 ⋅ R2 = R2 ⋅ R1 , (1.35)
S1 ⋅ S 2 = S 2 ⋅ S1 .

Dacă s x = s y , atunci are loc S ⋅ R = R ⋅ S


3) Pentru mai multe transformări în secvenţă, ordinea este, de regulă, următoarea:
scalarea se aplică înaintea rotaţiei.

2. Transformări ale sistemului de coordonate


Considerăm două sisteme de coordonate în plan, xOy şi x ′O ′y ′ . Unui punct fix din
plan, P , îi corespund două reprezentări: ( x , y ) în sistemul xOy şi ( x ′, y ′) în sistemul x ′O ′y ′ .
Sistemul x ′O ′y ′ se poate obţine prin transformarea sistemului xOy , transformare ce se poate
defini prin relaţia dintre cele două reprezentări ale punctului P .
2.1. Translaţia

Dacă sistemul x ′O ′y ′ s-a obţinut prin translaţia sistemului xOy cu vectorul de


translaţie (fig. 1.7a)
r r
v = tx i + t y j ,
atunci relaţia dintre coordonatele lui P în cele două sisteme este:

x′ = x − t x
⇔ P ′ = TC ⋅ P (1.36)
y′ = y − t y

cu matricea de translaţie a transformării de coordonate:

1 0 − t x 
TC (t x , t y ) = 0 1 − t y  (1.37)
 
0 0 1 

y y′
P( x, y ) y
P( x ′, y ′)
P( x, y )
y′
P ′( x ′, y ′)
O′ x′
v x′ α
tx
θ
O tx x O, O ′ x

a) b)
Figura 1.7

Observaţie. Legătura dintre matricea transformării sistemului de coordonate TC şi matricea


transformării geometrice T (în ideea în care transformările nu se aplică sistemului de
coordonate ci se aplică punctului P ) este:

TC (t x , t y ) = T ( −t x ,−t y ) = [T (t x , t y )]−1 , (1.38)

deci, matricea transformării de coordonate este inversa matricii transformării geometrice.


2.2. Rotaţia

Fie sistemul x ′O ′y ′ obţinut prin rotaţia axelor lui xOy cu unghiul θ faţă de axa x
(fig. 1.7b). Pentru punctul P în sistemul xOy are coordonatele:

x = r cos α
, (1.39)
y = r sin α

iar în sistemul x ′O ′y ′ :

x ′ = r cos(α − θ )
. (1.40)
y ′ = r sin(α − θ )

Din relaţiile (1.39) şi (1.40) rezultă:

x ′ = r cos α cos θ + r sin α sin θ = x cos θ + y sin θ


. (1.41)
y ′ = r sin α cos θ − r cos α sin θ = − x cos θ + y cos θ

Notând cu RC (θ ) matricea transformării în cazul rotaţiei unui sistem de coordonate avem:

 cos θ sin θ 0
RC (θ ) = − sin θ cos θ 0 . (1.42)
 
 0 0 1

Se observă că RC (θ ) este inversa matricii transformării geometrice de rotaţie a punctului P


faţă de origine vechiului sistem:

RC (θ ) = R( −θ ) = [R(θ )]−1 (1.43)

2.3. Scalarea

Considerăm că formăm un nou sistem de coordonate cu aceeaşi origine şi orientare a


axelor, dar cu alte unităţi de măsură de-a lungul axelor x şi y . Dacă noile unităţi de măsură
se obţin prin scalarea vechilor unităţi cu factorii s x , respectiv s y , atunci relaţia dintre
coordonatele aceluiaşi punct în cele două sisteme este:

1
x′ = x ⋅ , y, y ′
sx
(1.44)
1 P′(1,2)
y′ = y ⋅ , •
sy P (100,200)

O, O ′ x, x ′
Fig. 1.8
iar matricea transformării de coordonate:

 1 0 0
 sx 
SC ( s x , s y ) =  0 1 0 . (1.45)
 sy 
 0 0 1
 

Se observă că
 
[ ]
SC ( s x , s y ) = S  1 , 1  = S ( s x , s y ) −1 (1.46)
 sx sy 

unde prin S am notat matricea transformării de scalare geometrică (a coordonatelor


punctului).

3. Transformarea de instanţiere
Obiectele se definesc în mod obişnuit într-un sistem de coordonate propriu (local),
numit sistem de coordonate obiect. Acest sistem este caracterizat prin unităţi de măsură
adecvate, de exemplu metri sau milimetri. Pentru a reprezenta obiectul respectiv într-un desen
asupra lui trebuie efectuată o transformare. Operaţia de trecere din sistemul local în alt spaţiu
de desenare (care are altă origine şi alte coordonate), se numeşte instanţiere, iar transformarea
respectivă, transformare de instanţiere.
Reprezentarea în diverse poziţii, dimensiuni şi orientări în noul spaţiu se numeşte
instanţă a obiectului. Transformarea de instanţiere este compusă, în general, din scalare,
rotaţie şi translaţie, dar pot fi necesare şi alte transformări (oglindire, etc.).
Observaţie: Translaţia este ultima transformare care se aplică.
În exemplul 3, în programul AVION.CPP, utilizăm o astfel de transformare pentru
obţinerea instanţei avionului.

4. Aplicaţii
Pentru a exemplifica modul de implementare a transformărilor analizate anterior vom
considera trei exemple:
1. Rotirea de n ori a unui pătrat construit din linii în jurul centrului ecranului, cu un unghi
specificat.
2. Translaţia unui pătrat astfel încât centrul său să parcurgă circumferinţa unui arc de cerc cu
centrul în centrul ecranului.
3. Realizarea unor instanţe ale unui avion şi apoi rotirea acestuia în jurul centrului ecranului.
Pentru aceste aplicaţii utilizăm mediul de programare Visual C++ 8.0 (Microsoft
Visual Studio 2005). La programele corespunzătoare primelor două aplicaţii se vor folosi
funcţiile desen() şi init_obiect(raza, latura). Funcţia desen trasează conturul pătratului
apelând funcţia DrawLine. Funcţia init_obiect calculează coordonatele vârfurilor pătratului în
poziţia sa iniţială.

Exemplul 1. Să se rotească un pătrat în jurul centrului ecranului. Se vor efectua n


rotaţii succesive (în sensul trigonometric) cu pasul 2π n .

Indicaţii. În Visual C++ 8.0 se creează un proiect de tipul Windows Forms Application. În
namespace-ul cu denumirea dată proiectului va fi creată o clasă denumită implicit Form1.
Pentru această clasă definiţi o funcţie care să trateze evenimentul Paint asociat cu Form1 (o
denumire uzuală pentru această funcţie este On_Paint). Funcţia On_Paint va conţine
instrucţiunile necesare pentru afişarea pătratului.

Structura funcţiilor care realizează cerinţele problemei este prezentată mai jos. Trebuie
completate părţile lipsă ale aplicaţiei. Prin utilizarea comentariilor sunt prezentate explicaţii
ale principalelor acţiuni. În figura 1.9 este redată imaginea care trebuie obţinută pentru n = 10 .

Fig. 1.9 Rotaţii succesive ale unui pătrat

int xc, yc; //centrul suprafetei de desenare

void desen(Graphics ^g, Pen ^p, float x[4], float y[4])


{
//functie ce deseneaza patratul
... ... ... ... ... ... ...
}

void init_obiect(int raza, int latura, float x[4], float y[4])


{
//fuctie ce calculeaza coordonatele varfurilor in pozitia initiala
... ... ... ... ... ... ...
}

private: System::Void On_Paint(System::Object^ sender,


System::Windows::Forms::PaintEventArgs^ e) {
double u;
float x[4], y[4];

int N;

Graphics ^g=e->Graphics;

//suprafata de desenare
Rectangle rect = Form::ClientRectangle;

xc = rect.X + rect.Width / 2; //centrul ecranului


yc = rect.Y + rect.Height / 2;

N = 10;

double du = 2*System::Math::PI/N;
double c = System::Math::Cos(du);
double s = -System::Math::Sin(du);

//culoarea de desenare
Drawing::Pen ^myPen = gcnew Pen(Color::Black);
//culoarea fondului
g->Clear(Color::Beige);

init_obiect(60,50, x, y);

... ... ... ... ... ... ...

Exemplul 2. Să se efectueze translaţia unui pătrat, astfel încât centrul său să parcurgă
circumferinţa unui cerc cu centrul în centrul ecranului.
Indicaţie. Structura programului corespunzător este prezentată mai jos. În figura 1.10 este
redată imaginea care trebuie obţinută pentru 10 translaţii succesive.

Fig. 1.10 Translaţii succesive ale unui pătrat


int xc, yc; //centrul suprafetei de desenare

void init_obiect(int raza, int latura, float x[4], float y[4])


{
//fuctie ce calculeaza coordonatele varfurilor in pozitia initiala
... ... ... ... ... ... ...
}

void desen(Graphics ^g, Pen ^p, float x[4], float y[4])


{
//functie ce deseneaza patratul
... ... ... ... ... ... ...
}

private: System::Void On_Paint(System::Object^ sender,


System::Windows::Forms::PaintEventArgs^ e) {

double u;
float x[4], y[4]; //coordonatele varfurilor patratului
int xcp, ycp; //coordonatele centrului patratului
int raza=60, latura=50;

int N;

Graphics ^g=e->Graphics;

Rectangle rect = Form::ClientRectangle;

xc = rect.X + rect.Width / 2; //centrul ecranului


yc = rect.Y + rect.Height / 2;

N = 10;

//calculeaza du, sin, cos


... ... ... ... ... ... ...

//culoarea de desenare
Drawing::Pen ^myPen = gcnew Pen(Color::Black);

//culoarea fondului
g->Clear(Color::Beige);

init_obiect(raza, latura, x, y);

//se calculeaza coordonatele initiale ale centrului patratului


xcp = xc + raza;
ycp = yc;

for(u = 0; u < 2*System::Math::PI ; u += du)


{
desen(g, myPen, x, y); //se afiseaza conturul patratului

//se calculeaza noua pozitie a centrului patratului


...
//se calculeaza componentele vectorului de translatie
...
//se aplica translatia fiecarui varf al patratului
...
//se actualizeaza pozitia curenta a centrului patratului
...
//se aplica un delay
...
}
}

Exemplul 3. Se consideră un avion descris într-un sistem de coordonate propriu prin:


A(-30,0), B(-5,30), C(-5,40), D(0,45), E(5,40), F(5,30), G(30,0), H(5,20), I(5,-30), J(15,-40),
K(0,-35), L(-15,-40), M(-5,-30), N(-5,20). Se cere:
- Să se deseneze avionul orientat spre dreapta, în sus, spre stânga şi în jos, (scalarea fiind
facută cu 50/(latura max)), deplasat faţă de centru cu 50 pixeli la dreapta, respectiv în sus, în
stânga şi în jos.
- Să se rotească avionul în jurul centrului ecranului în sens trigonometric. Se consideră o altă
instanţiere a avionului, iniţial orientat la dreapta şi deplasat faţă de centru cu 150 pixeli
(scalarea se va face cu 70/(latura max)).
Indicaţii. Structura programului care realizează cerinţele anterioare este prezentată mai jos.
Pentru afişarea avionului intr-o nouă poziţie, se utilizează un timer cu ajutorul căruia la un
anumit interval de timp se actualizează suprafaţa de desenare.

using namespace System;


using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
using namespace System::Data;
using namespace System::Drawing;

bool firstTime = true;


typedef struct{
float x,y;
} coord2D;
const int np = 14;
coord2D avionRot[np]; //avionul care se roteste

//descrierea avionului
coord2D obiect[14]={{-30,0},{-5,30},{-5,40},{0,45},{5,40},{5,30},
{30,0},{5,20},{5,-30},{15,-40},{0,-35},
{-15,-40},{-5,-30},{-5,20}};

void afisare(coord2D corp[], Pen ^pen, Graphics ^g)


{
... ... ... ... ... ... ...
}

//extensie-determina laturile dreptunghiului de incadrare a obiectului


void extensie(coord2D corp[], int np, float &latx, float &laty)
{
int i;
float xmin, ymin, xmax, ymax;
xmin=xmax=corp[0].x;
ymin=ymax=corp[0].y;
for(i=1; i<np; i++)
{
if(corp[i].x < xmin) xmin=corp[i].x;
if(corp[i].x > xmax) xmax=corp[i].x;
if(corp[i].y < ymin) ymin=corp[i].y;
if(corp[i].y > ymax) ymax=corp[i].x;
}
latx=xmax-xmin;
laty=ymax-ymin;
}

//instantiere avion transformat fata de originea s.c.


void instantiere(coord2D avion[], float u, float scal, int tx, int ty)
{
//u - unghiul de rotatie
//scal - factorul de scalare
//tx, ty - componentele vectorului de translatie
... ... ... ... ... ... ...
}

private: System::Void On_Paint(System::Object^ sender,


System::Windows::Forms::PaintEventArgs^ e) {

int xc, yc;


float c, s, latx, laty, scal;

Rectangle rect = Form::ClientRectangle; //suprafata de desenare


xc = rect.X + rect.Width / 2; //centrul suprafetei de desenare
yc = rect.Y + rect.Height / 2;

extensie(obiect,np,latx,laty);
scal = (latx>laty)? 50/latx : 50/laty;

Graphics ^g = e->Graphics;
Drawing::Pen ^myPen = gcnew Pen(Color::Red); //setam culoarea de desenare

coord2D avion[np];

//instantiere avion orientat dreapta


instantiere(avion, ..., ..., ..., ...);
afisare(avion, myPen, g);

//instantiere avion orientat in sus


... ... ... ... ... ... ...
afisare(avion, myPen, g);

//instantiere avion orientat stanga


... ... ... ... ... ... ...
afisare(avion, myPen, g);

//instantiere avion orientat in jos


... ... ... ... ... ... ...
afisare(avion, myPen, g);
if(firstTime)
{
//calculeaza coordonatele initiale ale avionului care se roteste
instantiere(avionRot, 180, scal, xc + 150, yc);
//desenare in pozitia initiala
afisare(avionRot, myPen, g);
firstTime = false;
}
else
{
//calculeaza sin/cos de 3 grade
c=System::Math::Cos(Math::PI/60);
s=-System::Math::Sin(Math::PI/60);

//actualizeaza coordonatele varfurilor avionului care se roteste


for(int i = 0; i < np; i++)
{
float xx = avionRot[i].x;
avionRot[i].x = xx*c - avionRot[i].y*s + xc - xc*c + yc*s;
avionRot[i].y = xx*s + avionRot[i].y*c + yc - xc*s - yc*c;
}
//desenare in noua pozitie
afisare(avionRot, myPen, g);
}
}

private: System::Void On_Tick(System::Object^ sender,


System::EventArgs^ e) {
this->Refresh();
}

În urma rulării programului trebuie să se obţină, la un moment dat, o imagine ca cea


redată în fig. 1.11.

Fig. 1.11 Rotirea unui avion în jurul unui grup de patru avioane
Probleme propuse
1. Se consideră originea sistemului de coordonate în centrul ecranului. Să se deseneze un
pătrat (centrul pătratului diferit de centrul ecranului) şi apoi să se realizeze simetricul lui faţă
de dreapta y = x şi y = − x .

2. Să se transleze grupul celor patru avioane din exemplul 3 atfel încât centrul figurii grupului
celor patru avioane să descrie circumferinţa unui cerc cu centrul în centrul ecranului. Cel de-al
cincilea avion se va roti tot timpul în jurul grupului celor patru avioane.

Evaluare