Az elméleti részben nagy vonalakban áttekintettük azokat a lehetőségeket, amikkel felületeket tudunk leírni. Mi most ebben a részben csak az Euler-Monge típusú felületekkel fogunk foglalkozni, de előtte még megnézzük azt, hogyan lehet létrehozni, például egy gömböt virtuális világunkban.

Két skaláris változótól függő vektorfüggvény

Még egy kis elmélet következik a gyakorlat előtt. Szóval tekintsünk most az (u,v) síkon (paramétersíkon) vagy annak egy tartományában értelmezett három dara kétváltozós függvényt. Az x, y, z függvényeket. Ha ez megvan, akkor legyen ezeknek a függvényeknek az értelmezési tartománybeli az u, v szám párhoz tartozó x(u,v), y(u,v), z(u,v) helyettesítési értéke egy r helyvektor három koordinátája a derékszögű Descartes-féle koordinátarendszerben a következő lesz: (u,v) Ž r(u,v)=x(u,v)i+y(u,v)j+z(u,v)k

Ha u, v befutja az értelmezési tartományt, akkor az előbbi utasítással két skaláris változótól (paramétertől) függő vektor-skalár függvényt értelmeztünk. Ha most a r(u,v) vektor-skalár függvény értékkészletét alkotó helyvektorokat a koordináta-rendszerben ábrázoljuk, akkor ezek végpontjainak halmaza az r(u, v) grafikonját alkotja. Ez általában egy felület lesz, nekünk pedig pont ez kell (lásd 1. ábra). Ha az egyik paramétert, mondjuk az u-t állandónak választjuk, akkor r(u,v) csak egyetlen paramétertől függ, tehát grafikonja egy, a felületen elhelyezkedő görbe, felület görbe lesz. Mivel u=állandó választással jött létre, v paramétervonalnak nevezzük. Hasonlóképpen a v=állandó választással az u paramétervonalak jönnek létre.

Ezek után már bátran nekiugorhatunk egy gömb modellezéséhez. A sík, a gömb és egyéb másodrendű felület megadása egy három ismeretlenes egyenlettel történik. A felület pontjai azzal jellemezhetőek, hogy koordinátái eleget tesznek egy három ismeretlenes egyenletnek, általánosságban ezt így jelölnénk: f(x,y,z)=0. Ha ebből ki tudnánk fejezni z-t, akkor az úgynevezett Euler-Monge-féle megadásról beszélnénk, lásd majd a következő fejezetet. Esetünkben az origó középpontú R sugarú gömb ama félgömbjének az egyenlete, amelyet belőle az xy koordinátasík vág le és a z-tengely pozitív irányába esik, X2+Y2+Z2=R2 (Zł 0) alku lesz. Ezt könnyedén Euler-Monge-módszerrelalakba lehet hozni. Első feladatunk tehát az, hogy az x2+y2+z2=r2 egyenletű gömbfelület vektoregyenletét feltudjuk írni. A megoldás pofon egyszerű lesz. Vegyük a gömbfelület tetszőleges P pontját. Nos ennek a P pontnak a koordinátáit kell meghatározni. A követezőek lesznek, ha u-nak választjuk a P pont x, y síkon lévő P' vetületéhez vezető egyenes és az x tengely hajlásszögét, és v-nek pedig a P ponthoz vezető sugár és a z tengely hajlásszögét:

    x=r*sinv*cosu

    y=r*sinv*sinu r(u,v)

    z=r*cosv

Ezért a gömbfelület vektoregyenlete: r(u,v)=(r*sinv*cosu)*i+(r*sinv*sinu)*j+(r*cosv)*k ahol 0Ł uŁ 2p és 0Ł vŁ p . Ezzel készen is volnánk.

Igazából a megvalósítás során számunkra az explicit formára lesz szükségünk. Kezdésként hozzunk létre néhány konstanst:

Const radius=40; finomsag=0.2;       pn=1000; { maximum number of points }

A radius-ban fogjuk eltárolni gömbünk sugarát, a finomság mértékétől függ majd, hogy hány pontot is fogunk előállítani a felületbél, és végül pn megszabja a maximális pontok számát. Ezután a pontok számára létrehozunk egy points nevű váltózót, ami végül is egy pn*3-as mátrix lesz:

      points : Array[1..pn,0..2] of integer;

Így a mátrixunknak pn sora és három oszlopa lesz, pn a pontok száma 1-től pn-ig, míg 0,1,2 megfelel a pontok koordinátáinak, úgy mint x,y,z. Ezután már az alábbi eljárás segítségével, könnyedén létrehozhatjuk gömbünket:

Procedure Initialize; var   alpha,betha:real;   i:word;   r,x,y,z:integer; begin   i:=1;   alpha:=2*pi;   while alpha>0 do begin     betha:=pi;     while betha>0 do begin       x:=round(radius*cos(alpha)*sin(betha));       y:=round(radius*cos(betha));       z:=round(radius*sin(alpha)*sin(betha));       points[i,0]:=x; points[i,1]:=y; points[i,2]:=z;       betha:=betha-finomsag;       inc(i);       if i> pn then begin         writeln('to many points, change step...'); halt; end;       end;       alpha:=alpha-finomsag;     end;     nofpoints:=pred(i);   end;

Ahogy látható, nem csinálunk mást, csak szépen befutjuk az intervallumot alpha esetében 0 és 2p , míg betha esetében 0 és p között. És közben az x,y,z koordinátákat a megkapott képletek alapján kiszámítjuk, és a mátrixunkba töltjük. Mivel alpha-nak és betha-nak az intervallum maximális értékét adtuk meg kezdőértéknek, ezért visszafelé haladva számítjuk ki a pontokat, ezért egy-egy pont után alpha és betha értékéből ki kell vonni a finomságot, vagyis azt az értéket, ami meghatározza, hogy hány pontot is akarunk számítani. Amint alpha és betha értéke eléri az intervallum alsó határát a ciklus befejeződik. Érdemes a ciklus során számolni a ténylegesen kiszámított pontok számát, mert a megjelenítéskor semmi értelme nincs a kiszámítottnál több vagy éppen kevesebb ciklusra. Mi most a megjelenítés legkönnyebb és leglátványtalanabb módját válaszuk, minden pontot pixelként jelenítünk meg.

  For n:=1 to nofpoints do begin     setcolor(15);     Vetit(points[n,0],points[n,1],points[n,2]);     putpixel(xt,yt,15);   end;

Egy ciklussal egytől a ténylegesen kiszámított pontok számáig minden egyes pontra elvégezzük a vetítést, majd az így kapott kétdimenziós pontot, pixelként ábrázoljuk. Megfelelő pontszám esetén, szépen kivehető a gömb, láthatjuk az ábrán is. Ehhez hasonlóan érdemes elgondolkodnia az olvasónak, hogy mi lehet annak a hengerfelületnek a vektoregyenlete, amelynek a vezérgörbéje az x2/4+y2/9=1 egyenletű ellipszis, tengelye pedig a z tengely, vagy azon, hogy miképpen lehet egy torusz felületet létrehozni.

Euler-Monge előállítású felületek a gyakorlatban

Mielőtt az elméletet a gyakorlatba vinnénk át, képzeljük el pontosan azt, hogy miről is van szó. Az lesz a legegyszerűbb, ha lelki szemeink előtt elképzelünk egy kisebb dimbes-dombos formát. Ha felülnézetből nézzük rá, akkor a forma két oldala lehet számunkra egy x, és egy y tengely. Bármely tetszőlegesen megválasztott x és y koordinátán (például a forma bal felső sarkától x irányban 10 és y irányban 25 egységnyire) értelmezhetünk egy harmadik értéket, ez lehet a z koordináta. A formát megadhatjuk akár egy kétdimenziós mátrixszal (tömbbel) is - s bármely felületet - megadhatunk úgy is, hogy leírjuk egy függvénnyel. Az ábrán valójában az látható, hogy az adott függvényt, vagy terepasztalt, formát, egy az xy síkkal párhuzamos a z tengelyre pedig merőleges síkkal elvágtuk.

Így görbéket kaptunk, melyeket merőlegesen levetítve, kapjuk meg a felület rétegvonalait. Amelyből a felület alakjára, meredekségére, stb. tudunk következtetni. Ugyanis a rétegvonalak sűrűségéből a felület meredekségére tudunk következtetni, amit térképkészítésnél fel is használnak. A felület egy - egy adott X és Y koordinátájához egy Z érték tartozik (ez a függvényérték). Az eddigi függvényeknél, amiket már ábrázoltunk, mindig csak egy változók paraméterünk volt (a coszinuszfüggvény-ábrázolásnál az x, a Lissajoux-görbénél pedig a t). Most viszont azt mondtuk, hogy az X és az Y is paraméter - ebből következik, hogy meg kell valósítani azt, hogy a felület X és Y tartományán is végigmenjünk (mindkettőhöz tartozhat akár külön tartomány is, pl. az X mehet 0-tól 2*pi-ig, az Y mehet -2-től 3*pi-ig). A felületet szimpla vonallal fogjuk ábrázolni - ennek egy némileg szimpatikusabb megoldása a felület hálós ábrázolása, amelyben a hálót négyzetekkel rajzoljuk ki. Ez utóbbi esetben a négyzetek fillezett négyzetek: ezért van értelme ezt a módszert is kipróbálni (hiszen könnyebben értelmezhető és szebb képet kapunk a felületről).

Ahhoz, hogy ezt meg tudjuk oldani, először vennünk kell pl. a legelső sort a felületből. Ez nyilván az X tartományának "végigfutását" fogja jelenteni, miközben pontokkal (vagy ezeket összekötő szakaszokkal) ábrázoljuk a felület adott sorát. Ha végeztünk vele, vesszük a következő sort, egészen addig, amíg a sor (az Y paraméter) is eléri az ábrázolni kívánt tartomány végét. Ehhez egymásba ágyazott ciklusokat javasolt felhasználni, a következő képen:

  y:=ytol;   While y<yig do begin       x:=xtol;     While x<xig do begin       z:=f(x,y);       Vetit(x,y,z);       If (z<-0.5) Then szin:=green Else       If (z<0.5) Then szin:=lightgreen Else       If (z<1) Then szin:=yellow       Else szin:=red;       Setcolor(szin);       If x=xtol then MoveTo(320+round(scale*kx),240-round(scale*ky));       LineTo(320+round(scale*kx),240-round(scale*ky));       x:=x+nov;     end;     y:=y+nov;   end;   x:=xtol;   While x<xig do begin     y:=ytol;     While y<yig do begin       z:=f(x,y);       Vetit(x,y,z);       If (z<-0.5) Then szin:=green Else       If (z<0.5) Then szin:=lightgreen Else       If (z<1) Then szin:=yellow       Else szin:=red;       Setcolor(szin);       If y=ytol then MoveTo(320+round(scale*kx),240-round(scale*ky));       LineTo(320+round(scale*kx),240-round(scale*ky));       y:=y+nov;     end;     x:=x+nov;   end; end;

Amint látjuk az intervallum "bejárása" a már megszokott módón hajtódik végre. Azért hogy kicsit látványosabbá tegyük a megjelenítést, lehet mélység szerint is színezni, azaz bizonyos z értékek esetében más és más rajzszint fogunk alkalmazni. Az előbb ismertetett módon 3 értékkel fogunk rendelkezni: X, Y és Z koordinátákkal, viszont a képernyőn csak kétféle van, az X és az Y (az egyszerűség kedvéért a képernyőn értelmezett koordinátákat ezentúl KX és KY jelzi majd).Ahhoz, hogy az ismert X,Y és Z koordinátákat leképezhessük a KX és KY koordinátákra, használhatunk többféle leképezést, ábrázolási módot is. Ezekkel már az előző részben részletesebben foglalkoztunk. A vetítés alkalmazása után már a képernyőn megjeleníthető a felület, valamint az eddigi forgató eljárást alkalmazva a térben el is forgatható.

Nos ennek is a végére értünk, remélem érthető volt minden. Ezeket a felületeket valóban nem nehéz ábrázolni, és viszonylag kevés matematikai is elegendő hozzá, ezért érdemes sokat próbálkozni, és kísérletezni. Mellékeltem a források mellé egy egyszerű, de annál hasznosabb programocskát, amivel könnyedén lehet ábrázolni függvényeket, és felületeket, így mindenki megnézheti egy adott függvény grafikus képét. Sok sikert!

A cikkhez kapcsolódó Pascal és Delphi nyelvű példaprogramok és forráskódjuk innen tölthetők le.

Felhasznált és ajánlott irodalom:

Foley, van Dam, Feiner, and Hughes: "Számítógépes grafika: Alapelvek és gyakorlat" c.
Dr. Szirmay-Kalos László: Számítógépes grafika, 2001
Scharnitzky Viktor: Vektorgeometria és lineáris algebra, 1999 (alap!)
L. Ammeraal: Programming Principles in Computer Graphics
Bárczy-Barnabás: Differenciálszámítás, 2001
Turcsányi Tamás, Debreceni Egyetem, 2000
Budai Attila: Számítógépes grafika, 1999
Füzi János: Grafikai Alkalmazások Delphi Nyelven, 2000
Füzi János: Interaktív grafika, 1997