Aplicatie Grafica pe Baza Curbelor Bezier Utilizand Limbajul Java

Cuprins

Tratarea matematică a curbelor Bézier

I.1 Scurta descriere a curbelor Bézier

I.2 Construcția și clasificarea curbelor Bézier

I.3 Curbe Bézier în baza Bernstein

I.4 Algoritmul de Casteljau

I.5 Legatura dintre forma Bernstein și algoritmul de Casteljau

I.6 Derivatele unei curbe Bézier

I. 7 Modificarea unei curbe Bézier

Tratarea informatică a curbelor Bézier

II.1 Scurtă prezentare a curbelor Bézier

II.2 Interpretarea grafică a curbelor Bézier

II.3 Curbele Bézier și fonturile TrueType

II.4 Descrierea suprafețelor la modul general

II.5 Suprafețe Bézier

Prezența curbelor Bézier în alte domenii

III.1 Prezența curbelor Bézier în infrastructură

III.2 Prezența curbelor Bézier în pictură

Prezentarea tehnologiilor utilizate în dezvoltarea aplicației

IV.1 Limbajul de programare Java

IV.2 Mediul de dezvoltare Eclipse

IV.3 Tehnologia AWT

IV.4 Tehnologia Swing

Prezentarea generală a aplicației

Bibliografie

APLICAȚIE GRAFICĂ PE BAZA CURBELOR BZIER UTILIZÂND LIMBAJUL JAVA

Prefață

Modelarea geometrică(Computer Aided Geometric Design) este o ramură a matematicii și informaticii care se bazează pe concepte geometrice utilizate în grafica pe calculator. Problemele legate de proiectarea algoritmică a curbelor și suprafețelor sunt utile în grafica pe calculator și în proiectarea asistată de calculator. Modelarea geometrică reprezintă procesul în urma căruia un obiect fizic sau virtual este descris din punct de vedere matematic.

Dacă ar fi să prezentăm pe scurt dezvoltarea geometriei computaționale, am putea afirma că principalii algoritmi s-au bazat pe unele rezultate din analiza numerică și au fost concepuți în atelierele de creație ale unor firme cunoscute: Boeing, Renault, Citron etc., fiind folosiți în automatizarea unor operații de proiectare pentru diverse componente ale unor mașini și mecanisme produse de aceste firme. În faza inițială (adică prin anii 1960-1970), rezultatele erau redactate ca niște rapoarte de cercetare interne și erau considerate secret de serviciu. Publicarea acestor rapoarte s-a făcut atunci când și firmele concurente au ajuns la rezultate de același tip și păstrarea acestora ca secrete nu mai avea sens.

Altfel spus, cei dintâi beneficiari ai modelării geometrice au fost industria constructoare de mașini și industria aviatică.

În ultima perioadă de timp modelarea geometrică s-a extins într-o largă sferă de domenii, începând cu generarea de imagini media și ajungând la lucruri foarte complexe, precum reconstrucția 3D a corpurilor si aplicații in tomografiile computerizate.

Dacă vrem să realizăm desene în 2D, de cele mai multe ori ne folosim de linii drepte și de curbe. Liniile drepte sunt ușor de desenat și la fel de ușor de generat cu ajutorul computerului. Este suficient să alegem primul și ultimul punct și linia dreapta dintre cele două este generată. Pe de altă parte, curbele sunt mai complicate. Dacă pentru o persoană desenatul unei curbe reprezintă un lucru banal, realizarea acestui lucru cu ajutorul unui computer este mai dificil. Pentru a desena o curbă cu ajutorul computerului avem nevoie de o funcție matematică cu ajutorul căreia să descriem modul în care ar trebui desenată funcția.

Curbele și suprafețele Bézier reprezintă unele din elementele fundamentale pe care se bazează modelarea geometrică.

Tema acestei lucrări este reprezentată de curbele Bézier și de aplicațiile grafice care se pot genera pe baza lor. Lucrarea de fața va fi structurată în cinci capitole.

În primul capitol vor fi prezentate din punct de vedere matematic curbele Bézier. Voi prezenta clasificarea curbelor Bézier în funcție de numărul de puncte ale poligonului de control, modalitătile de reprezentare a curbelor Bézier în baza Bernstein și folosind algoritmului de Casteljau. Acest capitol cuprinde și legătura dintre algorimul lui de Casteljau și forma Bernstein, derivatele unei curbe Bézier și modalitățile de modificare ale unei curbe Bézier.

În cel de-al doilea capitol voi trata curbele Bézier din punct de vedere informatic și voi descrie câteva dintre întrebuințările lor în grafica pe calculator. Dintre cele mai importante aplicații pe baza curbelor Bézier amintim fonturile TrueType și suprafețele Bézier.

În cel de-al treilea capitol voi prezenta, pe scurt, modul în care curbele Bézier pot fi regăsite și în afara domeniilor deja consacrate: matematică și informatică. Menționez prezența curbelor Bézier în infrastructură (Podul Strings din Ierusalim) și în artă (picturile lui Pablo Picasso).

Cel de-al patrulea capitol voi prezenta tehnologiile folosite în cadrul dezvoltării aplicației.

Ultimul capitol al lucrării va consta în aplicația practică, descrierea ei, câteva părți ale codului sursă și print screen-uri din cadrul acesteia.

Capitolul I: TRATAREA MATEMATICA A CURBELOR BZIER

I.1 Scurta descriere a curbelor Bézier

Principalul scop al modelării geometrice este acela de a realiza imagini cât mai realiste.

În modelarea geometrică se lucrează în mare parte cu curbe polinomiale. Curbele polinomiale reprezintă curbele definite de o parametrizare polinomială de tipul:

c : [a,b] → R3 , c(t) = (x1(t), x2(t), x 3(t)), cu xi ∈ Pn[a,b], i ∈{1,2,3}, unde:

Pn [a,b] = { P: [a,b] → R | P(t) = a0 + a1 t + a2t2 + …. + antn, ai ∈ R, i= }.

Maximul gradelor polinoamelor xi, i= se numește gradul curbei.

Fie (b0, b1, …, bn) o mulțime ordonată de puncte din Rm. Aceasta poartă numele de poligon de control (sau poligon caracteristic). Punctele bi, i= se numesc puncte de control (puncte caracteristice) iar segmentele determinate de punctele bi si bi+1, i= se numesc laturi ale poligonului. Implicit, dacă punctele bn și b0 coincid, poligonul de control se numește poligon inchis.

În încercarea sa de a proicta sub forme cât mai diferite capotele automobilelor, Pierre Bézier, inginer la Renault a venit cu ideea de a exprima funcțiile polinomiale aparținând mulțimii Pn [0,1], relativ la baza Bernstein, B’ = , în locul bazei canonice: B = (1, t, t2, …, tn).

O curbă Bézier reprezintă o linie curbă sau o traiectorie definită de ecuații matematice. Aceste curbe au fost denumite după matematicianul și inginerul Pierre Bézier în anii 1960.

Curbele Bézier reprezintă o unealtă importantă în ceea ce privește modelarea geomtrică, fiind folosite în diverse domenii: de la programarea care se bazează pe editarea de imagini (cum ar fi Adobe Illustrator) pană la animații, unde curbele sunt folosite pentru trasarea mișcării (Adobe Flash). Acestea sunt folosite în grafica pe calculator pentru a modela curbe netede. Deoarece curba este inclusă în interiorul poligonului convex definit de punctele de control, punctele pot fi afișate grafic și utilizate pentru manevrarea intuitivă a curbei. Cele mai multe dintre programele care se ocupă de grafică includ o unealtă pentru desenarea cubelor Bézier.

Combinații de curbe Bézier interconectate sunt folosite în diverse programe de grafică vectorială sau editare imagini, ca de exemplu Adobe Illustrator, Adobe Photoshop sau Inkscape.

În cazul animațiilor, curbele Bézier pot fi folosite pentru a trasa mișcarea. Utilizatorul aplicației poate contura calea dorită folosind curbe Bézier iar aplicația generează cadrele necesare pentru ca obiectul să se miște de-a lungul căii. Acest tip de curbe este folosit, de asemenea, în numeroase aplicații de animație, cum ar fi Adobe Flash și Synfig.

Curbele Bézier au, de asemenea, întrebuințări în generarea unor fonturi, cum ar fi TrueType. Acest font folosește curbe Bézier pătratice. Diverse sisteme de imagistică, cum ar fi PostScript sau Asymptote folosesc curbele Spline-Bézier pentru generarea formelor curbate.

Curbele Bézier au o mare importanță în aproximarea formelor deoarece este nevoie doar de câteva puncte pentru a defini un număr ridicat de forme.

I.2 Construcția și clasificarea curbelor Bézier

Curbele Bézier pot fi reprezentate in doua moduri: iterativ, folosind scrierea lor în baza Bernstein și recursiv, folosind algoritmul lui De Casteljau. Ambele cazuri menționate vor fi tratate în detaliu in acest capitol.

Orice curbă Bézier este definită de o mulțime de control P0, P 1,P 2, …P n, unde n este un număr natural dat.

Curbele Bézier se împart, în funcție de numărul punctelor lor de control, în mai multe categorii:

Curbe Bézier liniare

Curbele Bézier liniare au poligonul de control compus doar din două puncte (P0 și P1). Curba care corespunde acestor două puncte este, de fapt, chiar segmental de dreaptă care unește cele două puncte. Expresia curbei definită de un asemenea poligon de control este urmatoarea:

B(t) = P0 + t (P1 – P0) = (1-t) P0 + t P1 , t [0,1].

Parametrul t din expresia de mai sus reprezintă distanța la care este amplasat punctul B(t) fața de punctele de control P0 și P1. De exemplu, daca t = 0.3, atunci putem spune ca B(t) se află la o treime față de P0, respectiv două treimi față de P1. În timp ce parametrul t variază între 0 și 1, B(t) descrie linia ce unește punctele P0 și P1.

Imagine I.1

Curbe Bézier pătratice

Curbele Bézier pătratice (cunoscute și sub numele de curbe Bézier cuadrice) au poligonul de control compus din trei puncte (P0, P1 și P2). O asemenea curbă reprezintă un segment de parabolă. Expresia curbei definită de un asemenea poligon de control este urmatoarea:

B(t) = (1-t)2 P0 + 2(1-t)tP1 + t2P2, t[0,1].

Pentru a explica cine este de fapt punctul B(t), trebuie sa definim două puncte auxiliare, Q0 și Q1. Punctul Qi variază între Pi și Pi+1 și descrie o curbă Bzier liniară, i = . Acum putem spune ca punctul B(t) variază între punctele Q0 și Q1, descriind o curbă Bézier cuadrică.

Observație: Daca punctele care compun poligonul de control, P0, P1 și P2 sunt coliniare (punctul P1 este situat între punctele P0 și P2 ), atunci curba Bézier asociată are gradul 1, imaginea sa fiind segmental [P0, P2].

Imagine I.2

Curbe Bézier cubice

Curbele Bézier cubice au poligonul de control compus din patru puncte (P0, P1, P2 și P3). Expresia curbei definită de un asemenea poligon de control este urmatoarea:

B(t) = (1-t)3 P0 + 3(1-t)2t P1 + 3(1-t)t2 P2 + t3 P3, t[0,1].

De această dată, pentru a explica cine este punctual B(t) avem nevoie de cinci puncte auxiliare, Q0, Q1, Q2, R1, R2, unde punctul Qi variază între Pi și Pi+1 și descrie o curbă Bzier liniară, i = iar punctul Ri variaza intre Qi și Qi+1 și descrie o curbă Bézier cuadrică. Punctul B(t) variază între R0 și R1, descriind o curba Bézier cubică.

Imagine I.3

Curbe Bézier de ordin superior

Curbele Bézier de ordin superior au poligonul de control compus din cel putin cinci puncte. Expresia curbei definită de un asemenea poligon de control este, pentru cazul general urmatoarea:

B(t) = =(1-t)n P0 +t P1 + … + tn Pn, t[0,1].

Imagine I.4

Proprietăți ale curbelor Bézier

Fie (b0, b1, …, bn) un poligon de control din Rm. Curba Bézier asociată b : [0,1] → Rm are câteva proprietăți importante, din care enumerăm:

Gradul curbei b este mai mic cu o unitate decât n (numarul punctelor sale de control);

Curba de mai sus interpolează extremitățile poligonului său de control pentru ca b(0) = b0 și b(1) = b1. De aici rezulta ca daca b0 = bn (poligonul de control al curbei este închis), atunci și curba Bézier asociată este închisă;

Imagine I.5

Curba b este inclusă în înfășuratoarea convexă a punctelor sale de control (adică toate punctele sale sunt incluse în înfășuratoarea convexă a punctelor sale de control);

Această proprietate poate fi observată în imaginea de mai jos, unde am desenat cu culoarea crem înfășurătoarea convexă a punctelor de control care determină curba.

Imagine I.6

Curba b este invariantă la ordinea punctelor sale de control. Astfel spus, doua poligoame de control P: (b0, b1, …, bn) și P’: (bn, bn-1, …, b1) definesc aceeași curbă.

I.3 Curbe Bézier în baza Bernstein

Bazele matematice ale curbelor Bézier constau în polinoamele Bernstein. Așa cum am menționat și mai sus, Bézier a exprimat funcțiile polinomiale sub formă de combinații liniare ale polinoaelor Bernstein încercl pentru ca b(0) = b0 și b(1) = b1. De aici rezulta ca daca b0 = bn (poligonul de control al curbei este închis), atunci și curba Bézier asociată este închisă;

Imagine I.5

Curba b este inclusă în înfășuratoarea convexă a punctelor sale de control (adică toate punctele sale sunt incluse în înfășuratoarea convexă a punctelor sale de control);

Această proprietate poate fi observată în imaginea de mai jos, unde am desenat cu culoarea crem înfășurătoarea convexă a punctelor de control care determină curba.

Imagine I.6

Curba b este invariantă la ordinea punctelor sale de control. Astfel spus, doua poligoame de control P: (b0, b1, …, bn) și P’: (bn, bn-1, …, b1) definesc aceeași curbă.

I.3 Curbe Bézier în baza Bernstein

Bazele matematice ale curbelor Bézier constau în polinoamele Bernstein. Așa cum am menționat și mai sus, Bézier a exprimat funcțiile polinomiale sub formă de combinații liniare ale polinoaelor Bernstein încercand să obțina forme cât mai variate pentru capotele de automobile. Scrierea în formă Bernstein a curbelor Bézier reprezintă, de fapt, scrierea acestora sub formă algebrică.

Polinoamele Bernstein sunt definite astfel :

(t) = ,

De exemplu, pentru n = 1 definim urmatoarele polinoamele Bernstein:

De grad 1:

= 1 – t

= t

De grad 2:

= (1-t)2

= 2 t(1-t)

= t2

De grad 3:

= (1-t)3

= 3 t(1-t)2

= 3 t2(1-t)

= t3

În continuare, vom utiliza, prin abuz de limbaj, termenul de polinoame Bernstein și pentru restricțiile funcțiilor polinomiale asociate polinoamelor Bernstein. Polinoamele Bernstein pe un interval arbitrar [a,b] se definesc în următorul mod:

Polinoamele Bernstein au următoarele proprietăți importante:

Polinoamele Bernstein sunt pozitive pe intervalul [0,1];

Pentru orice număr natural n, polinoamele Bernstein de acel grad formează o partiție a unității (valoarea fiecărui polinom Berstein este pozitivă iar suma tuturor acestor polinoame este 1):

;

Polinoamele Bernstein și sunt definite astfel:

și

;

Funcția are pe intervalul [0,1] un punct de maxim pentru t= ;

Polinoamele Bernstein verifică următoarea relație recursivă:

Demonstrație:

=

=

Fie curba Bézier b : [0,1] → Rm definită de poligonul de control (b0, b1, …, bn). Aceasta curba se poate exprima astfel:

Exemplu: Considerăm următorul poligon de control:

b0 = (1,0), b1 = (1,1), b2 = (0,1).

Curba Bézier asociata b : [0,1] → R2 se scrie sub formă Bernstein în modul următor:

=

=

= .

Avem, de exemplu:

și

.

În continuare, dorim să stabilim dacă punctul aparține imaginii lui b. Altfel spus, dorim să găsim un punct pentru care . Acest lucru este echivalent cu:

Rezolvând sistemul de mai sus, obținem soluția t0 = . De aici deducem că punctul , mai exact,

Polinoamele Bernstein de grad n, , formează o bază pentru spațiul vectorial al polinoamelor cu gradul cel mult egal cu n. Putem spune, deci, că orice curbă polinomială de grad n poate fi scrisă ca o curbă Bézier.

Fie curba Bézier definită de poligonul de control (b0, b1, …, bn), Deoarece în modelarea geometrică, acuratețea calcului are o mare importanță, pentru evaluarea parametrizării Bernstein a curbei definită mai sus, eșalonăm astfel operațiile:

Eșalonarea definită mai sus se numește metoda Horner – Bézier.

I.4 Algoritmul de Casteljau

Deși lucrările lui Casteljau, inginer la firma Citroën, au fost elaborate în anul 1959, cu ceva timp înaintea lucrărilor lui Bézier, acestea nu au fost publicate niciodată. Rapoartele lui Casteljau au fost păstrate doar sub forma unor rapoarte la firma de automobile la care acesta lucra. Rapoartele menționate anterior au devenit cunoscute la mult timp dupa conceperea schemei, când metoda de definire a curbelor folosind polinoamele Bernstein devenise deja cunoscută. Acesta este motivul pentru care curbele poarta doar numele lui Bézier. Paul de Casteljau a dat o definiție procedurală curbelor Bézier.

În cele ce urmează, vom defini algoritmul lui de Casteljau atât pentru cazul particular n=2 cât și pentru cazul general.

Algoritmul lui de Casteljau pentru cazul n=2

Fie trei puncte coliniare b0, b1 și b2. Pentru tR construim urmatoarele trei puncte:

.

Astfel, când t variază în mulțimea numerelor reale, punctul descrie parabola care trece prin punctele b0 și b2 și ale cărei tangente în punctele respective sunt dreptele b0b1 și b1b2. Dacă atunci obținem arcul parabolei, arc care unește punctele b0 și b2.

Exemplu: Fie punctele b0 = (2,4), b1 = (4,2) și b2 = (4,0). Vom calcula punctele și corespunzătoare valorilor t= și t=.

Pentru t= avem urmatoarele valori:

Pentru t= avem urmatoarele valori:

Punctele și pot fi scrise intr-un tabel triunghiular. Acest tabel poartă numele de schemă de Casteljau. Astfel, tabelul corespunzător este:

b0

b1

b2 .

Schemele de Casteljau corespunzătoare celor doua exemple de mai sus sunt:

(2,4) (2,4)

(4,2) (3,3) respectiv (4,2)

(4,0) (4,1) (4,0) .

Algoritmul lui de Casteljau pentru cazul general

Fie punctele b0, b1, …, bn Rm. Notăm , unde i = și t . Definim următoarele puncte:

unde r = și i = .

Cand t variază, punctul descrie o curbă notată cu bn. Punctele b0, b1 , …, bn sunt punctele de control ale curbei, iar poligonul determinat de cele n+1 puncte este poligonul de control al curbei.

Matricea triunghiular inferioară corespunzătoare schemei lui de Casteljau este, pentru cazul general, următoarea:

b0

b1

b2

………………………………………………..

bn ……… .

Schema de mai sus poate fi exprimată și în mod recursiv, astfel:

unde r = și j = .

I.5 Legatura dintre forma Bernstein și algoritmul de Casteljau

Fie următorul poligon de control din Rm: (b0, b1, … , bn). Următoarele afirmații sunt adevărate:

Curba Bézier bn construită utilizând algoritmul de Casteljau coincide cu o curba Bézier b definită utilizând polinoamele Bernstein. Altfel spus, curba bn poate fi scrisă sub forma

Punctele intermediare din algoritmul de Casteljau descriu, de asemenea niște curbe Bézier. Dacă avem un punct r și i = , punctul descrie, atunci când t variază o curba Bézier – cea asociată poligonului de control (bi, bi+1, … , bi+r).

Punctele curbei Bézier pot fi scrise și folosind punctele intermediare din algoritmul de Casteljau:

.

I.6 Derivatele unei curbe Bézier

Operatorul de diferențiere în avans ∆ este definit de următoarea formulă: ∆bi ≔bi+1 – bi, Ɐ i = .

Prin convenție, ∆0bi ≔ bi, Ɐ i = . Pentru r ≥ 2 se definește ∆rbi ≔∆r-1 (∆bi), Ɐ i = .

Fie (b0, b1, … , bn) poligonul de control asociat unei curbe b:[0,1]→ Rm. Derivatele funcției b sunt date de formulele:

Daca t=0 sau t=1, atunci derivatele depind doar de poligonul de control, oricare ar fi ordinul derivatei. Mai mult, b’(0) = n(b1 – b0) și b’(1) = n(bn – bn-1). Putem reformula relațiile precedente astfel: vectorii tangenți la curba Bézier în punctele b0 (respectiv bn) sunt coliniari și au același sens cu vectorii (respectiv ). Dacă vectorii sunt nenuli, ei reprezintă direcția tangentelor la curbă în punctele respective.

Pentru t [0,1] are loc următoarea egalitate: . Altfel spus, punctele construite de algoritmul de Casteljau în etapa (n-1) determină vectorul tangent la curba Bézier în punctul b(t).

Exemplu: Fie punctele b0 = (1, -2), b1 = (3,2), b2 = (3, -2) și b3 = (-3, -2). Schema de Casteljau corespunzătoare punctelor date și valorii t0=1/2 este:

(1, -2)

(3,2) (2, 0)

(3, -2) (3, 0) (5/2, 0)

(-3, -2) (0, -2) (3/2, -1) (2, -1/2).

Vectorul tangent la această curbă este:

b’ (1/2) = 3 ( (3/2, -1) – (5/2, 0) ) = 3 (-2/2, -1) = (-3, -3).

1.7 Modificarea unei curbe Bézier

Modificarea unei curbe Bézier poate fi realizată într-unul din următoarele moduri: deplasarea unui punct de control, inserarea repetată a unui punct de control, mărirea gradului poligonului de control sau prin subdivizare. În cele ce urmează vom trata toate cele patru cazuri.

Deplasarea unui punct de control

Fie (b0, b1, … bj-1,bj, bj+1, … bn) poligonul de control asociat unei curbe Bézier b și fie (b0, b1, … bj-1, j, bj+1, … bn) poligonul de control asociat unei curbe Bézier . Folosind exprimarea în forma Bernstein obținem

Vectorii și sunt coliniari. Această coliniaritate ne arată faptul că dacă deplasăm punctul b(t) într-o anumită direcție, fiecare punct al curbei se deplasează de-a lungul aceleiași direcții. Cu toate acestea, lungimea segmentului parcurs diferă în funcție de parametrul t. Pentru extremitățile b0=b(0) și bn=b(1) rămân aceleași.

Inserarea repetată a unui punct de control

Fie (b0, b1, … , bj-1, bj, bj+1, …, bn) poligonul de control asociat unei curbe Bézier b. Utilizând scrierea sub formă Bernstein a curbei, obținem că ponderea punctului bj este

.

Dacă inserăm de k ori punctul bj, obținem poligonul de control de n+k puncte (b0, b1, …, bj-1, bj, … ,bj, bj+1, … bn), unde numărul de apariții al lui bj este k.

Considerând curba Bézier asociată obținem că ponderea punctului bj în curba este mai mare decât ponderea lui bj în curba b. Altfel spus, curba Bézier este mai „apropiată” de punctul bj decât curba b.

Observație: cu toate că din punct de vedere al imaginii geometrice poligoanele coincid, dacă le privim ca pe două poligoane de control (mulțimi ordonate de puncte) ele sunt distincte. Din această observație putem deduce că cele doua curbe Bézier asociate sunt diferite.

Mărirea gradului unei curbe Bézier

Fie b0,b1 și b2 trei puncte coliniare distincte, cu punctul b1 situat între punctele b0 și b2. Curba Bézier asociată poligonului de control (b0, b2) este dată de relația: Curba este una polinomială și care are ca imagine geometrică segmentul [b0b2]. Curba Bézier asociată poligonului de control (b0, b1, b2), fiind o curbă polinomială de grad cel mult 2, admite următoarea parametrizare: Imaginea acestei curbe este, de asemenea, tot segmentul [b0b2]. Astfel, pentru două poligoane de control diferite și două curbe Bézier cu parametrizări diferite putem obține aceeași imagine geometrică.

Tratăm cazul particular în care b1 este chiar mijlocul segmentului [b0b2]:

Obținem ,deci, că pentru acest caz atât imaginile geometrice ale celor două curbe cât și parametrizările b și coincid.

În cazul în care ne întrebăm când unui poligon de control îi putem asocia un nou poligon de control cu un punct în plus astfel încât cele două curbe Bézier asociate să coincidă, raspunsul este următorul:

Fie poligonul de control asociat curbei Bézier b. Definim poligonul de control ) astfel: și Notăm cu curba Bézier asociată. Oricare ar fi un parametru t între 0 și 1, Imaginile celor două curbe coincid. Singurul poligon de control care generează curba b, care are n+2 puncte și are ca extremități punctele b0 și bn este chiar poligonul P(1).

Exemplu: Fie punctele b0 = (-6, 6), b1 = (0,6) și b2 = (3,0). Atunci avem că:

Calculăm curbele Bézier pe care le generează poligoanele de control , respectiv

=

Am obținut, deci, că cele două polinoame de control generează aceeași curbă Bézier.

Observație: Extremitățile celor două poligoane de control, P și P(1) coincid. Punctele intermediare ale poligonului P(1) sunt situate pe segmentele determinate de punctele de control ale poligonului P.

Dacă aplicăm același procedeu de mai multe ori, obținem un șir de poligoane P, P(1), P(2), …, unde P(k+1) = (P(k))(1). Șirul obținut converge la curba Bézier definită de toate aceste poligoane, dar convergența este lentă și nu are consecințe practice.

Procedeul descris mai sus este util atunci când avem o familie de curbe Bézier date prin poligoanele de control și dorim ca acestea să fie generate de poligoane cu același număr de puncte. Atunci: determinăm poligonul cu cele mai multe puncte (fie n – numărul acestora) și mărim numărul de puncte al fiecărui poligon de control, până când toate ajung egale cu n. Acest procedeu se folosește în practică la generarea suprafețelor, unde există algoritmi care necesită ca toate datele de intrare să reprezinte curbe de același grad. Procedeul de mărire a gradului poate fi folosit și în transferul de date între diferite sisteme care lucreaza doar cu curbe care au gradul fixat.

Subdivizare

Fie curba Bézier b : [0,1] → R2. Oricare ar fi un parametru restricțiile curbei b la intervalele și sunt curbe polinomiale, în particular, chiar curbe Bézier. În acest caz, ne punem problema determinării unui poligon care determină aceste restricții.

Să luăm următorul exemplu: Fie b segmentul determinat de b0 și b1. Atunci, pentru orice reprezintă curba Bézier pe care o determină poligonul de control . Procesul prin care unei curbe Bézier îi asociem două arce ale sale care au reuniunea egală chiar cu curba inițială reprezintă chiar procesul de subdivizare.

Fie curbele Bézier b și asociate poligoanelor de control și, respectiv, . Dacă următoarele relațiile , atunci între punctele din schemele lui de Casteljau asociate curbelor au loc următoarele relații: și

În cazul general putem spune că dacă avem o curbă Bézier b determinată de poligonul de control , pentru orice parametru restricția lui b la intervalul este curba Bézier pe care o determină poligonul de control iar restricția lui b la intervalul este curba Bézier pe care o determină poligonul de control , unde punctele sunt punctele de Casteljau corespunzătoare pentru valoarea a parametrului. Avem deci, valorile particulare

Exemplu: Fie punctele b0 = (-4 , 0), b1 = (0,0), b2 = (0,8) și fie curba Bézier asociată lui, b : [0,1] → R2. Scriem punctele calculate cu ajutorul algoritmului lui de Casteljau pentru parametrul

(0,8)

Deducem că restricția lui b la intervalul este curba Bézier determinată de poligonul de control ((-1,2), (0,4), (0,8)).

Procesul descris mai sus, de divizare a unei curbe Bézier pentru un parametru în intervalul [0,1] (să zicem se poate repeta, obținând arcede curbă din ce în ce mai mici. Procedeul este util în cazul în care vrem să stabilim dacă o dreaptă intersectează o curbă Bézier. Mai exact, se studiază daca dreapta respectivă intersectează sau nu paralelipipedul minim determinat de poligonul de control care generează curba Bézier (minmax box-ul). În cazul în care dreapta nu intersectează minmax box-ul, ea nu intersectează nici curba. În cazul în care dreapta intersectează paralelipipedul, prin subdivizări repetate putem aproxima punctele de intersecție ale dreptei date cu curba Bézier inițială.

Capitolul II: TRATAREA INFORMATICĂ A CURBELOR BZIER

II.1 Scurta prezentare a curbelor Bézier

Grafica asistată de calculator iși propune să construiască imagini cât mai apropiate de realitate. În scopul desenării unui obiect real, trebuie mai întâi să îi calculăm suprafața și apoi să o stocam în memoria calculatorului ca pe un obiect matematic.

Paul de Casteljau, inginer la , a definit în anul 1959 prima metodă recursivă de a construi curbe cât mai apropiate de realitate. Punctul de plecare în construirea curbelor era un număr finit de puncte, numite puncte de control.

În anul 1962, acelorași curbe le-au fost asociate de către Pierre Bézier ecuații parametrice.

Curbele Bézier au utilizări importante în grafica pe calculator și în tehnologia informației. Dintre aceste utilizări, poate cele mai importante sunt suprafețele Bézier și fonturile TrueType.

Fie n+1 puncte distincte, P0, P1, … , Pn. Punctele poartă numele de puncte de control. Poligonul care se formează unind punctele de control de mai sus, în ordinea dată, se numește poligon de control (sau poligon Bézier). Acest poligon de control nu este unic.

Așa cum am spus și în capitolul anterior, putem defini curbele Bézier în două moduri: folosind polinoame Bernstein sau folosind algoritmul lui de Casteljau.

Astfel, curba Bézier de grad n corespunzătoare punctelor de control P0, P1, … , Pn este dată de următoarea formulă:

În formula de mai sus, Pk este punctul de control cu indicele k din mulțimea de puncte de mai sus iar bk,n(t) sunt polinoamele Bernstein de grad n. Polinoamele Bernstein de grad n sunt date de formula:

În scopul prezentării pe scurt a algoritmului lui de Casteljau, definim fiecare element din schema algoritmului (fiecare element al matricei inferior triunghiulară) ca fiind obținut din formula:

unde r = și j = .

Această formulă se poate numi exprimarea recursivă a schemei lui de Casteljau.

II.2 Interpretarea grafică a curbelor Bézier

Fie punctele de control P0, P1, …, Pn, parametrul și fie punctul B(t). Poziția grafică a punctului B(t) se obține urmând pașii de mai jos:

se considera punctele care împart fiecare segment Pi-1Pi în raportul t:(1-t)

se consideră drept puncte de control noile puncte de mai sus. Repetăm pasul anterior până când rămâne un singur punct. Punctul rămas este chiar punctul pe care îl căutăm, B(t0).

Exemplu: Fie un poligon de control format din patru puncte: P0(0,0), P1(0,2), P2(2,2), P3(4,0). Vrem să scriem ecuația parametrică a curbei Bézier pe care o definesc cele patru puncte de control și să determinăm poziția punctului corespunzător valorii t = a parametrului.

În acest scop, folosim scrierea curbei Bézier utilizând polinoamele Bernstein. În primul rând, calculăm polinoamele Bernstein necesare folosindu-ne de formula scrisă mai sus:

Scriem formula necesară pentru calcularea curbei Bézier:

Altfel spus, am obținut următoarea curbă parametrică:

Pentru a calcula poziția punctului corespunzător valorii t = a parametrului, putem înlocui direct în ecuațiile de mai sus, obținând:

Pentru a obține grafic rezultatul de mai sus luăm punctele poligonului de control, două câte două și le împărțim la raportul Obținem punctele Q0(0,1) , Q1(1,2) și Q3(3,1). Luăm în considerare aceste puncte și repetăm pasul precedent. Obținem, deci, un nou set de puncte: R0(0.5 , 1.5) și R1 (2, 1.5). Dacă mai aplicăm o dată pasul anterior, obținem punctul S0(1.25, 1.5) . Coordonatele punctului S0 se pot rescrie ca respectiv (exact valorile lui x si y aplicate în punctul .

Adăugăm și reprezentarea grafiă a modalității de obținere a punctului dorit:

Imagine II.1

II.3 Curbele Bézier și fonturile TrueType

Curbele Bézier reprezintă instrumente importante în domeniul tehnologiei informației, ele fiind folosite în construcția fonturilor TrueType.

Fonturile TrueType folosesc curbe Bézier pătratice (au poligonul de control compus din trei puncte). Astfel, fiecare curbă este echivalentul unei serii de curbe Bézier pătratice. Fiecare dintre aceste curbe este determinată de trei puncte de control și are o ecuație parametrică.

Fie trei puncte de control ale fiecărei curbe Bézier (P0x, P0x), (P1x, P1y), (P2x, P2y) și un parametru t în intervalul [0,1]. Atunci avem că reprezintă ecuația parametrică a curbei. Când parametrul t variază între 0 și 1, sunt generate toate punctele de pe curba definită de poligonul de control P0, P1, P2.

În imaginea de mai jos este prezentată realizarea caracterului „e” utilizând fontul TrueType. Pot fi văzute atât punctele care formează poligoanele de control cât și curbele pe care acestea le generează.

Imagine II.2

Din punct de vedere vizual, putem descrie curba generată ca plecând din punctul P0, parcurgând o porțiune din traiectorie ca pe o linie dreaptă între punctele P0 și P1 și ajungând în punctul P2 după ce parcurge o porțiune din traiectorie ca pe o linie dreaptă între punctele P1 și P2. Putem spune, deci, că tangentele sunt ușor de definit în fonturile TrueType.

II.4 Descrierea suprafețelor la modul general

Din punct de vedere intuitiv, putem defini noțiunea de suprafață ca pe un set de puncte care alcătuiesc o curbă sau o linie în mișcare.

Din punct de vedere matematic, o suprafață poate fi definită ca o mulțime de puncte care în fiecar epunct are o structura asemănătoare cu un plan.

Suprafețele sunt bidimensionale și pot fi plane sau curbe. Ele mărginesc corpuri tridimensionale.

Putem defini suprafața unui corp ca pe frontiera acelui corp. Putem, deci, să spunem ca suprafața unui cub este formată din șase pătrate (care reprezintă cele șase fețe ale cubului).

II.5 Suprafețe Bézier

La fel ca și curbele lui Pierre Bézier și suprafețele îi poartă numele matematicianului și inginerului francez. Acestea din urmă au fost descrise pentru prima oară de către inginerul francez Bézier în 1972.

Suprafețele Bézier sunt definite de o rețea de puncte de control, spre deosebire de curbele Bézier, care sunt definite de un poligon de control. Ele au întrebuințări în grafica pe calculator și proiectarea asistată de calculator.

O suprafață Bézier de grad (m,n) este definită de o mulțime de (m+1,n+1) puncte de control bi,j. Matricea de puncte bi,j se numește rețeaua punctelor de control ale suprafeței Bézier.

Unei suprafețe Bézier îi este asociată o suprafață poligonală pe porțiuni, unde o porțiune reprezintă un patrulater de vârfuri bi,j , bi,j+1, bi+1,j , bi+1,j+1 iar suprafața totală reprezintă reuniunea acestor patrulatere (i).

O suprafață Bézier de ordin (n,m) corespunzătoare rețelei de puncte de control este dată de următoarea relație:

În relația de mai sus sunt polinoamele Bernstein de grad n, respectiv m date de relațiile:

Suprafețele Bézier pot avea orice grad, însa cele mai folosite în modelarea geometrică sunt suprafețele Bézier de grad (m=3, n=3), numite suprafețe bicubice. Geometria unui singur ,,petic” bicubic este definită de o mulțime de 16 puncte de control. Mai jos am adăugat un exemplu de suprafață Bézier descrisă anterior.

Imagine II.3

Un triunghi Bézier este un tip special de suprafețe Bézier. Acestea sunt create prin interpolarea liniară a punctelor de control. Muchiile triunghiului sunt chiar curbe Bézier determinate de punctele de control menționate anterior. Am adăugat mai jos o imagine care reprezintă un triunghi Bézier.

Imagine II.4

Reprezentările suprafețelor netede cu ajutorul ,,plaselor’’ Bézier sunt superioare reprezentărilor realizate folosind triangulari întrucât primele sunt mai ușor de manipulat.

Un ,,petic” Bézier de grad (m,n) poate fi redat fie din două triungiuri Bézier de grad m+n, fie ca un singur triunghi Bézier de grad m+n cu domeniul de definiție reprezentat ca un pătrat în locul unui triunghi. Un triunghi Bézier de grad m poate fi, de asemenea, contruit dintr-o suprafață Bézier de grad (m,n) care are punctele de control așa încât o muchie se suprapune cu un punct sau cu domeniul de definiție reprezentat ca un triunghi în locul unui pătrat.

Observație: O suprafață Bézier este în întregime inclusă în acoperirea convexă a punctelor sale de control. Curbele pe o suprafață în care u și v sunt constante reprezintă curbe Bézier .

Capitolul 3: PREZENȚA CURBELOR BZIER ÎN ALTE DOMENII

Curbele Bézier reprezină instrumente puternice în modelarea geometrică. Pe lângă această întrebuințare, pe care cea mai multă lume o cunoaște, se pare că ele există și în alte domenii.

III.1 Prezența curbelor Bézier în infrastructură

Podul Strings din Ierusalim (The Jerusalem Chords Bridge), deschis în anul 2011 pentru a ajuta la decongestionarea traficului, reprezintă o atracție turistică prin aspectul său. Podul este suspendat, astfel întreaga sa greutate este susținută de partea superioară. Întreaga punte a podului este susținută de o mulțime de cabluri de oțel, toate acestea fiind conectate la un singur turn. Întrucât fiecare dintre cablurile de oțel are forma unei parabole, se pare că baza matematică a construirii întregului pod constă in curbele Bézier pătratice.

Imagine III.1

III.2 Prezența curbelor Bézier în pictură

Printre multele lucrări ale lui Picasso, există o colecție de picturi reprezentând animale. Acestea au fost realizate folosind doar linii. Cu toate că picturile par foarte simple, se pare că ele influențează observatorul într-un deosebit de profund. Picasso a realizat o serie de unsprezece desene în care arată versiuni ale unui taur. Primele desene din serie sunt mai mult sau mai puțin realiste dar, pe parcursul seriei este surprins taurul până la esența sa, ultima pictură necesitând doar zece linii.

Imagine III.2

Se pot recunoaște, astfel, aspecte matematice în picturile sale. Cel mai evident mod în care esența matematică este surprinsă în lucrările sale este reprezentat de prezența curbelor Bézier. Astfel, în cadrul unuia dintre desenele din seria cu animale despre care vorbeam mai sus, câinele este desenat folosind o secvență de nouă curbe Bézier.

Imagine III.3

Capitolul IV: PREZENTAREA TEHNOLOGIILOR UTILIZATE ÎN DEZVOLTAREA APLICAȚIEI

IV.1 Limbajul de programare Java

Aplicația ce va fi prezentată în capitolul următor este dezvoltată integral în limbajul de programare Java utilizând mediul de dezvoltare integrat Eclipse.

Java este un limbaj de programare orientat – obiect, de nivel înalt, conceput la începutul anilor 1990 de către James Gosling la Sun Microsystems. Limbajul de programare Java a fost lansat în anul 1995. Cea mai mare parte din aplicațiile distribuite sunt scrise în acest limbaj de programare, acestea putând fi utilizate pe diverse dispozitive, cum ar fi calculatorul personal, telefonul mobil sau agenda electronică.

Limbajul de programare Java are următoarele caracteristici principale:

simplitate – în vederea eliminării posibilității de a scrie un cod confuz au fost eliminate supraîncărcarea operatorilor și moștenirea multiplă;

robustețe – în vederea eliminării surselor frecvente ale erorilor au fost eliminați pointerii și a fost adăugată o procedură de colectare a reziduurilor. Acest colector de reziduuri marchează obiectele care nu mai sunt folosite și eliberează spațiul pe care acestea le ocupă.

complet orientat pe obiecte – nu mai există stilul de programare procedural. Unitatea fundamentală de programare este clasa. Fiecare clasă conține câmpuri, metode și constructori. Câmpurile unei clase reprezintă variabilele declarate în acea clasă, metodele unei clase reprezintă funcțiile declarate în interiorul clasei iar constructorii clasei seamănă cu metodele dar poartă obligatoriu același nume cu clasa și nu pot întoarce valori.

portabilitate – nu depinde de platforma de lucru, aceeași aplicație rulează fără a face nicio modificare pe diverse sisteme de operare ( de exemplu, Windows și Unix). Pentru a rula fără modificări un program scris în limbajul Java pe o platformă, aceasta trebuie să aibă instalată o mașină virtuală Java. Acest lucru este posibil datorită faptului că sursele sunt compilate într-un cod de octeți. În timp ce codul mașină (o succesiune de 0 și 1) depinde de tipul calculatorului, acest cod de octeți ( o serie de instrucțiuni asemănătoare unui cod scris într-un limbaj de asamblare) este intermediar între codul mașină și codul sursă și nu depinde de tipul calculatorului.

Limbajul Java este cel mai sigur limbaj de programare disponibil. Prin utilizarea diverselor metode este asigurată securitatea programelor. Dintre metodele utilizate în scopul menținerii securității programelor, amintim verificarea dinamică a codului și impunerea unor reguli stricte pentru rularea unor programe lansate pe calculatoare care se află la distanță. Lipsa pointerilor face accesarea anumitor zone de memorie imposibilă în cazul în care accesul nu este autorizat. Utilizatorul este obligat să prevadă diversele erori (excepții posibile).

Limbajul Java este modelat după limbajele de programare C și C++, tranziția între acestea făcându-se relativ ușor. Cu toate că acest limbaj de programare împrumută o parte din sintaxă de la limbajele de programare C și C++, el are un model al obiectelor mai simplu.

IV.2 Mediul de dezvoltare Eclipse

Un mediu de dezvoltare integrat ( IDE – Integrated developement enviroment) reprezintă un produs software care înglobează diverse facilități și permite dezvoltarea unor aplicații folosind anumite limbaje de programare.

Un mediu de dezvoltare integrat constă de obicei dintr-un editor de cod sursă, o parte care se ocupă de construitul aplicației (build tool) și o parte care se ocupă de testarea aplicației (debugger). Unele medii de dezvoltare, cum ar fi NetBeans și Eclipse, conțin un compilator, un interpretor sau chiar pe ambele.

Un compilator reprezintă un program care trascrie codul sursă al unui program scris într-un limbaj de programare într-un alt cod, numit cod mașină.

Un interpretor este un program care implementează o mașină virtuală pe baza unui set de instrucțiuni ale unui limbaj de programare. Practic, un interpretor citește instrucțiunile unui program, le analizează și apoi le execută utilizând mașina virtuală.

Imagine IV.1

Cele mai folosite medii de dezvoltare pentru Java sunt următoarele: NetBeans, Eclipse, JCreator și CodeGuide.

Un program de tip sursă deschisă (open source) reprezintă un program care este dezvoltat de către o comunitate și care este oferit spre folosire utilizatorilor sub o licență liberă și care garantează accesul tuturor acestor utilizatori la codul sursă al aplicației. Un program de acest tip are ca principală caracteristică libertatea acordată utilizatorilor săi. Astfel, utilizatorii îl pot utiliza în orice scop, îl pot copia sau redistribui, îl pot modifica în scop personal sau îl pot îmbunătăți și repartaja cu alți utilizatori.

Un bun exemplu de program de tip sursă deschisă îl reprezintă mediul de dezvoltare Eclipse. Acesta este scris în mare parte în limbajul de programare Java și conține un spațiu de lucru de bază și un plug-in care ajută la personalizarea mediului de lucru. Un plug-in reprezintă un program care poate fi integrat într-un alt program cu scopul de a îndeplini anumite funcții.

Eclipse pune la dispoziție, prin intermediul unor programe de tip plug-in, posibilitatea de a dezvolta aplicații și în alte limbaje de programare cum ar fi Ada, C, C++, PhP sau Python.

Imagine IV.2

Imaginea de mai sus reprezintă o captură de ecran din cadrul mediului de dezvoltare Eclipse în timpul elaborării aplicației ce urmeză a fi descrisă în următorul capitol.

Versiunea inițială a fost dezvoltată de cei de la IBM VisualAge. Pachetul de dezvoltare Eclipse (SDK – Software Developement Kit ) le este destinat programatorilor care utilizează limbajul de programare Java. Utilizatorii pot extinde funcționalitățile sale prin instalarea diverselor plug-in-uri existente pentru platforma Eclipse cum ar fi pachetele pentru utilizarea altor limbaje de programare. De asemenea, programatorii pot contribui la dezvoltarea aplicației cu propriile lor programe de tip plug-in.

IV.3 Tehnologia AWT

Termenul de interfață cu utilizatorul (UI – User Interface) reprezintă un mod de comunicare între un program și utlizatorii săi. O interfață grafică (GUI – Graphical User Interface) reprezintă o particularitate a interfeței cu utilizatorul, deci un mod de comunicare vizuală între un program și utilizatorii săi.

Limbajul de programare Java le pune utilizatorilor săi la dispoziție o serie de clase atât în vederea implementării funcționalităților interfeței cu utilizatorul cât și în vederea implementării funcționalităților interfețelor grafice.

Facilități de lucru în vederea folosirii interfețelor grafice ne sunt oferite de către biblioteca de clase java.awt (AWT = Abstract Window Toolkit).

La crearea unei aplicații care utilizează trebuie să fie parcurși următorii pași:

Crearea unei suprafețe grafice pentru afișare (o fereastră, de exemplu) pe care urmează să fie plasate obiectele grafice pe care le vom folosi (de exemplu butoanele sau casetele text). Această suprafață grafică trebuie să aibă o configurație inițială care să conțină cel puțin dimensiunile acesteia.

Crearea și așezarea diverselor obiecte grafice pe suprafața de afișare descrisă la pasul precedent și poziționarea acestora printr-o metodă.

Crearea unui mecanism prin care programul să reacționeze în momentul în care utilizatorul interacționează cu obiectele grafice ale aplicației.

Urmărirea evenimentelor care sunt generate atunci când utilizatorul interacționează cu obiectele grafice.

Cea mai mare parte a obiectelor grafice utilizate în limbajul Java sunt subclase ale clasei abstracte Component. Excepția de la această regulă este reprezentată de meniurile clasei MenuComponent.

Imagine IV.3

Mai sus poate fi vazută ierarhia subclaselor care compun clasa Component. În cele ce urmează, voi prezenta pe scurt fiecare dintre subclasele de mai sus.

Clasa Container este o subclasă a clasei Component, menționată mai sus. O instanță a clasei Container reprezintă o componentă care poate include alte componente AWT. Crearea și afișarea pe ecran a obictelor grafice nu se realizează automat. Obiectele trebuie așezate pe o suprafață de afișare, cum ar fi o fereastră. Ele vor deveni vizibile atunci când suprafața de afișare pe care sunt plasate va deveni vizibilă. O suprafață de tipul celei descrise reprezintă o instanță a clasei Container.

Un container este deci, folosit pentru a adăuga componente pe suprafața sa. Componentele pe care le adăugăm vor fi adăugate într-o listă. Pozițiile pe care le vor avea componentele în aceasă listă definesc ordinea de traversare a acestora (de la primul la ultimul element). În cazul în care la adăugarea unei componente nu este specificat niciun index, această componentă va fi adăugată pe cea mai din urmă poziție.

Clasa Container conține metodele add (pentru adăugarea unei componente pe o suprafață de afișare) și remove (pentru eliminarea unei componente). Modul în care componentele sunt așezate pe suprafața de afișare nu este o caracteristică a clasei Containter. Orice obiect de tip container are atașat un gestionar implicit de poziționare. Acest gestionar implicit de poziționare este un obiect care implementează interfața LayoutManager. Pachetul java.awt conține următorii gestionari de poziționare:

FlowLayout: toate componentele sunt adăugate una dupa cealaltă, pe linii, de al stânga la dreapta, de sus în jos, în limita spațiului disponibil.

Imagine IV.4

BorderLayout: suprafața de afișare este împărțită în cinci regiuni (nord, sud, vest, est și centru). O componentă poate fi plasată în una dintre aceste regiuni ocupând întregul spațiu de afișare din acea regiune. Pentru a adăuga mai multe obiecte grafice în aceeași regiune, ele trebuie mai întâi grupate într-un panel care va fi apoi amplasat în zona dorită.

Imagine IV.5

GridLayout:suprafața de afișare este organizată ca un tabel cu linii și coloane, componentele fiind plasate în celulele tabelului, de la stânga la dreapta, de sus în jos. Toate celulele tabelului au aceeași dimensiune iar o componentă poate ocupa o singură celulă.

Imagine IV.6

GridBagLayout:suprafața de afișare este considerată un tabel care are celule de dimensiuni diferite, cu condiția ca celulele de pe aceeași linie să aibă aceeași înălțime iar cele de pe aceeași coloană să aibă aceeași lățime. O componentă poate ocupa mai multe celule ale tabelului.

Imagine IV.7

Controalele grafice permit interacțiunea cu utilizatorul.

Un obiect de tip Button (buton) este o componentă care are rolul de a plasa un buton etichetat pe o suprafață de afișare.

Un obiect de tip Canvas reprezintă o suprafață de desenare.

Un obiect de tip Checkbox (căsuță de opțiuni) reprezintă o componentă care se poate regăsi în una din stările „selectată” sau „neselectată”. Aceste obiecte sunt folosite pentru a prelua o anumită opțiune de la utilizator. Acțiunea pe care utilizatorul o întreprinde asupra obiectului îi schimbă acestuia starea în starea complementară celei în care se afla.

Un obiect de tip CheckBoxGroup (grup de comutatoare) definește un grup de componente din care doar unul poate fi selectat la un momentdat. Aceste componente poartă numele de butoane radio.

Un obiect de tip Choice reprezintă o listă de opțiuni din care utilizatorul are posibilitatea de a selecta una singură. La un momentdat singura opțiune vizibilă din listă este chiar cea selectată. Orice componentă de acest tip este însoțită de un buton etichetat cu o săgeată verticală. La apăsarea acestui buton este afișată lista întreagă din care utilizatorul poate selecta opțiunea dorită.

Un obiect de tip Label (etichetă) reprezintă o componentă definită pentru plasarea unui text pe o suprafață de afișare. O etichetă conține un text static scris pe o singură linie și care poate fi modificat doar din program, nu și de către utilizator.

Un obiect de tip List (listă de opțiuni) reprezintă o listă din care utilizatorul poate să selecteze, la un momentdat una sau mai multe opțiuni, în funcție de setarea acesteia. Din listă sunt vizibile atâtea opțiuni câte se încadrează în limita dimensiunilor grafice ale listei.

Un obiect de tip Scrollbar (bară de defilare) reprezintă o componentă fie verticală, fie orizontală, care pune la dispoziția utilizatorului o modalitate de a alege o valoare dintr-un anumit interval.

Un obiect de tip ScrollPane reprezintă o componentă care permite atașarea mai multor bare de defilare unei componente grafice. Acest tip de obiecte reprezintă o modalitate de a implementa obiectele care nu au funcționalitatea de defilare automată (cum ar fi listele).

Un obiect de tip TextField reprezintă un control de editare a textului. Este definit doar pentru o linie de text și este util în vederea interogarării utilizatorului în legătură cu anumite valori.

Un obiect de tip TextArea reprezintă un control de editare a textului definit pentru mai multe linii. Acest tip de obiect se utilizează în vederea adăugării unor comentarii sau a editării unor texte.

Pentru dezvoltarea aplicațiilor grafice se folosește clasa Window. Această clasă permite crearea unor ferestre care nu au chenar sau bară de meniuri. Pentru a crea ferestre mai complexe, se folosesc subclasele acesteia, Frame și Dialog.

Clasa Frame este folosită pentru crarea unor ferestre funcționale și independente care pot conține și bare de meniuri. Fiecare aplicație grafică are în componență cel puțion o astfel de fereastră, care poartă numele de fereastră principală și care va fi afișată la pornirea programului. În momentul în care o nouă fereastră este creată, ea nu este vizibilă. Aceasta devine vizibilă doar în momentul în care este apelată metoda show din clasa Window.

Gestionarul de poziționare implicit al clasei Window este BorderLayout. În momentul în care este creată o fereastră, aceasta va avea suprafața nulă până când îi vor fi adăugate componente. Butonul de închidere al ferestrelor nu este funcțional până când nu este implementată interfața WindowListener și nu este adăugat la lista ascultătorilor ferestrei evenimentul aferent.

Interfețele grafice oferă un tip special de ferestre create pentru preluarea de date de la utilizator. Acestea poartă numele de ferestre de dialog și sunt implementate prin intermediul clasei Dialog.

Cea mai mare diferență dintre obiectele de tip Dialog și obiectele de tip Frame constă în faptul că o fereastră dialog depinde de o altă fereastră (fereastră părinte). Atunci când asupra ferestrei părinte se aduc modificări, modificările se reflectă și în ferestrele sale dialog.

Plasarea componentelor pe o suprafață de afișare nu este tocmai simplă atunci când avem de-a face cu mai multe obiecte grafice. În acest caz, componentele ar trebui grupate într-un obiect de tip Panel (panou). Un panel reprezintă cel mai simplu obiect al clasei Panel, clasă care extinde clasa Container. Acesta nu are o reprezentare vizibilă, el doar oferă o suprafață de afișare unor componente grafice (posibil chiar altor panel-uri). Fiecarui panel îi este atașat în mod implicit gestionarul de poziționare FlowLayout. Acest gestionar poate fi schimbat utilizând metoda setLayout.

Prin urmare, pentru ca aranjarea componentelor să fie eficientă, trebuie urmați următorii pași:

Gruparea componentelor care au legătură în panel-uri;

Aranjarea componentelor fiecărui panel specificând gestionarele de poziționare corespunzătoare panel-ulurilor;

Aranjarea panel-urilor pe suprafața de desenare specificând gestionarul de poziționare al ferestrei.

Un eveniment se produce atunci când utilizatorul întreprinde o acțiune asupra uneia dintre componentele grafice care comunică efectiv cu programul. Dintre evenimentele des întâlnite amintim apăsarea unui buton, modificarea unu text dintr-o castetă de editare text și închiderea unei ferestre.

Evenimentele generate de componentele unui program sun interceptate prin intermediul unor clase speciale. Aceste clase poartă numele de listener (ascultător). În limbajul de programare Java, orice obiect poate „asculta” evenimente generate de anumite componente grafice.

Imagine IV.8

În ordinea scrierii unui fragment de cod sursă care să se execute atunci când utilizatorul și o componentă grafică interacționează, trebuie parcurși doi pași importanți. În primul rând trebuie scrisă o clasă de tip „listener” care să se ocupe cu „ascultatul” evenimentelor care sunt produse de acea componentă. În cadrul acestei clase trebuie implementate metodele specifice pentru tratarea evenimentelor. În cel de-al doilea rând trebuie comunicat componentei respective faptul că îi sunt „ascultate” de către clasă evenimentele pe care le generează. Altfel spus, clasa respectivă este un „consumator” al evenimentelor produse de componentă.

Aceste evenimente descrise anterior sunt, de fapt, obiecte. Pentru fiecare tip de eveniment există o clasă care instanțiază respectivul tip. Pentru acționarea unui buton avem de-a face cu un eveniment descris de clasa ActionEvent. Pentur modificarea unui text avem de-a face cu un eveniment descris de clasa TextEvent. Aceste două clase extind clasa AWTEvent.

Dacă în declarația unei clase se specifică faptul că această clasă trebuie să asculte evenimente, ea devine o clasă consumatoare de evenimente (listener). Continuând exemplul de mai sus spunem că o clasă care ascultă evenimente de tip ActionEvent implementează interfața ActionListener și că o clasă care ascultă evenimente de tip TextListener implementează interfața EventListener.

Orice aplicație care utlizează o interfață grafică cu utilizatorul trebuie să afișeze pe ecran toate componentele pentru care există o reprezentare vizuală. Pe lângă componentele standard, care sunt deja definite, este posibil să fie nevoie și de desenarea componentelor definite de programator.

Desenarea componentelor este un proces care se execută automat la afișarea pentru prima oară a unei componente, la operațiile de redimensionare a suprafeței de afișare sau la operațiile de maximizare sau minimizare și ca răspuns la o solicitare explicită de-a programului.

Procesul de desenare este controlat de trei metode ale clasei Component: metodele paint, update și repaint.

Metoda void paint(Graphic g) se ocupă de desenarea unei componente. Această metodă trebuie să fie supradefinită de fiecare componentă în parte pentru a furniza reprezentarea sa grafică deoarece definirea din superclasa Component nu are nicio implementare. Metoda trebuie apelată ori de câte ori conținutul unei componente este desenat sau modificat. Desenarea în Java trebuie să se facă doar în cadrul metodelor paint ale componentelor grafice. Parametrul g de tip Graphics reprezintă contextul grafic în care se execută desenarea componentelor. Un context grafic este un obiect prin intermediul căruia poate fi controlat procesul de desenare al unui obiect (o porțiune de ecran, imprimanta sau o zonă de memorie).

Observație: Pot fi realizate desene și în afara metodei paint, dar la orice redimensionare, maximizare sau minimizare a suprafeței de afișare, aceste desene vor dispărea.

Metoda void update (Graphics g) se ocupă de actualizarea stării grafice a unei componente. În vederea realizării acțiunii acestei metode trebuie efectuați următorii pași: se șterge componenta prin supradesenarea ei în culoarea fundalului, se stabilește culoarea componentei și se apelează metoda paint pentru redesenarea componentei. Ca și în cazul metodei paint, obiectul primit ca parametru reprezintp contextul grafic în care se execută desenarea componentelor.

Metoda void repaint( ) execută în mod explicit o apelare a metodei update cu scopul de a actualiza reprezentarea grafică a unei componente.

Pe lângă posibilitatea de a utiliza componentele grafice standard, Java oferă posibilitatea controlului la nivel de pixel pe dispozitivul grafic. Altfel spus este permisă desenarea diverselor forme grafice direct pe suprafața unei componente. Componenta Canvas din AWT este componenta din care se derivează subclase pentru crearea unor suprafețe de desenare. Desenarea pe o astfel de planșă se face supradefinind metoda paint a acesteia.

O planșă reprezintă, de fapt, o suprafață dreptunghiulară pe care se poate desena. Întrucât dimensiunile standard ale planșei sunt 0, se recomandă ca aceasta să redefinească metoda getPrefferedSize (sau getMinimumSize, getMaximumSize) deoarece ele vor fi apelate de către gestionarii de poziționare.

În ordinea creării unui desen sunt parcurși următorii pași:

Se crează o planșă de desenare (subclasă a clasei Canvas);

Se redefinesc metodele paint, getPrefferedSize, getMinimumSize, getMaximumSize;

Se adaugă planșa pe un container utilizând metoda add;

Se tratează evenimentele de tip KeyEvent, MouseEvent, FocusEvent dacă este cazul.

IV.4 Tehnologia Swing

Tehnologia Swing face parte din proiectul JFC (Java Foundation Classes) care are rolul de a facilita scrierea de aplicații care folosesc o interfață grafică imbunătățită față de AWT. JFC conține următoarele elemente:

Componente Swing – extind componentele oferite de modelul AWT;

Look-and-Feel – se referă la schimbarea înfățișării și a modului de interacțiune cu aplicația în funcție de preferințele utilizatoruilu;

Accesibility API – se referă la dezvoltarea de aplicații realizează comunicarea cu dispozitivele speciale pe care le utilizează persoanele cu diverse tipuri de handicap (de exemplu dispozitivele de recunoaștere a vocii);

Java 2D API – oferă facilități pentru crearea de aplicații grafice de nivel avansat (de exemplu desenele complexe, operațiile geometrice de scalare, rotație și translație);

Drag-and-drop – oferă facilitatea de a utiliza operații de tip drag-and-drop între aplicațiile Java;

Internaționalizare – alături de localizarea aplicațiilor permit dezvoltarea și configurarea acestora în diverse zone ale globului.

Tehnologia Swing oferă un set de componente GUI extensibile care permit crearea aplicațiilor Java cu interfață grafică competitivă comercial. În acest scop, în API – ul pe care Swing îl oferă se regăsesc șaptesprezece pachete care conțin sute de clase și interfețe. Dintre aceste șaptesprezece pachete cel mai important pachet este cel care conține pachetele de baza: javax.swing.

O grupare a componentelor care pot fi folosite în scopul creării interfețelor grafice Swing este următoarea:

Componente atomice – în această categorie intra componentele:

JLabel, JButton, JcheckBox, JRadioButton, JToggleButton, JScrollBar, JSlider, JProgressBar, JSeparator;

Componente complexe – în această categorie intră următoarele componente: JTable, JTree, JComboBox, JSpinner, Jlist, JFileChooser, JColorChooser, JOptionPane;

Componente care se ocupă de editarea textului:

JTextField, JFormatdedTextField, JPasswordField, JTextArea, JEditorPane, JTextPane;

Componente de tip meniu:

JMenuBar, JMenu, JPopupMenu, JMenuItem, JCheckBoxMenuItem, JRadioButtonMenuItem;

Componente de tip containter:

JPanel, JScrollPane, JSplitPane, JTabbedPane, JDesktopPane, JToolBar, JFrame, JDialog, JWindow, JInternalFrame, JApplet.

Swing nu înlocuiește pachetul AWT ci îl extinde adăugându-i diverse componente care fie le îmbunătățesc pe cele vechi, fie sunt cu totul noi. Astfel, printr-o convenție s-a stabilit ca numele unei clase AWT să fie prefixat cu litera „J” să reprezinte numele clasei care îi corespunde în Swing; deci clasei java.awt.Label îi corespunde javax.swing.JLabel.

Capitolul V: PREZENTAREA GENERALĂ A APLICAȚIEI

Aplicația de față reprezintă o modalitate de creare a unor desene folosind numai curbe Bézier. Inginerul francez Bézier este responsabil pentru reprezentarea curbelor în baza Bernstein. Pe de altă parte, lui Paul de Casteljau i se datorează posibilitatea descrierii curbelor lui Bézier într-un mod procedural.

Cu toate că lucrările de cercetare ale lui Pierre Bézier au fost elaborate mai târziu decât ale lui de Casteljau, ele au fost primele publicate. Rapoartele inginerului de la Citron au fost păstrate doar sub forma unor rapoarte tehnice ale firmei.

În cadrul aplicației am optat pentru folosirea scrierii curbelor Bézier utilizând algoritmul de Casteljau.

După cum știm cu toții, curbele Bézier au un rol foarte important în modelarea geometrică. Am ales să realizez această aplicație pentru că în ciuda faptului că ele sunt importante în grafică, nu sunt foarte răspândite aplicațiile interactive pe baza lor. În urma cercetărilor făcute de către mine, singurele programe care se bazează pe curbele Bézier pe care le-am găsit până acum prezintă curbele Bézier la nivel teoretic – în mare, prezintă doar modul de generare al acestora.

Aplicația are rolul de a exemplifica întrebuințările curbelor Bézier în grafică și de a arata cât de ușor pot fi acestea modelate. Aplicația poate fi folosită atât de studenții unor facultăți de profil tehnic, pentru a înțelege mai bine cum sunt definite curbele Bézier și cum pot fi acestea controlate cât și de orice altă persoană care este în căutarea unui program cu care să se „joace” în timpul liber. Cu toate acestea, aplicația nu este concepută în scop didactic.

Față de celelalte aplicații deja existente, lucrarea mea prezintă următoarul plus: utilizatorul iși poate alege modul în care vrea să folosească aplicația; fie că vrea doar să genereze o curbă Bézier, fie că vrea să genereze un desen folosind curbe Bézier, fie că vrea să reproducă un desen utilizând curbele mai sus menționate.

Aplicația este realizată în limbajul Java, utilizând o interfață grafică intuitivă, foarte ușor de folosit, în care sunt prezentate clar opțiunile. Am ales să folosesc limbajul de programare Java deoarece îmi este familiar din timpul facultății și deoarece acesta oferă posibilitatea de a lucra cu interfețele grafice într-un mod natural, nu foarte dificil.

Simplitatea și organizarea structurată a informațiilor face ca aplicația să fie una ușor de folosit și pentru persoanele care nu sunt foarte familiarizate cu tehnologia.

Așa cum spuneam și în capitolul anterior, în vederea lucrului cu interfețe grafice trebuie să luăm în considerare următoarele trei aspecte: crearea și afișarea pe ecran a unei suprafețe grafice pe care urmează să fie plasate obictele grafice, existența unei modalități de poziționare a obiectelor pe suprafața grafică menționată și un mecanism prin care programul să răspundă la acțiunile pe care un utilizator le execută asupra obiectelor grafice.

Pentru realizarea lucrului cu interfețele grafice am folosit pachetele de clase java.swing și java.awt.

Swing constă într-o serie de componente vizuale care extind componentele pachetului de clase java.awt (Abstract Window Toolkit). Cu toate că Swing conține atât componentele pachetului AWT îmbunătățite, am optat să le folosesc pe ambele deoarece există câteva incompatibilități între cele două. Spre exemplu, în AWT Frame se pot adăuga componente direct la instanța frame deoarece clasa AWT Frame crează automat o instanță Panel (putem folosi, deci, comanda frame.add(component)) spre deosebire de clasa JFrame, unde acest lucru nu este la fel de ușor. În cazul clasei Jframe trebuie sa precizăm exact în care dintre componentele ale lui JrootPane vom plasa componenta dorită (de obicei folosim contentPane). Sintaxa pe care o folosim pentru JFrame este: myJFrame.getContentPane().add(component).

După cum am spus în capitolul precedent, la interacțiunea dintre utilizator și o componentă grafică se produce un eveniment. Utilizând aceste evenimente am construit toate panourile de care avem nevoie în dezvoltarea aplicației. Construirea unui astfel de panou se face în următorul mod:

/*––––––––––- PANEL START ––––––––*/

Panel_start.setBackground(new Color(255,235,255));

JButton btnGenerareCurbe = new JButton("Generarea unei curbe Bézier");

btnGenerareCurbe.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

Panel_generare.setVisible(true);

Panel_start.setVisible(false);

}

});

btnGenerareCurbe.setBounds(71, 79, 287, 23);

Panel_start.add(btnGenerareCurbe);

JButton btnReproducereaUnorDesene = new JButton("Crearea de desene folosind curbe Bézier");

btnReproducereaUnorDesene.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

Panel_reproducere.setVisible(true);

Panel_start.setVisible(false);

}

});

btnReproducereaUnorDesene.setBounds(71, 166, 287, 23);

Panel_start.add(btnReproducereaUnorDesene);

Aplicația constă pe de o parte în construirea și modificarea unei curbe Bézier dată de o mulțime de puncte de control dată de utilizator și, pe de altă parte, crearea sau reproducerea unor desene date folosind numai curbe Bézier predefinite în prealabil. Ambele moduri de utilizare ale aplicației vor fi descrise mai detaliat în paginile următoare.

Așa cum spuneam mai sus, aplicația are două moduri de utilizare. În captura de ecran de mai jos cele două moduri pot fi observate:

Imagine V.1

Panel-ul surprins în captura de ecran de mai sus este chiar cel generat în secvența de cod sursă de mai sus.

Cel dintâi mod de utilizare al aplicației îi corespunde primului buton, „Generarea unei curbe Bézier” constă, evident, în generarea curbe Bézier corespunzătoare unei mulțimi date de puncte de control. Fiecare punct de control este ales de utilizator printr-un singur click. Utilizatorului aplicației îi este pus la dispoziție un meniu de tip drop-down (un obiect de tip Choice) din care poate alege una dintre opțiunile: extindere, editare sau ștergere. Astfel, în funcție de opțiunea aleasă, punctele care determină curba pot fi mutate sau șterse, putând astfel să încercăm generarea unui desen anume.

Prima opțiune a obiectului de tip Choice, opțiunea „Extindere”, este prima cea implicită. Aceasta îi permite utilizatorului să adauge puncte noi la mulțimea care determina curba. Singurul lucru pe care acesta trebuie să îl facă pentru a adauga un nou punct este să dea click în locul in care dorește să fie amplasat noul element al mulțimii punctelor de control care determină curba. La fiecare punct pe care utilizatorul îl adaugă, traiectoria curbei este actualizată.

Pentru o precizie mai mare, pe ecran sunt afișate tot timpul coordonatele mouse-ului. Pentru afișarea coordonatelor la care se află mouse-ul am utilizat funcția setCoords(int x, int y). Această funcție se ocupă cu determinarea coordonatelor la care se află pointer-ul mouse-ului. Odată aflate coordonatele, le inserăm într-un obiect de tip Label (etichetă). La fiecare mișcare a mouse-ului, coordonatele pointer-ului sunt actualizate.

Cea de-a doua opțiune a obiectului de tip Choice, „Editare”, îi oferă utilizatorului posibilitatea de a modifica poziția unui punct dintre cele care determina curba. Ceea ce trebuie să facă utilizatorul pentru a modifica o curbă este să își aleagă un punct pe care să îl mute utilizând o mișcare de tip drag and drop. Altfel spus, trebuie să dea click pe punctul pe care dorește să îl repozitioneze, să țină butonul de click apăsat pe tot parcursul acțiunii și să miște cu ajutorul mouse-ului punctul până acesta ajunge pe poziția dorită. Și în acest caz, traiectoria curbei este actualizată pe tot parcursul mutării punctului.

Ultima opțiune a obiectului, opțiunea „Ștergere”, îi permite utilizatorului să șteargă un punct din mulțimea punctelor care determină curba Bézier. Pentru a șterge unul dintre punctele menționate, singurul lucru care trebuie făcut este apăsarea click-ului la coordonatele punctului pe care dorim să îl eliminăm. Bineînțeles, la ștergerea oricărui punct se reactualizeaza traiectoria curbei.

Utilizatorul aplicației are la dispoziție, pe lângă meniul de tip drop-down și trei butoane la apăsarea cărora au loc diverse acțiuni.

Primul buton dintre cele trei are ca text setat „Ștergeți toate punctele”. Așa cum este de așteptat, apăsarea acestui buton are ca efect eliminarea tuturor punctelor care alcătuiesc poligonul de control al curbei care era în curs de generare.

Cel de-al doilea buton, „De-Casteljau” încarcă prezentarea algoritmului lui de Casteljau într-un mod cât mai intuitiv pentru curba creată.

Apăsarea ultimului buton, „Înapoi”, întoarce aplicația la panel –ul anterior.

Imagine V.2

În imaginea de mai sus pot fi observate toate detaliile pe care le-am prezentat anterior. Panel-ul foloște un gestionar de poziționare de tip BorderLayout împărțită doar în trei regiuni. În zona de nord a acestuia se regăște label-ul (eticheta) care indică poziția mouse-ului. În zona centrală este amplasată suprafața de desenare pe care se vor afla curbele ce urmează a fi generate. În zona sudică a paginii se regăsesc obiectul de tip Choice care conține alegerile posibile și cele trei butoane a căror acțiune este deja descrisă. Se observă atât punctele care alcătuiesc poligonul de control cât și segmentele de dreaptă care unesc cele două puncte și bineînteles, curba corespunzătoare acestora.

Pentru construirea unei curbe Bézier definită de o mulțime de puncte, am folosit câteva funcții pe care urmeză să le prezint.

Fie două puncte p0 și p1 date și fie t o valoare reală din intervalul [0,1]. Funcția „interpolare”, existentă mai jos, returnează punctul rezultat în urma interpolării celor două puncte de mai sus folosind valoarea parametrului t. Așa cum am spus în primul capitol, formula pe care o folosim pentru interpolarea a două puncte într-un al treilea este:

În cazul de față, punctele p0 și p1 sunt și iar punctul ce va fi returnat de către funcția de mai jos îi corespunde lui .

public static Point interpolare(Point p0, Point p1, double t){

double x = (1-t) * p0.x + t * p1.x;

double y = (1-t) * p0.y + t * p1.y;

return new Point ((int) Math.round(x), (int) Math.round(y));

}

Cea de-a doua funcție imi calculează utilizând funcția de interpolare de mai sus, fiecare punct al algoritmului lui de Casteljau.

public static Point evalBezier(Point arr[],double t) {

for (int iter = arr.length ; iter > 0 ; iter–) {

for (int i = 1 ; i < iter ; i++) {

arr[i-1] = interpolare(arr[i-1],arr[i],t);

}

}

return arr[0];

}

Nu în ultimul rând, funcția „drawBezier” desenează punctele care determină curba și dreptele care le unesc. Reamintim faptul că o curbă Bézier generată de două puncte este chiar segmentul de dreaptă care unește cele două puncte.

protected void drawBezier(Graphics g) {

int np = points.size();

Point ptArray[] = new Point[np];

Point p0,p1;

if (np < 2)

return;

else if (np == 2){

p0 = (Point)points.elementAt(0);

p1 = (Point)points.elementAt(1);

g.setColor(Color.red);

}

p0 = (Point)points.elementAt(0);

for (int i = 1 ; i <= 50 ; i++) {

double t = (double)i/50.0; //t in intervalul [0,1]

points.copyInto(ptArray);

p1 = functiiGeometrice.evalBezier(ptArray,t);

g.setColor(Color.red);

g.drawLine(p0.x, p0.y, p1.x, p1.y);

p0 = p1;

}

}

În încercarea de a face aplicația cât mai simplu de utilizat, aceasta conține, pe lângă implementarea fragmentulului descris anterior și câteva informații despre aceasta parte. Altfel spus, am menționat în cel mai scurt mod definiția unei curbe Bézier și am prezentat în mică măsură ce își propune să facă aplicația.

Am precizat de asemenea și câteva indicații despre cum ar trebui să fie utilizată aplicația pentru a obține o curbă Bézier care să fie cât mai aproape de desenul pe care utilizatorul și-a propus să îl realizeze. Cele trei opțiuni care compun obiectul de tip Choice prezentat mai sus sunt foarte importante în vederea realizării figurii dorite.

În vederea realizării acestui lucru, am populat panel-ul (panoul) respectiv cu o suprafață pe care se poate încărca text și am adăugat textul dorit în aceasta.

Imagine V.3

De asemenea, tot în aceasta parte a aplicației pot fi văzuți și pașii intermediari ai generării curbei prin intermediul algoritmului lui De Casteljau.

Așa cum am spus și în primul capitol al lucrării, algoritmul lui de Casteljau generează pentru fiecare două puncte consecutive ale poligonului de control se generează un nou punct prin interpolare, dupa o valoare t care aparține intervalului [0,1], după următoarea formulă:

unde r = și j = .

Pentru reproducerea algoritmului lui de Casteljau pe exemplul de față, am folosit o funcție care la fiecare pas face următorele: desenează primul punct (cel rezultat din interpolarea primelor două puncte), apoi deseneaza toate segmentele de dreaptă generate de punctele date (inclusiv segmentele care determină curba) și, în cele din urmă, desenează restul punctelor. La ultimul pas, desenează (cu culoarea neagră) chiar ultimul punct generat (în urma interpolării ultimelor două puncte obținute).

protected void drawDeCasteljau(Graphics g) {

int np = points.size();

if (np <= 0)

return;

Point p0,p1;

for (int i=0 ; i <= step ; i++) {

p0 = dePnts[i][0];

g.setColor(new Color(238,58,140));

g.fillRect(p0.x – 2, p0.y – 2, 4, 4);

for (int j = 1 ; j < np-i ; j++) {

p1 = dePnts[i][j];

g.setColor(new Color(255,182,193));

g.drawLine(p0.x, p0.y, p1.x, p1.y);

g.setColor(new Color(238,58,140));

g.fillRect(p1.x – 2, p1.y – 2, 4, 4);

p0 = p1;

}

}

if (step == np-1) {

drawBezier(g);

g.setColor(Color.black);

p0 = dePnts[step][0];

g.fillRect(p0.x – 2, p0.y – 2, 4, 4);

}

}

Imagine V.4

Imaginea de mai sus exemplifică aplicarea algoritmului de Casteljau pentru curba prezentă imaginea V.2. Și de această data, asupra panel-ului este aplicat un gestionar de poziționare de tip BorderLayout.

Partea de nord și partea centrală ale panoului sunt populate în același mod ca și în cazul generării de curbe Bézier. În partea de sud a panel-ului găsim o etichetă care afișează valoarea pe care parametrul t o are la un momentdat, un scrollbar (bară de defilare) orizontal și două butoane.

Scrollbar-ul este adăugat în următorul sens: pentru fiecare unitate de deplasare spre stânga se scade valoarea 0.1 din parametrul t, respectiv la fiecare unitate deplasată spre dreapta se adaugă valoarea 0.1 la parametrul t. Este de reținut faptul că parametrul t este definit doar pe intervalul [0,1]. Valoarea lui t este actualizată în conținutul etichetei ori de câte ori asupra barei de defilare intervin modificări.

Primul buton, „Pasul următor” este responsabil de avansarea cu un pas în algoritmul de Casteljau.

Matricea triunghiular inferioară corespunzătoare schemei lui de Casteljau este, pentru cazul general, următoarea:

b0

b1

b2

………………………………………………..

bn ……… .

Elementele de pe prima coloană sunt chiar punctele de control ale curbei. Practic, la fiecare apăsare a lui se generează punctele de pe coloana următoare în matricea inferior triunghiulară de mai sus (matricea se parcurge de la stânga la dreapta, de sus în jos). La primul pas sunt desenate doar punctele care compun poligonul de control al curbei și segmentele de dreaptă care le unesc, două câte doua. La fiecare apăsare a butonului „Pasul următor” vor fi interpolate cele n puncte generate anterior și vor fi desenate cele n-1 puncte rezultate alături de segmentele de dreaptă care le unesc. La ultimul pas va fi generat un singur punct, desenat cu culoarea negru. Curba Bézier generată în urma utilizării algoritmului de Casteljau va fi curba care trece prin primul punct al poligonului de control, ultimul punct generat de algoritm și ultimul punct al poligonului de control.

Ultimul buton, „OK” are rolul de a întoarce aplicația la panel –ul anterior (cel în care se generează o curbă Bézier pe baza unor puncte date).

În cel de-al doilea mod de utilizare, corespunzător butonului „Crearea de desene folosind curbe Bézier”, utilizatorul va putea realiza sau reproduce niște desene existente utilizând doar curbe Bézier.

Pentru partea de creare a unor desene, nu va fi încărcată nicio imagine de fundal, lăsând utilizatorului libertatea de a-și pune în practică imaginația. La fiecare pas, utilizatorul aplicației poate adauga o curbă Bézier, asupra căreia poate face modificări. Curba Bézier adăugată la fiecare pas este determinată de patru puncte definite anterior. Toate curbele vor fi adăugate în același loc, fiind determinate, inițial, de același poligon de control (altfel spus, de aceleași patru puncte). În cazul de față am ales ca cele patru puncte care determină curba să fie următoarele:

Point p00 = new Point(50,36);

Point p01 = new Point(193,101);

Point p02 = new Point(67,167);

Point p03 = new Point(15,15);

points1.addElement(new Point(p00.x, p00.y));

points1.addElement(new Point(p01.x, p01.y));

points1.addElement(new Point(p02.x, p02.y));

points1.addElement(new Point(p03.x, p03.y));

Spre deosebire de prima parte a aplicației, de această dată, prin modificarea curbei mă refer doar la opțiunea prezentată anterior ca „editare”. Așadar, utilizatorul poate modifica poziția unui punct al poligonului de control, curba reactualizându-se. Pentru un exemplu concret, am modificat prima curba și am adaugat încă două, una dintre ele rămânând chiar în poziția în care a fost creată.

Imagine V.6

În imaginea de mai sus se poate observa plasarea unei curbe noi pe poziția standard, asupra căreia nu s-a făcut nici o modificare. Cu o nuanță de gri deschis am desenat și poligonul de control care determină curba. Se poate observa că și acest panou utilizează un gestionar de fișiere împărțit pe trei zone. Zona de nord conține o etichetă, un obiect de tip Choice și două butoane, zona centrală este ocupată de suprafața de desenare iar zona sudică are în alcătuire două butoane.

Eticheta din partea de nord a paginii conține textul static și ne-editabil „Încarcă fundal” și face referire la alegerea uneia dintre opțiunile obiectului de tip Choice.

Lista de tip drop-down prezintă toate desenele salvate până în momentul de față, începând cu desenele predefinite de către mine și terminând cu desenele salvate de utilizator.

Butonul „Curbă nouă” adaugă o nouă curbă pe suprafața de desenare, curbă ale cărei puncte de control sunt cele definite mai sus. În cazul în care este deja o curbă pe aceeași suprafață, cele două se vor suprapune.

Butonul „Salvează imaginea”, așa cum este de imaginat, se ocupă de salvarea desenului realizat de utilizator.

Butonul „Golire ecran”, din zona sudică a panel-ului realizează ștergerea tuturor curbelor de pe suprafața de desenare.

Butonul „Înapoi” se ocupă de tranziția între panel-uri.

Pentru adăugarea și editarea unei curbe Bézier am folosit același cod pe care l-am descris anterior, pe care îl folosesc și la generarea unei curbe Bézier.

Imagine V.7

În imaginea de mai sus se pot observa trei curbe Bézier alături de punctele de control care le determină și segmentele de dreaptă dintre acestea. Cea mai din stânga curbă este una adăugată pe poziția standard, celelalte două sunt formate prin editarea unor curbe aflate pe aceleași poziții cu prima.

În cazul în care utilizatorul este încântat de desenul pe care l-a realizat, acesta are opțiunea de a salva imaginea. Pentru a realiza acest lucru, el trebuie doar să apese butonul ”Salvează imaginea” și, pe ecran va apărea desenul acestuia fară punctele de control și segmentele de dreaptă care determină curbele. Desenul salvat poate fi apoi incărcat ca imagine de fundal. Desenele salvate de un utilizator la un momentdat rămân salvate doar la nivelul sesiunii de rulare a aplicației. În momentul în care aplicația este închisă, desenele proaspăt salvate se pierd.

Mai jos se poate observa ce se întâmplă cu desenul de mai sus dacă este apăsat butonul „Salvează imaginea”.

Imagine V.8

Pentru a reproduce un desen, va trebui sa alegem o imagine care va fi încărcată ca imagine de fundal în respectivul panel. Aplicația are un număr de desene deja date de către mine în codul sursă, ele putând fi reproduse folosind curbele Bézier. Pe lângă desenele standard, existente deja la rularea aplicației, avem posibilitatea de a alege ca fundal chiar un desen dintre cele desenate și salvate de noi. Toate imaginile care pot fi încărcate ca fundal se regăsesc într-o listă de tip drop-down. De fiecare dată când un desen este salvat, el este adăugat în lista respectivă cu numele de „New_i”, unde i reprezintă indicele desenului salvat în cadrul acestei sesiuni. Acest indice este de asemenea resetat la închiderea și redeschiderea aplicației.

În imaginea de mai jos poate fi observat un desen deja existent, încărcat ca fundal. Se observă cum din lista care conține numele desenelor a fost aleasă opțiunea „Măr”.

În ideea de a face mai evidentă diferenta dintre fundal și curbele adăugate de utilizator în încercarea sa de a reproduce desenul, am ales ca fundalul să aibă o culoare mai deschisă decât curbele. Astfel, desenul ce trebuie reprodus este de culoare gri iar curbele de care ne folosim sunt negre.

În acest moment scopul utilizatorului este să reproducă desenul încărcat ca imagine de fundal și care reprezintă un măr.

Imagine V.9

Pentru a salva în memorie un desen creat, am decis să folosesc o structură de tip vector ale cărui elemente vor fi, la rândul lor, tot vectori. Astfel, fiecare element din structură reprezintă un vector de puncte în care vor fi reținute abscisa și ordonata pentru fiecare punct care determină o curbă.

Vector <Vector<Point>> points2 = new Vector<Vector<Point>>();

Mai exact, pe prima poziție în vectorul points2 menționat mai sus se va afla reprezentarea primei curbe care alcătuiește desenul. Evident, o curbă este reprezentată ca un vector alcătuit din punctele care o determină. Pe cea de-a doua poziție în vectorul points2 se va afla reprezentarea celei de-a doua curbe care alcătuiește desenul și așa mai departe.

Am precizat mai sus faptul că desenele salvate pot fi regăsite în meniul de tip drop-down, în care imaginile predefinite au nume corespunzătoare atașate iar cele proaspăt salvate poartă numele de: „New_i”, unde i reprezintă numărul desenului proaspăt salvat. Pentru a reține toate desenele salvate, am folosit un vector în care fiecare element reprezintă un desen care are structura prezentată mai sus.

static Vector <Vector<Vector<Point>>> saved = new Vector Vector<Vector<Point>>>();

Mai jos se observă toate opțiunile care pot fi alese în cadrul acestei execuție a programului.

Imagine V.10

Pentru reproducerea unui desen existent utilizatorul va face următoarele: la un pas va introduce o curba Bézier determinată de un număr de puncte predefinite (în cazul de față, cele patru puncte indicate mai sus). Această curbă poate fi modificată prin mutarea punctelor. În urma prelucrărilor realizate asupra ei, aceasta poate fi adusă la forma și poziția potrivită unei bucăți din desen (sau chiar a întregului desen, dacă acesta poate fi reprodus utilizând o singură curbă Bézier cubică) .

Imagine V.11

În imaginea de mai sus se vede o încercare de a plasa prima și cea de-a doua curbă pe pozițiile potrivite.

În momentul în care consideram ca am plasat prima curbă în modul potrivit, putem adăuga o alta, care poate fi editată folosind același procedeu. Imaginea de mai jos exemplifică situația în care am tocmai am adăugat două curbe pe pozițiile potrivite și o a treia care nu a fost încă modificată, pentru a fi adusă la poziția dorită.

Imagine V.12

Scopul aplicației este, bineînteles, reproducerea integrală a desenului ales, eventual utilizând cât mai puține curbe Bézier cubice.

Este de reținut faptul că desenul de mai sus, cel care reprezintă un măr, este un exemplu ușor de reprodus utilizând instrumentele la care avem acces. Există bineînteles și exemple mai dificil de reprodus. Reproducerea imaginii de mai jos, care încearcă să reprezinte o floare necesită utilizarea mult mai multor curbe decât reproducerea banalului măr și mult mai multă atenție la modul în care punctele de control ale curbelor se intersectează.

Astfel, dacă mărul de mai sus poate fi reprodus destul de ușor prin utilizarea a patru curbe Bézier cubice, pentru desenul reprezentând floarea de mai jos, trebuie folosite în cel mai bun caz un număr de nouă curbe Bézier cubice.

Imagine V.13

Am adăugat, bineînțeles, și în această a doua parte a aplicației un panou cu o suprafață care conține text, în vederea explicării mai exacte a modului în care proiectul rulează.

Imagine V.13

În concluzie, aplicația are două părți, cea dintâi fiind, de fapt, implementarea bazei matematice de care avem nevoie în cea de-a doua. Prima parte conține câteva funcții care se ocupă cu generarea unei curbe Bézier utilizând algoritmul lui de Casteljau.

Cea de-a doua parte este mai complexă, utilizatorul putând face mai mult decât să genereze o curbă Bézier. În această a doua parte, dacă background-ul suprafeței de desenare este alb înseamnă că nu a fost aleasă nici o imagine de fundal iar aplicația poate fi folosită doar pentru a genera anumite desene. Aceste desene pot fi ulterior salvate și încărcate ca imagini de fundal. Daca fundalul suprafeței de desenare nu este alb, ci conține un anume desen, scopul utilizatorului devine acela de a reproduce desenul din fundal.

Pentru a realiza aplicația am parcurs următorii pași: în primul rând, am creat un algoritm care generează o curbă Bézier corespunzatoare unui set dat de puncte. În vederea acestui pas am folosit algoritmul lui de Casteljau. În al doilea rând, m-am ocupat de posibilitatea modificării traiectoriei unei curbe, prin mutarea sau ștergerea punctelor care o determină respectiv adăugarea unor puncte noi la mulțimea responsabilă de determinarea curbei. Ultimele lucruri de care am avut nevoie pentru realizarea proiectului au fost implementarea unui algoritm care să salveze un desen în funcție de punctele de care este determinat si a unui algoritm care să încarce ca imagine de fundal un desen deja salvat.

Concluzie

Așa cum am spus și la începutul lucrării, modelarea geometrică reprezintă o ramură importantă a informaticii și matematicii ale cărei principale idei se bazează pe conceptele geometrice utilizate în grafica pe calculator.

Primii beneficiari ai modelării geometrice au fost industria constructoare de mașini și industria aviatică.

În ultimii ani, conceptul de modelare geometrică s-a extins în diverse domenii – de la imagini media până la domeniul medical, aici referindu-ne la aplicațiile modelării geometrice în tomografiile computerizate.

Unul dintre elementele fundamentale ale modelării geometrice este reprezentat de curbele Bézier, descoperite de inginerul francez cu același nume în anii 1960.

Această lucrare de licență prezintă curbele Bézier și de aplicațiile grafice care se pot genera pe baza lor. Lucrarea a fost structurată în cinci capitole care conțin prezentarea matematică și informatică a curbelor Bézier, existența acestora în alte domenii și prezentarea aplicației și a tehnologiilor folosite în dezvoltarea acesteia.

Aplicația exemplifică întrebuințările curbelor Bézier în grafica pe calculator și își propune să arate cât de ușor pot fi acestea modelate. Aplicația nu este concepută în scop didactic dar poate fi folosită de către studenții care vor să înteleagă cum este generată o curbă Bézier. Aplicația realizată de mine oferă utilizatorului, față de restul aplicațiilor pe care le-am studiat, posibilitatea de a-și alege modul în care dorește să folosească aplicația. În acest scop are la dispoziție următoarele variante: generarea unei curbe Bézier, crearea unui desen utilizând curbe Bézier și reproducerea unui desen utilizând curbe Bézier.

În cele ce urmează voi rezuma pașii făcuți în dezvoltarea aplicației. Astfel, am creat un algoritm care generează o curbă Bézier corespunzatoare unui set dat de puncte utilizând algoritmul lui de Casteljau. Ulterior am tratat posibilitățile de modificare a curbei și am implementat un algoritm care să salveze un desen în funcție de punctele de care este determinat si a unui algoritm care să încarce ca imagine de fundal un desen deja salvat.

Am realizat aplicația în limbajul de programare Java, utilizând o interfață grafica intuitivă și structurată clar. Datorită acestor caracteristici, aplicația este una ușor de folosit și pentru persoanele nefamiliarizate cu tehnologia.

În concluzie, ceea ce am vrut să scot în evidență în cadrul lucrarării de față este faptul că o curbă Bézier poate fi foarte ușor modelată în aplicațiile care utilizează grafica pe calculator.

Bibliografie

[1] Emilia Petrișor, ,,Modelare Geometrică Algoritmică”, Editura Tehnică, București, 2001.

[2] Gerald Farin, ,,Curves and Surfaces for CAGD” – A practical guide, Academic Press, 2002.

[3] Hartmut Prautzch, Wolfgand Boehm, Marco Paluszny, ,, Bézier and B-Spline Techniques”, Editura Springer-Verlag, 2002

[4] Mihai – Sorin Stupariu, „Geometrie Computațională”, Cursul din Semestrul I, 2012-2013.

[5] Liliana Brăescu, Eva Kaslik, Simina Masiș, Simona Epure, Ioane Rodilă, „Curs de geometrie”, Timișoara, 2007

[6] Ruxandra Marinescu, Cursul de Tehnici Avansate de Programare, Anul II, Semestrul I

[7] Cristian Frasinaru, Curs practic de Java

[8] http://ro.math.wikia.com/wiki/Curbă_Bézier

[9] http://www.dynamicgeometry.com/JavaSketchpad/Gallery/Other_Explorations_and_Amusements/Bezier_Curves.html

[10] http://en.wikipedia.org/wiki/B%C3%A9zier_surface

[11] http://www.truetype-typography.com/ttoutln.htm

[12] http://ro.wikipedia.org/wiki/Java_%28limbaj_de_programare%29

Bibliografie

[1] Emilia Petrișor, ,,Modelare Geometrică Algoritmică”, Editura Tehnică, București, 2001.

[2] Gerald Farin, ,,Curves and Surfaces for CAGD” – A practical guide, Academic Press, 2002.

[3] Hartmut Prautzch, Wolfgand Boehm, Marco Paluszny, ,, Bézier and B-Spline Techniques”, Editura Springer-Verlag, 2002

[4] Mihai – Sorin Stupariu, „Geometrie Computațională”, Cursul din Semestrul I, 2012-2013.

[5] Liliana Brăescu, Eva Kaslik, Simina Masiș, Simona Epure, Ioane Rodilă, „Curs de geometrie”, Timișoara, 2007

[6] Ruxandra Marinescu, Cursul de Tehnici Avansate de Programare, Anul II, Semestrul I

[7] Cristian Frasinaru, Curs practic de Java

[8] http://ro.math.wikia.com/wiki/Curbă_Bézier

[9] http://www.dynamicgeometry.com/JavaSketchpad/Gallery/Other_Explorations_and_Amusements/Bezier_Curves.html

[10] http://en.wikipedia.org/wiki/B%C3%A9zier_surface

[11] http://www.truetype-typography.com/ttoutln.htm

[12] http://ro.wikipedia.org/wiki/Java_%28limbaj_de_programare%29

Similar Posts