14 elemente de grafica in pascal
TRANSCRIPT
133
14. Elemente de grafic• elementar• în Pascal
(Utilizarea unit-ului Graph )
14.1. Utilizarea ecranului în mod grafic.
Exist• dou• moduri de lucru cu ecranul: modul grafic •i modul text. În
ambele moduri, ecranul este privit ca o re•ea dreptunghiular• ce con•ine elemente
de acela•i fel. În modul text acestea sunt caracterele utilizate în scrierea obisnuit•,
iar în modul grafic elementele sunt puncte, cu ajutorul c•rora se construiesc
diferite figuri.
Limbajul Pascal ne ofer• posibilitatea de a utiliza ecranul •i în modul
grafic prin apelul rutinelor grafice aflate în unitul Graph. În acest unit sunt
declarate constante, tipuri de date, variabile, func•ii •i proceduri care pot fi
utilizate în Turbo Pascal. Reamintim c• programul care apeleaz• rutinele grafice
din unitul Graph va declara aceasta prin propozi•ia Uses Graph.
Pentru a utiliza ecranul în mod grafic, va trebui mai întâi s• select•m
modul grafic, adic• s• trecem ecranul din modul text în modul grafic prin
ini•ializarea sesiunii grafice.
În sesiunea grafic• se pot trasa diverse primitive grafice (puncte,
segmente, dreptunghiuri, cercuri, elipse, etc.) în diverse culori, iar pe un desen
realizat se pot aplica diverse mesaje utilizând diferite fonturi aflate la dispozitia
programatorului.
La terminarea sesiunii grafice sistemul va reveni în modul text.
Calculatoarele IBM_PC pot fi echipate cu diverse adaptoare grafice,
pentru care Turbo_Pascal are construit câte un driver grafic. De exemplu pentru
adaptorul grafic IBM EGA sau VGA driverul grafic este EGAVGA.BGI.
134
În modul grafic, ecranul poate fi
considerat ca fiind format dintr-o matrice
de puncte (pixeli).
Un punct de pe ecran poate fi aprins
(colorat) într-o anumit• culoare iar pozi•ia
s• este definit• prin coordonatele sale u •i v
reprezentând coloana, respectiv linia,
unde:
0≤ u < Dmx, Dmx = dimensiunea maxim• pe coloan•, iar
0≤ v < Dmy, Dmy = dimensiunea maxima pe linie.
Limitele Dmx •i Dmy depind de placa grafic• iar valorile acestora sunt
returnate de c•tre func•iile GetMaxX respectiv GetMaxY. De exemplu pentru
pl•ci de tipul EGAHi sau VGAMed, Dmx=640 iar Dmy=350.
Dac• dorim s• tras•m pe ecran primitive grafice referite prin coordonate
aflate într-un domeniu real, va trebui s• aplicam o transformare a acestor
coordonate, pentru c• instruc•iunile grafice refer• puncte de coordonate întregi
din domeniul [0 , Dmx] × [0 , Dmy].
Exist• posibilitatea de a realiza un
desen doar pe o por•iune a ecranului, pe un
subdomeniu [u1,u2] × [v1,v2] al domeniului
maxim [0,Dmx]×[0,Dmy].
Acest subdomeniu îl vom numi
fereastra fizic• (ViewPort) •i va fi precizat
prin coordonatele ecran a dou• puncte
diagonal opuse P1(u1,v1) •i P2(u2,v2).
0 u Dmx
0
v
Dmy
o P(u,v)
WiewPort
P1(u1,v1) v1
v2
o
o P2(u2,v2)
u1 u2
135
14.2. Instruc•iuni grafice.
Instruc•iunile grafice utilizeaz• proceduri, func•ii, tipuri de date, constante
•i variabile din unitul Graph. În acest paragraf vom descrie câteva din
posibilit••ile de lucru în mod grafic.
Deschiderea unei sesiuni grafice (trecerea în modul de lucru grafic) se
execut• prin apelul procedurii InitGraph (Gd,Gm,Pd) unde:
- Gd este parametrul "GraphDriver" •i poate lua valori întregi, de exemplu
0=Detect (selectare automat• în func•ie de tipul pl•cii grafice de nivel cel
mai înalt), 3=EGA, 9=VGA, etc.
- Gm este parametrul "GraphMode" •i poate lua valori întregi de exemplu
1=EGAHi, 2=VGAHi, etc.
- Gp este parametrul "PathToDriver" de tip string care precizeaz• calea
pentru driverele grafice (subdirectorul în care se afl• fi•ierul
EGAVGA.BGI, de exemplu : ‘C:\Tp\Bgi’).
Trecerea cu succes în modul grafic se poate verifica cu ajutorul func•iei
GraphResult care returneaz• codul erorii opera•iei. Dac• trecerea a fost realizat•
corect atunci codul de retur va fi nul (0=GrOk).
Instruc•iunile grafice (func•ii •i proceduri ale unit-ului Graph) vor
func•iona corect doar pe timpul sesiunii grafice (în mod grafic între InitGraph •i
CloseGraph).
Programul urm•tor îsi propune s• deseneze ni•te cercuri în cazul în care
reu•este s• treac• în modul grafic, iar în caz contrar s• tip•reasca un mesaj de
nereu•it• a ini•ializ•rii grafice.
Program Modul_Grafic; {Programul 1. Modul Grafic}
Uses Graph; {Refera Unit_ul Graph.Tpu}
Var Gd,Gm : integer; {GraphDriver •i GraphMode}
Pd : string; {Path To Driver}
136
Begin
Gd:=Detect; {Selectare automata}
Pd:=’F:\Soft\Tp\Bgi’; {Calea fisierlui EGAVGA.Bgi}
InitGraph (Gd,Gm,Pd); {Selectarea modului grafic}
If GraphResult<>0 Then {Daca nu am trecut}
Begin {in modul grafic}
Write(’Eroare InitGraph.’); {tipareste mesaj}
Readln; Halt(1) {de eroare •i stop}
End; {If}
Circle (300,200,100); Circle (250,150, 10); {Deseneaza Cercuri(Xo,Yo,Raza)}
Circle (350,150, 10); Circle (290,200, 3);
Circle (310,200, 3); Circle (300,250, 20);
Readln; {Asteapta Enter inainte de a se sterge ecranul}
CloseGraph {Termina sesiunea grafica}
End.
Procedura Circle (Xo,Yo,R) apelat• în exemplul anterior traseaz• un cerc
cu centrul în punctul de coordonate (Xo,Yo) de raz• R.
În mod normal, desenarea se execut• pe tot ecranul. Este îns• posibil s•
alegem doar o parte a ecranului pe care s• desen•m, numit• fereastr• ecran
(ViewPort). Definirea ferestrei ecran pe care vom desena se realizeaz• prin
procedura
SetViewPort(u1,v1, u2,v2, decupat)
Prin u1,v1, u2,v2 vom preciza fereastra fizic• în care vom efectua opera•ii
grafice. Ace•ti parametri sunt de tip întreg •i îndeplinesc urm•toarele restric•ii:
o
o P2(u2,v2)
0 ≤ u1 < u2 < GetMaxX
0 ≤ v1 < v2 < GetMaxY
WiewPort
0
v1
v2
GetMaxY
P1(u1,v1)
0 u1 u2 GetMaxX
137
Parametrul "decupat" este de tip boolean. Dac• are valoarea True
(ClipOn) atunci la desenarea unei primitive grafice se va decupa portiunea din
fereastra definit•. Dac• acest parametru are valoarea False (ClipOff) nu se execut•
decuparea, ceea ce înseamn• c• va fi vizibil• toat• primitiva grafica, chiar dac•
aceasta dep••este domeniul ferestrei. În Unitul Graph sunt definite constantele
ClipOn •i ClipOff având valorile True respectiv False.
Dup• declararea unei ferestre fizice prin procedura SetViewPort, un punct
se va referi prin coordonatele relative la aceast• fereastr•.
În exemplul urm•tor se vor trasa ni•te cercuri înaintea definirii unei
ferestre fizice •i dup• definirea unor astfel de ferestre, cu •i f•r• decupare.
Program Ferestre_Ecran; {Programul 2. Cercuri}
Uses Graph; {Refera Unit_ul Graph.Tpu}
Type Da_Nu=(Da,Nu);
Var Gd,Gm: integer; Pd: string;{GraphDriver •i GraphMode; Path To Driver }
Procedure Cercuri(u1,v1,u2,v2: integer;Dec:Da_Nu); {Deseneaza cercuri in }
Begin { fereastra ecran cu/fara decupare}
If Dec=Da
Then SetViewPort(u1,v1,u2,v2,ClipOn )
Else SetViewPort(u1,v1,u2,v2,ClipOff);
Circle (100,100,100); Circle ( 50, 50, 10); Circle (150, 50, 10);
Circle ( 90,100, 3); Circle (110,100, 3); Circle (100,150, 20);
End;
o
v1
v M(u’,v’)
u1 u
u’ = u-u1
v’ = v-v1
138
Begin
Gd:=Detect; {Selectare automata}
Pd:=’c:\Tp\Bgi’; {Calea fis. EGAVGA.Bgi}
InitGraph (Gd,Gm,Pd); {Trec in mod grafic}
If GraphResult<>0 Then Begin {Sunt in mod grafica?}
Write (’Eroare InitGraph.’);
Readln; Halt (1)
End; {Deseneaza in diferite ferestre ecran}
Cercuri( 0, 0,200,200,Da); {stanga-sus, integral}
Cercuri(400, 0,600,200,Da); {dreapta-sus, integral}
Cercuri(250, 0,350,200,Da); {centru-sus, decupat stanga}
Cercuri( 0,250,200,350,Da); {stanga-jos, decupat sus}
Cercuri(250,250,350,350,Da); {centru-jos, decupat stanga-sus}
Cercuri(400,250,400,250,Nu); {dreapta-jos, nedecupat}
Readln; CloseGraph {Termina sesiunea grafica}
End.
Stergerea ecranului se poate realiza în întregime utilizând procedura
ClearDevice sau numai pe domeniul unei ferestre fizice declarate anterior,
utilizând procedura ClearViewPort.
Selectarea culorilor se realizeaz• prin apelul urm•toarelor proceduri:
SetColor(Culoare_cerneala), care alege culoarea de desenare, iar procedura
SetBkColor(Culoare_fond) alege culoarea fondului ecranului. Parametrii acestor
proceduri sunt de tip întreg, pot lua valori din domeniul 0..15 •i reprezint• codul
culorii dorite. În unitul Graph sunt declarate urm•toarele constante ce pot fi
utilizate de c•tre programator:
Black = 0; DarkGray = 8;
Blue = 1; LightBlue = 9;
Green = 2; LightGreen = 10;
Cyan = 3; LightCyan = 11;
Red = 4; LightRed = 12;
Magenta = 5; LightMagenta = 13;
Brown = 6; Yellow = 14;
LightGray = 7; White = 15;
139
Func•iile GetColor •i GetBkColor returneaz• culoarea curent• a cernelii
respectiv a ecranului.
Coordonatele punctului curent (cursorului grafic) pot fi ob•inute prin
apelurile func•iilor GetX •i GetY care returneaz• aceste valori (coordonatele
ultimului punct referit).
Punctul curent se poate muta (î•i poate schimba coordonatele f•r• trasare)
prin apelul procedurilor MoveTo(un,vn) sau MoveRel(Du,Dv). Procedura MoveTo
mut• vârful creionului grafic în punctul de coordonate (un,vn), acesta devenind
noul punct curent. Procedura MoveRel translateaz• punctul curent cu valorile
(Du,Dv), ceea ce permite precizarea coordonatelor noului punct curent în
coordonate relative fa•• de ultimul punct referit (vechea pozi•ie).
Unitul Graph con•ine rutine pentru trasarea unor primitive grafice, care
vor fi descrise în continuare.
Procedura PutPixel(u,v,c) deseneaz• în culoarea c punctul de coordonate
u,v.
Func•ia GetPixel(u,v) returneaz• codul culorii unui punct de coordonate
u,v. Pentru aceast• func•ie am ales un exemplu în care ne propunem s• umplem o
zon• din ecran cu o anumit• culoare. Aceasta zon• este format• din punctele la
care se poate ajunge mergând doar pe linie sau coloan• prin puncte de aceea•i
culoare cu un punct interior precizat.
Program Culoare_Pixel; Uses Graph; {Programul 3. Colorare }
Var Gd,Gm: integer; Pd: string;
Procedure Colorare(u,v,cn: integer); {Colorare din punctul (u,v) }
Var Cv: integer; { cu culoarea cn }
Procedure Umplere(u,v:integer);
Begin If GetPixel(u,v)=Cv Then Begin PutPixel(u,v,Cn);
Umplere (u+1,v); Umplere (u-1,v); Umplere (u,v+1); Umplere (u,v-1);
End End;
Begin
Cv:=GetPixel(u,v); Umplere(u,v);
End;
140
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’;
InitGraph (Gd,Gm,Pd);
If GraphResult<>0 Then
Begin
Write (’Eroare InitGraph’); Readln; Halt(1)
End;
SetColor(Blue); Circle(300,200,35);
SetColor(LightBlue); Circle(290,190, 7); Circle(310,190, 7);
SetColor(Brown); Circle(297,200, 2); Circle(303,200, 2);
SetColor(LightRed); Circle (300,217,10);
Colorare (300,200,Yellow); {Colorare din}
Readln; {punctul (300,200)}
CloseGraph {cu culoarea galben}
End.
În exemplul prezentat, frontiera zonei ce va fi colorat• este format• din
puncte de culoare diferit• de cea a punctului interior dat.
Procedura Line(ui,vi,uf,vf) traseaz• în culoarea curent• segmentul ce are ca
extremit••i punctele (ui,vi) •i (uf,vf). De exemplu Line(0,0,GetMaxX,GetMaxY),
are ca efect desenarea diagonalei principale a ecranului.
Un segment se mai poate trasa utilizând procedura LineTo (uf,vf) care
deseneaz• segmentul determinat de ultimul punct referit (punctul curent) •i
punctul de coordonate (uf,vf) precizat prin parametrii procedurii LineTo. Apelul
Line(ui,vi,uf,vf) este echivalent cu MoveTo(ui,vi) urmat de LineTo(uf,vf). În
paragraful urm•tor (14.3) este dat un exemplu de reprezentare grafic• a unor
func•ii în care sunt utilizate procedurile Line •i LineTo (programul 14.7).
Procedura LineRel (Du,Dv) traseaz• un segment de la punctul curent
P(u,v) pâna la punctul P’(u+Du,v+Dv). Programul urm•tor permite realizarea
unui desen prin segmente orizontale •i verticale utilizând tastele O, P, Q •i A
pentru trasarea spre stânga (Du=−5), dreapta (Du=+5), sus (Dv=−5) respectiv jos
(Dv=+5).
141
Program Desen; Uses Graph, Crt; {Programul 14.4. Linie franta}
Const l=5;
Var Gd,Gm: integer; Pd : string; Sens : Char;
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’; InitGraph (Gd,Gm,Pd);
If GraphResult<>0 Then Begin Write (’Eroare InitGraph.’); Halt (1) End;
MoveTo(GetMaxX Div 2, GetMaxY Div 2); {Centrul ecranului }
Repeat
Repeat Until KeyPressed; Sens:=UpCase(ReadKey);
Case Sens Of
’O’: LineRel (-l, 0);
’P’: LineRel ( l, 0);
’Q’: LineRel ( 0,-l);
’A’: LineRel ( 0, l)
End {Case}
Until not (Sens in [’O’,’P’,’Q’,’A’]); Readln; CloseGraph
End.
Procedura Rectangle (ui,vi,uf,vf) deseneaz• dreptunghiul determinat de
vârfurile diagonal opuse (ui,vi) •i (uf,vf). De exemplu Rectangle (0,0,100,100)
deseneaz• un p•trat de latur• 100 în coltul din stânga-sus al ecranului.
Procedura Bar (ui,vi,uf,vf) realizeaz• •i umplerea (colorarea interiorului)
unui dreptunghi (semnifica•ia parametrilor fiind aceea•i). Un exemplu cu
ultimele dou• proceduri este dat în paragraful 14.3. Acestea sunt utilizate în
trasarea unei histograme în programul 14.8.
Pentru desenarea unui arc de cerc sau a unui sector de cerc, procedurile
Arc respectiv PieSlice solicit• urm•torii parametri:
- coordonatele centrului cercului,
- unghiul initial •i final exprimat în grade,
- raza cercului.
Procedura SetFillStyle(Model,Culoare) se utilizeaz• pentru umplerea unui
sector cu un Model dorit desenat într-o Culoare precizat•.
142
Ca exemplu am ales desenarea unei diagrame circulare a precipita•iilor
zilnice dintr-o s•pt•mân•. Dac• se cunosc precipita•iile preci (i=1,7) se poate
calcula unghiul ini•ial •i final (în grade) pentru fiecare sectori astfel:
uii=si-1/sn*360 •i ufi=si/sn*360, unde si=prec1+prec2+...+preci (s0=0).
Program Diagrama_Circulara; {Programul 14.5}
Uses Graph;
Const
Prec: Array[1..7] of integer = (25,10,15,20,25,17,5);
Var Pd : string;
Ui,Uf, Suma, i, Gd,Gm: integer;
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’ ;
InitGraph (Gd,Gm,Pd);
If GraphResult<>0 Then Begin
Write (’ Eroare InitGraph . ’); Readln; Halt (1)
End;
Suma:=0;
For i:=1 to 7 do Suma:=Suma+Prec[i];
Ui:=0;
For i:=1 to 7 do
Begin
Uf:=Ui+Round(Prec[i]*360/Suma);
SetFillStyle(i,i+8); {Umple cu modelul i in culoarea i+8}
PieSlice(GetMaxX div 2, GetMAxY div 2, {Coordonatele centrului}
Ui, Uf, 200 ); {Unghi initial •i final , Raza }
Ui:=Uf;
End;
Readln; CloseGraph
End.
143
Procedura Ellipse (uo,vo, gi,gf, rx,ry) deseneaz• un arc de elips• cu centrul
(uo,vo) cuprins între unghiurile gi,gf exprimate în grade hexazecimale având axele
rx,ry.
Procedura FillEllipse (uo,vo, rx,ry) deseneaz• •i umple un arc de elips• cu
centrul (uo,vo) cuprins între unghiurile gi,gf, iar procedura Sector (uo,vo, gi,gf, rx,ry)
deseneaz• •i umple un sector de elips• precizat prin parametrii actuali a c•ror
semnifica•ie a fost deja prezentat•.
Pentru a tip•ri pe ecran un text în modul grafic se pot utiliza procedurile
OutText (Mesaj) sau OutTextxy (u,v,Mesaj). Mesaj-ul este o expresie de tip string
•i va fi tip•rit• începând din ultimul punct referit (în cazul procedurii OutText)
respectiv din punctul de coordonate u,v (OutTextxy).
Apelul OutTextxy(u,v,Mesaj) este echivalent cu MoveTo(u,v) urmat de
OutText(Mesaj). De exemplu:
OutTextxy(GetMaxX Div 2, GetMaxY Div 2,’Centrul ecranului’)
are ca efect tip•rirea începând din mijlocul ecranului a textului "Centrul
ecranului".
La tip•rirea textelor se pot utiliza anumite fonturi puse la dispozi•ia
programatorului, se poate preciza direc•ia de scriere (orizontal• sau vertical•)
precum •i dimensiunea caracterelor. Aceste trei elemente se pot preciza prin
apelul procedurii SetTextStyle (Font,Directie,Marime).
Dac• se dore•te o scalare a caracterelor care vor fi tip•rite, atunci se poate
realiza acest lucru prin apelul procedurii SetUserCharSize (MultX,DivX,
MultY,DivY).
În programul 14.8 din paragraful 14.3 sunt utilizate proceduri de tip•rire a
textelor.
144
14.3. Desenarea pe ecran a figurilor din planul real.
În fereastra ecran [u1, u2] × [v1, v2] (ViewPort) putem reprezenta puncte
P(x,y) dintr-un domeniul [a,b] × [c,d] ⊂ R2 numit fereastr• real• (Window)
(vezi fig.14.3.1). Pentru a putea referi în instruc•iunile grafice un astfel de punct,
va trebui s• aplic•m o transformare de coordonate P(x,y) → M(u,v), care verific•
egalit••ile :
x-a u - u1
= b-a u2-u1 u:=Round((x-a)*(u2-u1)/(b-a))+u1
de unde rezult• y-d v- v1 v:=Round((y-d)*(v2-v1)/(c-d))+v1. = c-d v2-v1
Figura 14.3.1.
Pentru reprezentarea unei func•ii, a •i b pot fi capetele domeniului de
definitie, iar c •i d minimul respectiv maximul func•iei pe intervalul [a,b].
Dac• dorim s• referim un punct de coordonate reale din fereastra logic•
(Window) dup• declararea ferestrei ecran (ViewPort) atunci transformarea
P(x,y) → M(u’,v’), (x,y)∈[a,b]×[c,d],
necesar• pentru apelul unei rutine grafice este urm•toarea:
u’:=Round((x-a)*(u2-u1)/(b-a))
v’:=Round((y-d)*(v2-v1)/(c-d))
o
P1 (u1,v1)0
v1
v
v2
GetMaxY
M(u,v)
0 u1 u u2 GetMaxX
WiewPort
o
o
Ecranul
P2 (u2,v2)
y
c
Window
P(x,y) o
Planul real
a x b
d
145
Aceast• transformare va fi efectuat• dup• declararea ferestrei fizice prin
procedura SetViewPort pentru c• u’ •i v’ reprezint• coordonate relative din
fereastra ecran (vezi ViewPort descris în paragraful precedent).
În exemplul urm•tor se traseaz• locul geometric al mijloacelor segmentelor
de lungime dat• cu capetele pe dou• semidrepte perpendiculare.
Program Puncte; {Programul 14.6}
Uses Graph; {Loc geometric}
Var Gd, Gm: integer;
Pd: string;
x, l: real;
u1, u2, v1,v2: integer;
a, b, c, d: real;
Function u (x:real):integer; {Transformarea}
Begin u:=Round((x-a)*(u2-u1)/(b-a)) End; {coord. x→ u}
Function v (y:real):integer; {Transformarea}
Begin v:=Round((y-d)*(v2-v1)/(c-d)) End; {coord. y→ v}
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’;
InitGraph (Gd,Gm,Pd); l:=100; { l = Lung. Segm.}
a:=0; b:=l; c:=0; d:=l; {ViewPort}
u1:=200; v1:=100; u2:=400; v2:=300; {Window}
SetViewPort(u1,v1,u2,v2,ClipOn);
x:=0;
Repeat
PutPixel(u(x),v(0),Yellow); {Axa Ox}
PutPixel(u(x/2),v(Sqrt(Sqr(l)-Sqr(x))/2), White); {Mijloc}
PutPixel(u(0),v(Sqrt(Sqr(l)-Sqr(x))), Yellow); {Axa Oy}
x:=x+0.1;
Until x>l;
Readln; CloseGraph
End.
146
În exemplul urm•tor vom trasa graficul mai multor func•ii în diferite
ferestre ecran. Pentru a trasa axele de coordonate vom utiliza procedura Line iar
graficul func•iei îl vom realiza prin segmente desenate cu procedura LineTo.
Datorit• faptului c• vom lucra în coordonate reale, va trebui ca la apelurile
procedurilor grafice s• executam transform•rile în coordonate ecran prin func•iile
u •i v .
Program Grafice_de_Functii; { Programul 14.7. Graficele func•iilor }
{$F+} Uses Graph; { f, g, s, c }
Type Functie=Function(x:real):real;
Var Gd, Gm:integer; Pd:string;
Function f(x:real):real; Begin f:=Exp(Abs(x)) End;
Function g(x:real):real; Begin g:=Ln(Abs(x)) End;
Function s(x:real):real; Begin s:=Sin(x) End;
Function c(x:real):real; Begin c:= Cos(x) End;
Procedure Grafic(f: Functie; a,b,: real; u1,v1, u2,v2: integer); {f:[a,b]→R}
Var x,p,y : real;
Function u(x:real):integer; Begin u:=Round((x-a)*(u2-u1)/(b-a))+u1 End;
Function v(y:real):integer; Begin v:=Round((y-d)*(v2-v1)/(c-d))+v1 End;
Begin
SetColor(White); MoveTo(u1,v1); {Fereastra fizica}
LineTo (u2,v1); LineTo(u2,v2);
LineTo (u1,v2); LineTo(u1,v1);
p:=3*(b-a)/(v2-v1); {p=pasul pentru x}
x:=a; c:=f(a); d:=f(a);
While x<=b do Begin y:=f(x); {Pentru x:=a,b,p executa}
If y<c Then c:=y Else If y>d Then d:=y { c /d = min / max(f(x)) }
x:=x+p End;
SetColor(DarkGray); {Axele de coordonate}
If a*b<0 Then Line(u(0),v(c),u(0),v(d)); {Axa Oy}
If c*d<0 Then Line(u(a),v(0),u(b),v(0)); {Axa Ox}
x:=a; MoveTo (u(x),v(f(x))); SetColor(LightBlue); {Trasare grafic}
While x<=b do Begin {Pentru x:=a,b,p executa}
LineTo(u(x),v(f(x))); x:=x+p End; {trasare(x,f(x))}
End;
147
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’; InitGraph (Gd,Gm,Pd);
Grafic (f, -Pi, Pi, 10, 10, 310, 150);
Grafic (g, -Pi, Pi,320, 10, 620, 150);
Grafic (s,-2*Pi,3*Pi, 10,160, 310, 340);
Grafic (c,-3*Pi, Pi,320,160, 620 ,340);
Readln; CloseGraph
End.
În programul urm•tor vom desena
o histogram• a temperaturilor medii
lunare dintr-un an, realizat• cu
dreptunghiuri de forma al•turat•:
Program Histograma_Temperaturi; {Programul 14.8}
Uses Graph;
Const Temp:Array[1..12] of integer= (-5,-10,-4,5,10,15,20,25,17,10,7,6); {Temp.}
Luna:Array[1..12] of string[3]= {Lunile anului}
(’Ian’,’Feb’,’Mar’,’Apr’,’Mai’,’Iun’,’Iul’,’Aug’,’Sep’,’Oct’,’Nov’,’Dec’);
Var a,b,c,d: real; {Window}
Pd: string;
u1,v1,u2,v2, i,j,Gd,Gm: integer; {ViewPort}
Function u(x:real): integer; Begin u:=Round((x-a)*(u2-u1)/(b-a)) End;
Function v(y:real): integer; Begin v:=Round((y-d)*(v2-v1)/(c-d)) End;
Begin
Gd:=Detect; Pd:=’F:\Soft\Tp\Bgi’; InitGraph(Gd,Gm,Pd);
SetColor(White);
u1:=20; v1:=20; u2:=GetMaxX-20; v2:=GetMaxY-20;
Rectangle(u1,v1, u2,v2); SetViewPort(u1,v1,u2,v2,ClipOn);
a:=-1; b:=15; d:=Temp[1]; c:=Temp[1];
For i:=2 to 12 do Begin
If Temp[i]>d Then d:=Temp[i] Else {Maximul func•iei}
If Temp[i]<c Then c:=Temp[i] End; {Minimul func•iei}
c:=c-2; d:=d+5;
148
SetTextStyle(GothicFont,HorizDir,5);
OutTextxy(u(2),v(d),’Histograma temperaturilor’);
SetTextStyle(SansSerifFont,HorizDir,3); OutTextxy (u(13),v(0),’Luna’);
SetTextStyle(SansSerifFont,VertDir,3); OutTextxy (u(-1),v(d),’Temp.’);
SetColor(DarkGray); Line (u(0),v(c),u(0),v(d)); {Axa Oy}
Line (u(a),v(0),u(b),v(0)); {Axa Ox}
SetColor(LightBlue); {Trasare}
For i:=1 to 12 do Begin {histograma}
SetFillStyle(i Mod 6 +3,i+2); Bar(u(i),v(0),u(i+1),v(Temp[i]));
SetTextStyle(SmallFont,VertDir,5); OutTextxy (u(i+0.5),v(0),Luna[i]);
End; {For}
Readln; CloseGraph
End.
Reprezentarea grafic• a unor curbe remarcabile cum ar fi astroida care are
ca ecua•ie:
x2/3+y2/3=a2/3,
se poate realiza simplu dac• aceast• curb• este descris• de forma parametric• :
x=a·sin3t, y=a·cos3t (în programul Pascal a=Cst).
Program Graficul_unei_func•ii_Parametrice; {Programul 14.9}
Uses Graf, Graph; {x=X(t);y=Y(t)}
Const Marx=50; Mary=10; t1=0; t2=2*Pi; Cst=3; {Cst=a}
Function x(t:real): real;
Begin x:=Cst*Sqr(Sin(t))*Sin(t) End; {x(t)=a*Sin3t}
Function y(t:real): real;
Begin y:=Cst*Sqr(Cos(t))*Cos(t) End; {y(t)=a*Cos3t}
Var t, p, a,b, c,d : real;
Begin
SetColor(Yellow);
Rectangle(Marx-1,Mary-1,GetMaxX-Marx+1,GetMaxY-Mary+1);
View(Marx,Mary,GetMaxX-Marx,GetMaxY-Mary);
SetBkColor(Blue); ClearViewPort;
a:=x(t1); b:=x(t1); c:=y(t1); d:=y(t1); p:=(t2-t1)/200; t:=t1;
149
Repeat {Det.Window}
If x(t)>b Then b:=x(t) Else If x(t)<a Then a:=x(t);
If y(t)>d Then d:=y(t) Else If y(t)<c Then c:=y(t);
t:=t+p
Until t>t2;
Window_(a,d,b,c); SetColor(DarkGray); {Set Window}
If c*d<=0 Then Line(u(a),v(0),u(b),v(0)); {Axa Ox}
If a*b<=0 Then Line(u(0),v(c),u(0),v(d)); {Axa Oy}
t:=t1; MoveTo(u(x(t)),v(y(t)));
SetColor(White);
Repeat {Graficul}
LineTo(u(x(t)),v(y(t))); t:=t+p
Until t>t2; Readln
End.
Pentru aceasta am utilizat unit-ul (Graf) urm•tor :
Unit Graf;
INTERFACE
Uses Graph;
Var Gd,Gm, {Var.pt.InitGraph}
Vl,Vr,Vd,Vt: integer; { ... ViewPort}
Wl,Wr,Wd,Wt: real; { ... Window }
Procedure View(l,t,r,d:integer); {(Left, Top),}
Procedure Window_(a,d,b,c:real); {(Rigth,Down)}
Function u(x:real):integer; {Transf. x→u}
Function v(y:real):integer; { ... y→v}
Procedure Linie(x1,y1,x2,y2: real); {Trasare segment}
Procedure Punct(x,y:real;Cul: Byte); {Desenare punct}
IMPLEMENTATION
Function u; Begin u:=Round((x-Wl)/(Wr-Wl)*(Vr-Vl)) End;
Function v; Begin v:=Round((y-Wt)/(Wd-Wt)*(Vd-Vt)) End;
150
Procedure View;
Begin Vl:=l; Vr:=r; Vd:=d; Vt:=t; SetViewPort(l,t,r,d,ClipOff) End;
Procedure Window_;
Begin Wl:=a; Wr:=b; Wd:=c; Wt:=d End;
Procedure Linie;
Begin Line(u(x1),v(y1),u(x2),v(y2)) End;
Procedure Punct;
Begin PutPixel(u(x),v(y),Cul) End;
Begin
InitGraph (Gd,Gm,’C:\Tp\Bgi’);
If GraphResult<>GrOk Then Begin Write(’Err.Init Graph’); Readln; Exit
End {if}
End.
O problem• (de geometrie) de loc geometric o vom formula în continuare.
În triunghiul PQR se iau punctele E •i F pe laturile PQ respectiv PR
astfel încât PE=QF. Se cere s• se reprezinte grafic locul geometric al
mijloacelor segmentelor EF (N), dac• E •i F se plimb• pe laturile triunghiului
dat.
Program Loc_geometric_triunghi; {Programul 14.10}
Uses Crt, Graph, Graf; Const Marx=20; Mary=10;
Type Coord_Plan = Record x,y : real End;
Var m, pas, a,b, c,d : real; P,Q,R,E,F,N: Coord_Plan;
Procedure Rnd(Var L:Coord_Plan; v: integer); {Date L(x,y)}
Begin With L do Begin x:=v*100; y:=130*(1-Abs(v)) End End;
Function Min(a,b:real):real;
Begin If a<b Then Min:=a Else Min:=b End;
Function Max(a,b:real):real;
Begin Max:=a+b-Min(a,b) End;
Procedure Segment(A,B:Coord_Plan);
Begin Linie (A.x,A.y, B.x,B.y) End;
151
Begin SetBkColor(Blue); ClearViewPort;
Rnd(P,0); Rnd(Q,-1); Rnd(R,1); SetColor(Yellow); {Triunghiul PQR}
Rectangle (Marx-1,Mary-1, GetMaxX-Marx+1,GetMaxY-Mary+1); {ViewPort}
View (Marx,Mary, GetMaxX-Marx,GetMaxY-Mary);
a:=Min(P.x,Min(Q.x,R.x)); b:=Max(P.x,Max(Q.x,R.x)); {Det.Window}
c:=Min(P.y,Min(Q.y,R.y)); d:=Max(P.y,Max(Q.y,R.y));
pas:=1/300; SetColor(DarkGray); Window_(a,d,b,c); {Def.Window}
If c*d<=0 Then Line(u(a),v(0),u(b),v(0)); {Axa Ox}
If a*b<=0 Then Line(u(0),v(c),u(0),v(d)); {Axa Oy}
SetColor(Yellow);
Linie(P.x,P.y, Q.x,Q.y); Linie(Q.x,Q.y, R.x,R.y); Linie(R.x,R.y, P.x,P.y); {∆.PQR}
m:=0; SetColor(LightBlue); SetWriteMode(XorPut);
Repeat {Pt. m=0,1,pas}
E.x:=m*P.x+(1-m)*Q.x; E.y:=m*P.y+(1-m)*Q.y; {E=Afin (PQ)}
F.x:=m*R.x+(1-m)*P.x; F.y:=m*R.y+(1-m)*P.y; {F=Afin (RP)}
N.x:=(E.x+F.x)/2; N.y:=(E.y+F.y)/2; {N=Mijl (EF)}
Segment(E,F); Delay(10); Segment(E,F); {Desenez apoi sterg segm. EF }
With N do Punct(x,y,Yellow); {Pun punct N}
m:=m+pas
Until m>1;
End.
Pentru a desena imagini definite recursiv am ales exemplul urm•tor :
1) 2) 3)
Programul Pascal care realizeaz• astfel de imagini utilizând limbaje de
comenzi, este prezentat în continuare. O astfel de figur• se poate defini printr-o
baz•, o regul• de dezvoltare (de cre•tere) •i num•rul de transform•ri aplicate
(vârsta în ani).
152
Program Grafica_Recursiva; {Programul 14.11}
Uses Crt,Graph;
Var Suc,Pre: Array [’A’..’Z’] of char;
C : string; Gd,Gm : integer;
Procedure Succ_Pred;
Var p,i:integer;
Begin
p:=Length(C);
Suc[C[1]]:=C[2]; Pre[C[1]]:=C[p]; Suc[C[p]]:=C[1];
Pre[C[p]]:=C[p-1];
For i:=2 to p-1 do Begin Suc[C[i]]:=C[i+1]; Pre[C[i]]:=C[i-1] End
End;
Function Fi(x:Char): string; {Regula de dezvoltare}
Begin Fi:=x+Suc[x]+x+Pre[x]+x
End;
Function T(X:string): string; Var R:string; i:integer; {Cresterea cu un an }
Begin
If Length(X)=1 Then T:=Fi(X[1]) Else Begin
R:=’’; For i:=1 to Length(X) do R:=R+Fi(X[i]); T:=R End
End;
Function Tn(n:integer; X:string):string; {Cresterea in n ani}
Begin If n=1 Then Tn:=T(X) Else Tn:=Tn(n-1,T(X))
End;
Procedure Desen(S:string; x,y,l:integer); {Trasarea}
Var i:integer; {comenzilor}
Begin
MoveTo (x,GetMAxY-y);
For i:=1 to Length(S) do Begin
If S[i] in [’R’,’E’,’H’] Then x:=x+l Else If S[i] in [’L’,’F’,’G’] Then x:=x-l;
If S[i] in [’U’,’F’,’E’] Then y:=y+l Else If S[i] in [’D’,’G’,’H’] Then y:=y-l;
LineTo (x,GetMaxY-y)
End;
End;
153
Begin
Gd:=Detect; InitGraph(Gd,Gm,’c:\tp\bgi’);
C:=’RULD’; {Dreapta=R,Sus=U} Succ_Pred; {Stanga=L,Jos=D}
Desen(Tn(1,’R’), 10,170,28); {Anul I, baza R}
Desen(Tn(2,’R’),200,170,14); {Anul II, " }
Desen(Tn(3,’R’),400,170, 7); {Anul III, " }
Readln; CloseGraph;
End.
Pentru a reprezenta o suprafa•• definit• de o func•ie z : [a,b]x[c,d] → R,
va fi necesar• o proiec•ie a punctelor din R3 în planul XOY. Vom considera o
proiec•ie paralel• dup• o direc•ie precizat• prin dou• elemente: r •i α, a•a cum se
poate vedea în figura urm•toare:
Pentru un punct oarecare P(x,y,z) va
trebui s• calculam coordonatele x’ •i y’ ale
proiec•iei acestuia dup• direc•ia precizat•.
Se poate observa c• triunghiul AOB este
asemenea cu triunghiul PDP’, de unde
rezult• c• 1/r=z/DP’, deci DP’=r⋅z . Pentru
c• x’=x+DP’·cosα •i y’=y+DP’·sinα rezult•
c• x'=x+r·z·cosα iar y’=y+r·z·sinα.
1
Urm•torul program Pascal, deseneaz• suprafa•a descris• de func•ia:
z:[-π,π]×[-π,π]→R, z(x,y)=sin x2+cos y2, aplicând o proiec•ie paralel• de
direc•ie (r,a) = (1, π/4).
Trasarea suprafe•ei se reduce la o problem• plan•. Pentru un punct x fixat,
iar y variabil din intervalul [c,d] se traseaz• graficul proiec•iei corespunz•toare
punctelor P(x,y,z(x,y)).
P’
(0,0,1)
α
α
r
P
y,y’
A
B
O
D E
z
x,x’
154
Acest lucru se realizeaz• pentru mai multe puncte x alese din intervalul
[a,b] (n+1 puncte echidistante). Acela•i lucru se realizeaz• pentru y fix •i x
variabil, realizând astfel o imagine sub forma unei plase (ca în figura urm•toare).
Practic se reprezint• dou• •iruri de
curbe z(xi,y) •i z(x,yj), unde :
xi=a+i*(b-a)/n (i=0,1,...,n),
yj=c+j*(d-c)/m (j=0,1,...,m), iar n •i m
reprezint• fine•ea re•elei.
Program Suprafata; {Programul 14.12}
Uses Graph;
Var Vl,Vr, Vd,Vt, Wl,Wr, Wd,Wt, Gd,Gm, n,m : integer;
a,b, c,d, x,y, pas_x, pas_y, Ux,Uy, r,Alfa : real;
Function z(x,y:real):real; {z:[a,b]x[c,d]->R}
Begin z:=Sin(Sqr(x)+Sqr(y)); End;
Function Px(x,z:real):real; {Calculeaza x’}
Begin Px:=x+r*z*Cos(Alfa) End;
Function Py(y,z:real):real; {Calculeaza y’}
Begin Py:=y+r*z*Sin(Alfa) End;
Function u(x:real):integer;
Begin u:=Round((x-Wl) / (Wr-Wl)*(Vr-Vl))+Vl End;
Function v(y:real):integer;
Begin v:=Round((y-Wd)/(Wt-Wd)*(Vt-Vd))+Vd End;
Begin Gd:=Detect; InitGraph(Gd,Gm,’f:\soft\tp7\bgi’);
r:=1; Alfa:=Pi/4; n:=20; m:=20; {def.dir.pr. , def.diviz }
Vl:=100; Vr:=GetMaxX-100; Vt:=50; Vd:=GetMaxY-50; {ViewPort}
a:=-Pi; b:=Pi; c:=-Pi; d:=Pi; {dom.def.}
Pas_x:=(b-a)/n; Pas_y:=(d-c)/m;
155
Wl:=Px(a,z(a,c)); Wr:=Px(a,z(a,c)); {Max,Min/x’,y’ (Window) }
Wd:=Py(c,z(a,c)); Wt:=Py(c,z(a,c));
x:=a; Repeat y:=c;
Repeat Ux:= Px(x,z(x,y));
If Ux<Wl Then Wl:=Ux Else If Ux>Wr Then Wr:=Ux;
Uy:= Py(y,z(x,y));
If Uy<Wd Then Wd:=Uy Else If Uy>Wt Then Wt:=Uy;
y:=y+pas_y
Until y>d; x:=x+pas_x
Until x>b; SetColor (LightGray);
Line (u(Px(a,0)),v(Py(0,0)), u(Px(b,0)),v(Py(0,0))); {Axe}
Line (u(Px(0,0)),v(Py(c,0)), u(Px(0,0)),v(Py(d,0)));
Line (u(Px(0,0)),v(Py(0,0)), u(Px(0,z(a,c))), v(Py(0,z(a,c))));
Circle(u(Px(0,0)),v(Py(0,0)),2); {originea}
x:=a; SetColor(12); {x fixat, y variabil}
Repeat y:=c; {Pt. x=a,b,pas_x : muta. P’(x’,y’)}
MoveTo (u(Px(x,z(x,y))), v(Py(y,z(x,y)))); y:=y+pas_y;
Repeat {Pt. y=c,d,pas_y : tras. P’(x’,y’)}
LineTo (u(Px(x,z(x,y))), v(Py(y,z(x,y)))); y:=y+pas_y
Until y>d; x:=x+pas_x
Until x>b;
y:=c; SetColor(13); {y fixat, x variabil}
Repeat x:=a; {Pt. y=c,d,pas_y : muta. P’(x’,y’)}
MoveTo (u(Px(x,z(x,y))), v(Py(y,z(x,y))));
x:=x+pas_x;
Repeat {Pt. x=a,b,pas_x : {tras. P’(x’,y’)}
LineTo (u(Px(x,z(x,y))), v(Py(y,z(x,y))));
x:=x+pas_x
Until x>b; y:=y+pas_y
Until y>d;
Readln; CloseGraph
End.