Sunteți pe pagina 1din 8

Motivaţii

Una dintre cele mai interesante categorii de probleme informatice este cea a realizării
elementelor grafice, mai corect – geometrice. În spatele unei imagini sau oricărui alt element
grafic realizat pe monitorul calculatorului este ascuns un model matematic, rareori complex, dar
întotdeauna, – elegant şi perfect.
Problema de calcul a ariei unui triunghi sau patrulater este relativ simplă. Dar cum se
procedează atunci când este necesar să se calculeze aria unui poligon, care are 20 sau chiar 200
de laturi? Este oare acest poligon convex sau nu? Apoarţine oare un punct dat domeniului intrior
al acestui poligon? Şirul întrebărilor ar putea fi continuat la nesfârşit. Răspunsurile sunt ascunse
în algoritmii de geometrie computaţională.
Problemele de geometrie apar tot mai frecvent în concursurile de programare de cele mai
diverse ranguri – de la concursuri locale până la cele de talie internaţională. Spre deosebire de
metodele de rezolvare a problemelor devenite deja clasice (programarea dinamică, algoritmii
teoriei grafurilor, metoda Divide Et Impera, banalul Backtracking) care au fost descrise în mai
multe ediţii apărute la noi în Ţară şi peste hotare, algoritmii de rezolvare a problemelorde
geometrie computaţională au fost descrişi fragmentar doar în câteva ediţii1.
Începând cu acest articol, pe parcursul câtorva numere se va încerca o sistematizare a
algoritmilor de geometrie computaţională cu expunerea lor de la cele mai simple operaţii şi până
la analiza şi rezolvare unor probleme de concurs complexe.
Geometria computaţională în plan se bazează pe câteva elemente cheie. Cunoaşterea
proprietăţilor acestora permite rezolvarea majorităţii absolute a problemelor. Care sunt aceste
„cărămizi”, pe care se bazează algoritmii geometrici?
Enumerarea lor nu va lua mult timp:
• Sistem de coordonate
• Punct
• Distanţă
• Dreaptă
Celelalte elemente geometrice plane (segment, poligon, arie, perimetru etc.) pot fi definite cu
ajutorul elementelor enumerate mai sus. Prin urmare, posibilitatea de a procesa datele, care se
referă la elementele primare, permite rezolvarea problemelor care ţin de structurile geometrice
complexe.

1. Transformări de coordonate.

1.1 Deplasări şi rotaţii

Rezolvarea oricărei probleme de geometrie computaţională începe (dacă e necesar) de la


deplasarea coordonatelor elementelor cercetate (de cele mai multe ori - punctelor) într-un
domeniu potrivit al sistemului de coordonate (de obicei - în cadranul întâi). Deplasarea în unele
cazuri poate fi însoţită de rotaţia sistemului de coordonate.

Fie dat în planul de coordonate un punct P cu coordonatele carteziene (x,y). Deplasarea de


coordonate de-a lungul axei 0x cu o valoare dată a implică o modificare a coordonatelor
punctului conform formulelor:
x' = x + a
 ' (1.1)
 y =y

1
Printre ediţiile în care au fost descrişi unii dintre algoritmii geometrici pot fi menţionate: Th. H. Cormen ş.a.
„Introducere în algoritmi”, Cluj, Agora, 2001 şi C. Cadar ş.a. Culegere de probleme şi programe Pascal, Bucureşti,
Petrion, 1998.
În cazul deplasării de-a lungul axei 0y cu vloarea b transformarea de coordonate va fi dată de
sistemul:
 x' = x
 ' (1.2)
y = y + b

Modificarea “combinată” a coordonatelor cu a după 0x şi b după 0y va fi dată de sistemul:

 x' = x + a
 ' (1.3)
y = y + b

Următorul tip de transformare este rotirea


cu un unghi ϕ a punctului (punctelor) faţă
de originea sistemului de coordonate (des.
1). (în unele ediţii transformarea este
indicată ca rotirea originii coordonatelor
faţă de punctul (sau sistemul de puncte)
dat).

În acest caz există patru numere a,b,c,d ,


care permit trecerea univocă a
coordonatelor x,y în x’,y’, utilizând
sistemul de ecuaţii:

 x ' = ax + by
 ' (1.4)
 y = cx + dy

Pentru determinarea acestui cuadruplu de numere se folosesc punctele (1,0) şi (0,1)

Se observă, că la rotirea cu un unchi ϕ


punctul cu coordonatele (1,0) trece în
punctul (cos(ϕ ), sin(ϕ )), iar (0,1) – în
(-sin(ϕ ), cos(ϕ )). Înlocuind aceste valori
în calitate de coeficienţi în sistemul (1.4) se
obţine:

x' = a  a = cosϕ
 ' ⇒ (1.5.1)
y = c  c = sinϕ

Analogic:

 x' = b b = − sinϕ
 ' ⇒ (1.5.2)
y = d  d = cosϕ

Astfel, sistemul de ecuaţii pentru rotirea cu


un unghi ϕ a unui punct arbitrar (x,y) în
jurul centrului de coordonate capătă forma:
 x ' = x cos(ϕ ) − y sin(ϕ )
 ' (1.6)
 y = x sin(ϕ ) + y cos(ϕ )

În cazul, când rotirea cu unghiul ϕ a punctului cu coordonatele (x,y) este efectuară în raport cu
un punct (x0,y0), diferit de originea coordonatelor, mai întâi se transferă originea în centrul de
rotire (deplasarea de coordonate), apoi se efectuază rotirea în jurul noului „centru de
coordonate”:
 x ' − x0 = ( x − x0 ) cos(ϕ ) − ( y − y 0 ) sin(ϕ )
 ' sau
 y − y 0 = ( x − x0 ) sin(ϕ ) + ( y − y 0 ) cos(ϕ )
 x ' = x0 + ( x − x0 ) cos(ϕ ) − ( y − y 0 ) sin(ϕ )
 ' (1.7)
 y = y 0 + ( x − x0 ) sin(ϕ ) + ( y − y 0 ) cos(ϕ )

1.3 Implementări

În problemele de concurs pot apare diferite modele de transformări ale coordonatelor: deplasări
după o axă, deplasări combinate (după ambele axe), rotaţii faţă de un punct, deplasări însoţite de
rotaţii. Toate aceste transformări presupun recalcularea coordonatelor unui punct sau a unui
sistem de puncte.
Pentru rezolvarea eficientă a problemelor de geometrie este foarte importantă alegerea
corectă a structurilor de date. La moment se va implementa o singură structură – punctul:

type point=record
x,y : real;
end;

Procedura de deplasare a coordonatelor cu valorile vx după 0X şi vy după 0Y poate fi realizată în


felul următor:

procedure move(var P:point; vx,vy:real);


begin
P.x:=P.x+vx;
P.y:=P.y+vy;
end;

La fel de simplă este şi o posibilă implementare a rotaţiei cu un unghi u faţă de un punct cu


coordonatele vx şi vy:
procedure rotate (var P:point; u,vx,vy:real);
var old:point;
begin
old:=P;
P.x:=vx+(old.x-vx)*cos(u*pi/180)-(old.y-vy)*sin(u*pi/180);
P.y:=vy +(old.x-vx)*sin(u*pi/180)+(old.y-vy)*cos(u*pi/180);
end;
1.4 Probleme rezolvate

1.4.1 Comoara (Concursul on Line .Campion, ediţia 2005-2006)

Să gaseşti o comoară ascunsă de către piraţi este simplu – dacă ai o hartă. De obicei harta este
însoţită de un algoritm ce descrie deplasarea spre comoară. De exemplu: „Găseşte stânca albă.
Mergi 30 de paşi spre pădure, apoi 15 spre lac, ... , şi 20 prin peşteră. Comoara e sub semnul
desenat pe peretele drept”. Cea mai mare parte a indicaţiilor se reduce la deplasarea cu un anumit
număr de paşi în una din direcţiile date (1 – nord, 2 – nord-est, 3 – est, 4 – sud-est, 5 – sud, 6 –
sud-vest, 7 – vest, 8 – nord-vest). Lungimea pasului este considerată 1 pentru direcţiile 1,3,5, 7 şi
2 pentru direcţiile 2, 4, 6, 8.

Călătoria după traseul descris e foarte simplă, dar cere mult timp. Căutătorii de comori vor să
ajungă direct la comoară. De exemplu, în loc să meargă 3 paşi la nord, 1 la est, 1 – la nord, 3 la
est, 2 la sud şi 1 pas la vest, se poate de mers direct, făcând doar aproximativ 3.6 paşi (des. 3).

Cerinţă
Scrieţi un program, care după indicaţiile piraţilor determină punctul, în care este ascunsă
comoara. Se consideră că axa Ox e îndreptată spre est, iar Oy – spre nord. Iniţial căutătorul de comori se
află în originea sistemului de coordonate (punctul cu coordonatele (0, 0)).

Input
Prima linie a fişierului de intrare conţine numărul N – numărul de indicaţii (1≤N≤40). Următoarele N
linii conţii indicaţiile propriu-zise – numărul direcţiei (un număr întreg de la 1 la 8) şi numărul de paşi (un
număr întreg de la 1 la 1000), separate prin spaţiu.
Output
Unica linie a fişierul de ieşire va conţine două numere întregi X şi Y separate prin spaţiu –
coordonatele punctului în care este ascunsă comoara.
Exemple
Comoara.in comoara.out
6 3 2
1 3
3 1
1 1
3 3
5 2
7 1
1 -10 10
8 10
Rezolvare

Program comori;
Var
I,N:integer;
D,L:Longint;
X,Y:Longint;
Begin
Assign(Input,'comori.in');
Reset(Input);
Read(N);
X:=0; Y:=0; {fixarea pozitiei initiale}
For I:=1 To N Do
Begin {modelarea deplasarii conform instructiilor}
Read(D,L);
case D of
1: Y:=Y+L; { deplasare spre nord cu L pasi}
2: begin X:=X+L; Y:=Y+L; end; { deplasare spre nord - est cu L pasi}
3: X:=X+L; { deplasare spre est cu L pasi}
4: begin X:=X+L; Y:=Y-L; end; { deplasare spre sud - est cu L pasi}
5: Y:=Y-L; { deplasare spre sud cu L pasi}
6: begin X:=X-L; Y:=Y-L; end; { deplasare spre sud - vest cu L pasi}
7: X:=X-L; { deplasare spre vest cu L pasi}
8: begin X:=X-L; Y:=Y+L; end; { deplasare spre nord - vest cu L pasi}
End;
End;
Close(Input);
Assign(Output,'comori.out');
Rewrite(Output);
Write(X,' ',Y);
Close(Output);
End.
1.4.2 Robotul defectat

În urma unei lovituri de meteorit sistemul de comandă al unui robot care se deplasează pe
suprafaţa planetei Marte a fost deteriorat. Robotul continuă să primească instrucţiuni, dar le
interpretează în felul său. Fiecare instrucţiune este un set din trei numere (u,vx,vy) întregi,
pozitive. Dacă valoarea u > 90, atunci robotul se deplasează cu vx după axa 0X şi cu vy după axa
0Y. Dacă, însă u ≤ 90, atunci robotul se deplasează pe un arc de mărime u împotriva acelor de
ceasornic a circumferinţei cu centrul în punctul (vx,vy). (des.4) Raza circumferinţei este
segmentul care uneşte robotul cu centrul ei.

Cerinţă

Scrieţi un program, care după


coordonatele iniţiale ale robotului şi un
set dat de instrucţiuni determină
punctul final, în care este poziţionat
robotul.

Input
Prima linie a fişierului de intrare
conţine două numere întregi –
coordonatele iniţiale ale robotului.
Următoarele linii conţii câte o
instrucţiune, formată din trei numere
întregi, separate prin spaţiu.
Output
Unica linie a fişierul de ieşire va
conţine două numere X şi Y separate prin
spaţiu – coordonatele punctului în care se
află robotul defectat, indicate cu cel puţin
3 cifre după virgulă.

Exemplu
Robot.in (desen) Robot.out
3 2 -0.653 15.697
130 4 1
45 1 7
91 0 3
60 0 6
Rezolvare

program transformari;
const pi=3.141592;
type point=record
x,y : real;
end;
var
P: point;
alfa:real;
xn,yn:real;
f,g:text;

procedure move(var P:point; vx,vy:real);


begin
P.x:=P.x+vx;
P.y:=P.y+vy;
end;

procedure rotate (var P:point; u,vx,vy:real);


var old:point;
begin
old:=P;
P.x:=vx+(old.x-vx)*cos(u*pi/180)-(old.y-vy)*sin(u*pi/180);
P.y:=vy +(old.x-vx)*sin(u*pi/180)+(old.y-vy)*cos(u*pi/180);
end;

begin
assign(f,'robot.in');
reset(f);
assign(g,'rob.out');
rewrite(g);
readln(f,P.x,P.y);
while not eof(f) do
begin
readln(f,alfa,xn,yn);
if alfa>90 then move(P,xn,yn) else rotate(P,alfa,xn,yn);
end;
writeln(g,P.x:10:3,' ',P.y:10:3);
close(g);
end.
Bibliografie

1. C. Cadar ş.a. Culegere de probleme şi programe Pascal, Bucureşti, Petrion, 1998.


2. J.D.Foley, A. Vandam, Fundamentals of interactive Computer Graphics, Phillipines,
Addison-Wesley, 1984
3. Wolfgang K. Giloi Interactive Computer Graphics. Data structures, Algorithms,
Languages. Prentice Hall Inc., New Jersey, 1978
4. М. Ласло. Вычислительная геометрия и компьютерная графика на С++. Москва,
Бином, 1997

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