Σχετικά έγγραφα
(Hirdetmények) A VERSENYPOLITIKA VÉGREHAJTÁSÁRA VONATKOZÓ ELJÁRÁSOK EURÓPAI BIZOTTSÁG

1. Nyelvismereti feladatsor Maximális pontszám: 15

RAC 171. OLAJNYOMÁSÚ SZEGECSELŐ SZERSZÁM Ø 4,8* 7,8** SZEGECSEKHEZ (*kizárólag alumíniumból **csak alumíniumból) HASZNÁLATI UTASÍTÁS - ALKATRÉSZEK

SZÁLLÁS - ΔΙΑΜΟΝΗ. Θέλω ένα δωμάτιο. Egyágyast vagy kétágyast? Μονόκλινο ή δίκλινο; Kétágyast. Δηλαδή για τρεις νύχτες; Igen. Mennyibe kerül?

ÚJGÖRÖG NYELV JAVÍTÁSI-ÉRTÉKELÉSI ÚTMUTATÓ

DH 330. Originál használati utasítás...3 Oryginalna instrukcja obsługi...15 Πρωτότυπο οδηγιών λειτουργίας...28 Izvirna navodila za uporabo...

JAVÍTÁSI-ÉRTÉKELÉSI ÚTMUTATÓ

RENDHAGYÓ IGÉK

bab.la Φράσεις: Προσωπική Αλληλογραφία Ευχές ελληνικά-ουγγρικά

Ταξίδι Τρώγοντας έξω. Τρώγοντας έξω - Στην είσοδο. Τρώγοντας έξω - Παραγγελία φαγητού

1. Nyelvismereti feladatsor Maximális pontszám: 15

SZEGEDI TUDOMÁNYEGYETEM ELMÉLETI FIZIKAI TANSZÉK KÍSÉRLETI FIZIKAI TANSZÉK. TDK dolgozat

21. A 22. D 23. C 24. D 25. D 26. B 27. C 28. B 29. C 30. D

KÖZÉPSZINTŰ ÍRÁSBELI VIZSGA

NYELVI JELENSÉGEK 1. - KEZDŐKNEK

Συνέντευξη με τον Ούγ ρο Πρέσβη στην Αθήνα. Έδρα Νεοελ ών Σπο ών

Για να ρωτήσετε αν κάποιος μπορεί να σας βοηθήσει να γεμίσετε μια φόρμα

Bevándorlás Dokumentumok

DUPLEX Basic EN ISO 9001 :200. Zertificat Nr

Személyes Levél. Levél - Cím. Mr. N. Summerbee 335 Main Street New York NY 92926

Αξιότιμε κύριε Πρόεδρε, Very formal, recipient has a special title that must be used in place of their name

Αιτήσεις Συνοδευτική Επιστολή

Szia! / Jó napot! (attól függően, hogy magázod vagy tegezed az adott személyt)

Η α ιξιάτ κη Βουδαπέστη Τα δεύοντας στην Κεφαλ ιά Παραμυθ όρες Ελ κά μνημεία στο Makó 750 FT 3 ΑΠΡΙΛΙΟΣ 2012

Mr. Adam Smith Smith's Plastics 8 Crossfield Road Selly Oak Birmingham West Midlands B29 1WQ

ln(x)+c 1 ln( x)+c 2 (x>0) (x<0) x dx = x μ dx = xμ+1 μ +1 + C (x R +,μ 1) a x dx = ax sin(x) dx = cos(x)+c (x R) cos(x) dx =sin(x)+c (x R)

(2), ,. 1).

ÁLLAMI TÁMOGATÁS GÖRÖGORSZÁG

Ψυγειοκαταψύκτης Hűtő - fagyasztó Frigider cu congelator

ΕΛΛΗΝΙΚΗ ΕΤΑΙΡΕΙΑ ΕΠΙΣΤΗΜΟΝΩΝ ΚΑΙ ΕΠΑΓΓΕΛΜΑΤΙΩΝ ΠΛΗΡΟΦΟΡΙΚΗΣ ΚΑΙ ΕΠΙΚΟΙΝΩΝΙΩΝ ΜΕΛΟΣ IFIP, IOI Org. GREEK COMPUTER SOCIETY MEMBER OF IFIP, IOI Org.

Εμπορική αλληλογραφία Ηλεκτρονική Αλληλογραφία

Στις 3 Ιουλίου 2006, στην Αίθουσα Τέχνης της

Instrucøiuni de montaj μi exploatare. GasMultiBloc cu regim de funcøionare în douå trepte Tip MB-ZR (DLE) B01 Diametre nominale Rp 1/2 - Rp 1 1/4

EC2800AOW2 EL ΟΡΙΖΌΝΤΙΟΣ ΚΑΤΑΨΎΚΤΗΣ ΟΔΗΓΊΕΣ ΧΡΉΣΗΣ 2 HU FAGYASZTÓLÁDA HASZNÁLATI ÚTMUTATÓ 18

Mosógép Pralka automatyczna Skalbimo mašina Πλυντήριο Ρούχων WMD WMD WMD WMD 77105

(Hirdetmények) A VERSENYPOLITIKA VÉGREHAJTÁSÁRA VONATKOZÓ ELJÁRÁSOK EURÓPAI BIZOTTSÁG

Καλό Πάσχα! Η «ΓΛΩ ΣΑ» στη Βουδαπέστη. Συνέντευξη με τη Γλυκερία. Τα δεύοντας στο Pécs 750 FT 3 ΑΠΡΙΛΙΟΥ 2011

2742/ 207/ / «&»

Καλή Χρονιά! 750 FT 3 ΙΑΝΟΥΑΡΙΟΣ ΕΤΟΣ: 18 ο Εκδοση της Αυτοδιοίκησης Ελλήνων Ουγγαρίας

ιαφάνειες παρουσίασης #9 (α)

Οδηγίες Χρήσης használati útmutató instrukcja obsługi kullanma kılavuzu

Szavak. kénytelen) αρκεί elég, elegendő. terület, romkert. βαριέµαι un, unatkozik, lusta vmihez

Sheet H d-2 3D Pythagoras - Answers

Ταξίδι Γενικά. Γενικά - Τα απαραίτητα. Γενικά - Συνομιλία. Παράκληση για βοήθεια. Ερώτηση σε πρόσωπο αν μιλά αγγλικά

EDH3897SDE EL ΣΤΕΓΝΩΤΉΡΙΟ ΟΔΗΓΊΕΣ ΧΡΉΣΗΣ 2 HU SZÁRÍTÓGÉP HASZNÁLATI ÚTMUTATÓ 29. preciz.hu

πληρώσω προμήθεια; Fragen, ob Gebühren anfallen, wenn man in einem bestimmten Land Geld abhebt

Jelentkezés Ajánlólevél / Referencialevél

KGS 303 Plus. Originál használati utasítás...3 Oryginalna instrukcja obsługi...17 Πρωτότυπο οδηγιών λειτουργίας A0271_30IVZ.

KGS 305. Originál használati utasítás...3 Oryginalna instrukcja obsługi...17 Πρωτότυπο οδηγιών λειτουργίας...32 Izvirna navodila za uporabo...

La piastra. professionale. per capelli lisci o mossi in una. sola passata. The professional straightener for. straight or curly hair.

Προσωπική Αλληλογραφία Ευχές

Προσωπική Αλληλογραφία Ευχές

Εμπορική αλληλογραφία Επιστολή

ΟΚΤΩΒΡΙΟΣ ΕΤΟΣ: 15 ο Εκδοση της Αυτοδιοίκησης Ελλήνων Ουγγαρίας. Bernát / Kaparelis

Személyes Levél. Levél - Cím. Ông Nguyễn Văn A 219 Đội Cấn, Ba Đình Hà Nội, Việt Nam

Γραφικά Υπολογιστών Εισαγωγή

Ολοκλήρωση της θητείας του Έλληνα Πρέσβη. Ελληνόπουλα στο B lat. Οι ελληνικής καταγωγής αθλητές της Πέστης και το Ολυμπιακό Κίνημα

ÁLLAMI TÁMOGATÁS CIPRUS C

ΣΤΗ ΜΝΗΜΗ ΤΩΝ ΜΑΧΗΤΩΝ ΤΟΥ ΔΣΕ. Εκδοση της Αυτοδιοίκησης Ελλήνων Ουγγαρίας. Μάρτιος 2016


Felhasználói és szerelői kézikönyv

08 : 2005/10/28(13:56) Web. Web. Web. Web. Web Visual BASIC. B B Visual BASIC (1) 4. Bezier

ss rt çã r s t Pr r Pós r çã ê t çã st t t ê s 1 t s r s r s r s r q s t r r t çã r str ê t çã r t r r r t r s

Οδηγίες Χρήσης Πλυντήριο ρούχων Használati útmutató Mosógép LAVAMAT 61260TLE

Μπορείτε να με βοηθήσετε; (Borίte na me voithίsete?) Δεν μιλώ _[γλώσσα]_. (Den miló _[glóssa]_.) Δεν καταλαβαίνω. (Den katalabéno.

Tudna segíteni? Szia! / Jó napot! (attól függően, hogy magázod vagy tegezed az adott személyt)

r r t r r t t r t P s r t r P s r s r r rs tr t r r t s ss r P s s t r t t tr r r t t r t r r t t s r t rr t Ü rs t 3 r r r 3 rträ 3 röÿ r t

HC452400EB НҰСҚАУЛАРЫ

HY118- ιακριτά Μαθηµατικά

Οδηγίες χρήσεως. Σύστημα νεφελοποίησης PARI BOY Junior. για τη χρήση σε οικιακό περιβάλλον

HONDA. Έτος κατασκευής

EL Οδηγίες Χρήσης 2 Πλυντήριο πιάτων HU Használati útmutató 25 Mosogatógép FAVORIT W0P

Φέτος συμπληρώνονται 65 χρόνια απ την ίδρυση

2 using namespace s t d ; 4 { 12 int t= x ; 6 x=y ; 7 y=t ; 8 } 9 11 { 13 x= y ; 14 y=t ; 15 } {

ΔΙΑΔΙΚΑΣΙΕΣ ΠΟΥ ΑΦΟΡΟΥΝ ΤΗΝ ΕΦΑΡΜΟΓΗ ΤΗΣ ΠΟΛΙΤΙΚΗΣ ΑΝΤΑΓΩΝΙΣΜΟΥ ΕΠΙΤΡΟΠΗ

P P Ó P. r r t r r r s 1. r r ó t t ó rr r rr r rí st s t s. Pr s t P r s rr. r t r s s s é 3 ñ

ΜΗΝΥΜΑΤΑ ΑΓΑΠΗΣ ΚΑΙ ΕΙΡΗΝΗΣ ΑΠΟ ΤΟΝ ΠΑΤΡΙΑΡΧΗ ΒΑΡΘΟΛΟΜΑΙΟ

BIZOTTSÁG A VERSENYPOLITIKA VÉGREHAJTÁSÁRA VONATKOZÓ ELJÁRÁSOK. (Vélemények)

-! " #!$ %& ' %( #! )! ' 2003

H ανοιξιάτικη βονδατζε6τη. ΤΓαραμυθο κόρες Ελληνικά, μνημεία βτο. T αξιδενοντας 6 την Κ εφ α ΑΠΡΙΛΙΟΣ ιοβ-έζίόκ^ ÍÍOUÁNYA

ELŐSZÓ. Efsztratiadisz Sztratosz

Ax = b. 7x = 21. x = 21 7 = 3.

Active Speaker System

P r s r r t. tr t. r P

Έναρξη σχολικού έτους στο χωριό Μπελογιάννης Ελληνικά μνημεία στο P m n Συνέντευξη με τον Σοφοκλή Νικάκη

KONDENZÁCIÓS FALI GÁZKAZÁN

GETTING STARTED? EASY.

NYELVI JELENSÉGEK 2. - KÖZÉPHALADÓKNAK

Συμβούλιο της Ευρωπαϊκής Ένωσης Βρυξέλλες, 7 Μαρτίου 2017 (OR. en)

Εισαγωγή Αποκοπή ευθείας σε 2Δ Αποκοπή πολυγώνου σε 2Δ Αποκοπή σε 3Δ. 3ο Μάθημα Αποκοπή. Γραφικα. Ευάγγελος Σπύρου

m i N 1 F i = j i F ij + F x

Ε 1 1 Τ Ε Κ Ε Ζ Ε S Ε Κ Λ Ν Υ Ε L Υ- ÉS SZÉP TUDOMÁNYOK KIADJA A MAOYAH TUDOMÁNYOS AKADÉMIA. A Z I. O S Z T Á L Y R E N D E L E T É B Ő L SZERKESZTI

PARASPONDYLOS ZOTIKOS

C 1 D 1. AB = a, AD = b, AA1 = c. a, b, c : (1) AC 1 ; : (1) AB + BC + CC1, AC 1 = BC = AD, CC1 = AA 1, AC 1 = a + b + c. (2) BD 1 = BD + DD 1,

Δομημένος Προγραμματισμός

ΚΕΦΑΛΑΙΟ 2. Περιγραφή της Κίνησης. 2.1 Κίνηση στο Επίπεδο

Személyes Jókívánságok

Προσωπική Αλληλογραφία Επιστολή

GETTING STARTED? EASY.

User Manual GETTING STARTED? EASY. preciz.hu ZWQ 61025CI. EL Οδηγίες Χρήσης 2 Πλυντήριο ρούχων HU Használati útmutató 22 Mosógép

Transcript:

Tornai Róbert Bevezetés a számítógépi grafikába mobidiák könyvtár

Tornai Róbert Bevezetés a számítógépi grafikába

mobidiák könyvtár SOROZATSZERKESZT Fazekas István

Tornai Róbert Bevezetés a számítógépi grafikába Egyetemi jegyzet els kiadás mobidiák könyvtár Debreceni Egyetem Informatikai Intézet

Copyright c Tornai Róbert, 2003 Copyright c elektronikus közlés mobidiák könyvtár, 2003 mobidiák könyvtár Debreceni Egyetem Informatikai Intézet 4010 Debrecen, Pf. 12 http://mobidiak.unideb.hu A m egyéni tanulmányozás céljára szabadon letölthet. Minden egyéb felhasználás csak a szerz el zetes írásbeli engedélyével történhet. A m a A mobidiák önszervez mobil portál (IKTA, OMFB-00373/2003) és a GNU Iterátor, a legújabb generációs portál szoftver (ITEM, 50/2003) projektek keretében készült.

Tartalomjegyzék El szó... 9 I. Alapvet fogalmak, irányelvek... 11 1. Történeti áttekintés... 11 2. Az algoritmus fogalma... 12 3. Bolondbiztosság........ 12 4. Kódolási megfontolások..... 13 5. A homogén koordináták használata... 13 II. Inkrementális algoritmusok... 19 1. Szakasz rajzolása... 19 2. Kör rajzolása............... 21 III. Vágó algoritmusok... 27 1. Cohen-Sutherland algoritmus... 27 2. Alakzatra való lehatárolás.... 30 2.1. Kinn-benn algoritmus konvex sokszögekre.... 30 2.2. Szakasz vágása konvex sokszögre.... 33 2.3. Kinn-benn algoritmus konkáv sokszögekre...... 36 2.4. Szakasz vágása konkáv sokszögre... 39 IV. Harmadrend görbék... 45 1. Hermite-ív....... 46 2. Béziergörbe....... 48 3. B-spline... 49 V. 3D ponttranszformációk... 53 1. Egybevágósági transzformációk... 53 1.1. Eltolás... 53 1.2. Forgatás... 54 1.2.1. Forgatás az x tengely körül... 54 1.2.2. Forgatás az y tengely körül... 55 1.2.3. Forgatás a z tengely körül... 55 1.3. Tükrözés koordinátasíkra.... 56 1.3.1. Tükrözés az [y, z] koordinátasíkra......... 56 1.3.2. Tükrözés az [x, z] koordinátasíkra......... 57 1.3.3. Tükrözés az [x, y] koordinátasíkra.............. 58 2. Hasonlósági transzformációk......... 59 7

8 TARTALOMJEGYZÉK 2.1. Origó középpontú kicsinyítés és nagyítás...... 59 3. Affin transzformációk...... 59 3.1. Skálázás........... 59 3.2. Nyírás............. 60 VI. 3 dimenziós tér leképezése képsíkra és a window to viewport transzformáció... 63 1. Leképezések... 63 1.1. Centrális vetítés... 63 1.2. Párhuzamos vetítés... 64 1.3. Axonometria........ 66 2. A window to viewport transzformáció.... 67 VII. Rekurzív kitöltés... 71 VIII. Testmodellezés... 73 1. A drótvázmodell (wire frame)... 73 2. Felületmodell (a B-rep adatstruktúra)... 73 3. A testmodellek megjelenítése.... 74 3.1. Hátsó lapok eltávolítása... 75 3.2. Fest algoritmus... 75 3.3. Z-buffer algoritmus... 77 Szójegyzet... 83 Ajánlott Irodalom... 85

El szó Mottó: Nem számít semmi, csak az, hogy kérdezz, keresd a választ! (Tankcsapda) Jelen jegyzet összeállításánál igyekeztem az évek során összegy jtött tapasztalatokat beépíteni az egyes fejezetekbe. Mindemellett megpróbáltam a hangsúlyt a gyakorlati alkalmazásra fektetni. A példákat C++-ban készítettem el, a kódolás során pedig a Microsoft Visual C++ 6.0-ás környezetet használtam. A számítógépes kódokat könnyen fel lehet majd ismerni speciális szedésükr l. A kódrészletekben a lebeg pontos számokat a konvekcióknak megfelel en a tizedespont utáni egy darab 0-val jelöltem ket. Például: d = 5.0 / 4.0 - r;. Az algoritmusok hatékony elkészítéséhez szükséges volt néhány segédosztály implementálása. Ilyen például a síkbeli illetve térbeli pontok tárolására és kezelésére szolgáló CPoint2D és CPoint3D osztályok, melyek az alapvet m veleteken (összeadás, kivonás) kívül képesek akár a skaláris vagy a vektoriális szorzatot is el állítani, vagy a CMatrix osztály, mely a zérus illetve egységmátrix létrehozásán kívül pédául a mátrixok szorzását is implementálja. Nagyon hasznos továbbá a szilárd testek modellezésénél a CB_Rep, mely mind a geometriai, mind a topológiai információkat tárolja. Az ablaktechnikák pedig jó hasznát veszik a CWindowBase-nek, mely konvex alakzatok leírását valósítja meg, illetve acconcavewindow-nak, mely az el bbi osztály segítségével konkáv alakzatok leírását teszi lehet vé. A közölt kódrészletekben egy ebuffer felsorolt típusú változó fogja szabályozni, hogy az adott függvény közvetlenül a képerny re (Front) vagy egy háttérképerny re (Back) rajzol. Ezúton mondok köszönetet Dr. Szabó Józsefnek, Dr. Schwarcz Tibornak illetve Tomán Henriettának a lektorálásért és Fazekas Saroltának a szemléletes ábrákért. 9

I. fejezet Alapvet fogalmak, irányelvek Ahogy a technika fejl dik, sok leend programozónak illetve programtervez nek nincs megfelel tapasztalata és tudása a programozott hardverr l. Gondolok itt az egyes utasítások id igényét l kezdve, a grafikus hardverek speciális tulajdonságáig sok mindenre. Sajnos sokan az algoritmus fogalmát sem tudják pontosan. Ebben a fejezetben egy rövid történeti áttekintés után a jegyzetben követett elveket mutatom be, illetve a homogén koordináták fogalmát ismertetem. 1. Történeti áttekintés A számítógépi grafika annak idején nagyszámítógépeken kezd dött. Komolyabb (pl: orvosi, tervezési) feladatokhoz a mai napig célszámítógépeket használnak. Azonban a személyi számítógépek az elmúlt id ben olyan mérték fejl désnek indultak, hogy a valós idej animációk kivitelezése sem lehetetlen rajtuk, vagy akár egy házimozi rendszer lelkéül is szolgálhatnak. A grafikai megoldások fejl dését eleinte a konzol játékgépek és a személyi számítógépes játékok okozták. Napjainkban egyre több tervez i illetve szimulációs probléma oldható meg hatékonyan PC segítségével. A fejl dést a következ felsoroláson keresztül követhetjük nyomon. 80-as évek eleje: a felbontás 320x200 pixel, a használható színek száma 4, melyet 16 alapszínb l lehet kiválasztani. CGA videókártya - CGA monitor páros. Videómemória nagysága kb. 64KB. 80-as évek közepe-vége: megjelentek az EGA videokártyák max. 256KB memóriával. Felbontásuk 640x480 pixel 64 szín használatával. Emellett teret hódítottak a Hercules kártyák a hozzájuk tartozó monokróm monitorokkal, ugyanis a színes monitorok abban az id ben magánemberszámára szinte megfizethetetlenek voltak. A Hercules kártyák nagyobb (758x512) felbontást nyújtanak ugyan, de csak fekete-fehérgrafika mellett. Megjelentek a különféle emulációk az egyes m ködési módok között. 90-es évek eleje: A VGA kártyák 256KB memóriától egészen 4MB kivitelig kaphatóak voltak. A 640x480-as m ködési módot minimum teljesítették, azonban a több memóriával rendelkez darabok akár egészen a 2048x1536- os felbontást is tudták kezelni. Itt jelent meg el szöra 65536 szín (16 bites) üzemmód, majd kés bb a 16.7 millió szín (24 bites) ábrázolás. Látható, hogy a felbontás és a pixelenként tárolt egyre több színinformáció egyre nagyobb memóriát igényel. 11

12 I. ALAPVET FOGALMAK, IRÁNYELVEK 90-es évek vége: megjelentek a 3D gyorsítást végz modellek. Napjainkban memóriájuk 4MB-tól 256MB-ig terjed, azonban akármég ennél is többel rendelkez modellek megjelenése sem lehetetlen a közeljöv ben. Kezdetben csak célfeladatokat gyorsítottak, azonban manapság külön programozható a videokártyák GPU-ja. A személyi számítógépek háttértára, egyéb paraméterei is jelent s fejl désen mentek és mennek keresztül. A legszorosabban talán a CPU fejl dése kapcsolódik a videókártyán kívül a számítógépi grafikához, ugyanis a bonyolultabb grafikák létrehozásához komoly számolókapacitásra van szükség. Eleinte csak fixpontos számolások elvégzésére volt lehet ség. Ekkor az emulált lebeg pontos számolások igencsak komoly teljesítményveszteséggel jártak. Lehet ség volt ugyan coprocesszor használatára, de amellett, hogy költséges volt a beszerzése, sosem lett 100%-osan megbízható egy ilyen rendszer. Ennek köszönhet, hogy az inkrementális algoritmusok jelent s fejl désnek indultak abban az id ben. Kés bb, a 90-es évek közepét l integrálták a lebeg pontos egységet a CPU-val. Ez újabb lendületet adott a grafikus alkalmazásoknak. 2. Az algoritmus fogalma helyes (az algoritmus a kit zött célokat valósítja meg, a célfeltételeknek megfelel végeredményt szolgáltatja az összes lehetséges input esetén) teljes (a problémaosztály összes problémájára megoldást nyújt, ellen rzi az inputot, hogy az értelmezési tartományból való-e) véges (véges sok elemi lépés eredményeképpen minden megoldási úton eredményt szolgáltat, nem kerül végtelen ciklusba) determinisztikus (nem tartalmaz véletlenszer elemet a megoldás során, ugyanarra a bemeneti kombinációra minden egyes futás során ugyanazt az eredményt szolgáltatja) Az algoritmusok megalkotása során lényeges szempont, hogy az adott problémaosztály minden egyes problémájára megoldást nyújtsunk. Ez a gyakorlatban azt jelenti, hogy a megoldást szolgáltató függvény formális paraméterlistáján veszi át az összes változó paramétert. Emellett szükség szerint lokális változókat is definiálhatunk, azonban a függvény környezetét nem változtathatjuk meg. Ez biztosítja majd a létrehozott kód hordozhatóságát. 3. Bolondbiztosság A jegyzetben közölt algoritmusok els lépése az lesz, hogy amennyiben valamelyik paraméter hibás értékkel rendelkezhet (nem az értelmezési tartományból való), kezeli azt, miel tt a hibás érték problémát okozhatna. (Jegyzetemben általában a 0-val való osztás elkerülése a cél, ugyanis a többi matematikai m velet, ha értelmetlen is, de végrehajtható számítógépen. 0-val való osztáskor azonban az egész program futása megszakadhat.) Mindezek tükrében fontos, hogy a bolondbiztosságot mindig szem el tt tartsuk.

I. A HOMOGÉN KOORDINÁTÁK HASZNÁLATA 13 4. Kódolási megfontolások Fontos szempont az is, hogy az algoritmus milyen sebességgel hajtja végre feladatát. A felhasznált m veleteknél azt kell figyelembe venni, hogy a fixpontos m veletek nagyságrendileg gyorsabban hajthatók végre, mint a lebeg pontosak, illetve az összeadás és a kivonás sokkal gyorsabb m velet, mint a szorzás és az osztás. Ezt a legegyszer bben változóink típusának a megválasztásával tudjuk vezérelni. Fixpontos értékek tárolására az int a legtermészetesebb típus, mely a -2 147 483 648... 2 147 483 647 intervallum ábrázolására alkalmas 32 bites mikroprocesszor esetén. Lebeg pontos számok esetében a double típus a leghatékonyabb. Ett l általában csak memóriasz ke miatt térünk el a kisebb pontosságú float felé. Gyors algoritmusok készítésénél mindig figyelembe kell venni, hogy lényeges sebességnövekedést általában csak alapvet en új módszert l várhatunk. Amennyiben megvan a megfelel módszer, el ször egy helyes függvény megalkotása a cél. Akódolás során felmerül problémákat legtöbbszöra Debuggerhasználatával tudjuk a leggyorsabban és legkönyebben megoldani. Amennyiben már rendelkezünk egy jól m köd kóddal, a 80-20 szabályt kell még szem el tt tartanunk. Ez annyit tesz, hogy egy program idejének 80 százalékát a kód 20 százalékában tölti. Ez a 20 százalék a ciklusmagokat jelenti. Bármilyen optimalizáció ebben a 20 százalékban többszörösen térül meg a futás során. A Profiler használatával pontosan meghatározhatjuk, hogy az adott függvény a futási id t az egyes részeknél hány százalékban használta. Ezáltal segít annak a pontos követésében, hogy egy átírással valóban gyorsítottunk-e az algoritmuson, és ha igen, akkor mennyit. 5. A homogén koordináták használata A grafikai algoritmusok elkészítése során a f problémáink a következ k lesznek: meghatározni egy sík két közönséges egyenesének metszéspontját illetve eldönteni azt, hogy egy adott közönséges pont egy adott közönséges egyenes mely oldalán helyezkedik el. A sík kezeléséhez a közönséges térelemek körét végtelen távolinak is mondott ideális térelemekkel b vítjük ki. Ehhez olyan új koordinátákat vezetünk be, melyekkel ezeket az ideális térelemeket is kezelni tudjuk. Az euklideszi sík két egyenese vagy rendelkezik egy közös (metszés)ponttal vagy párhuzamos. A geometriában található számos tételpár, mely tulajdonképpen ugyanazt mondja ki az egyikben metsz, a másikban párhuzamos egyenesekre. Az egyenes pontjainak összességét egy ideális pont nak (végtelen távoli pont) mondott elemmel b vítjük, így oldva fel ezt a kétféleséget. Két egyenes pontjainak az összességét akkor és csak akkor b vítjük ugyanazzal az ideális elemmel, ha a két egyenes párhuzamos. Most már elmondhatjuk, hogy a sík bármely két egyenesének egyetlen közös pontja van, amit metszéspontnak hívunk akkor is, ha az ideális pont.

14 I. ALAPVET FOGALMAK, IRÁNYELVEK A vizsgált S síkban vegyünk fel egy x, y koordináta-rendszert, majd válasszunk egy olyan térbeli derékszög x 1,x 2,x 3 koordináta-rendszert, ahol az x 1, x 2 tengelyek párhuzamosak az x, y tengelyekkel, x 3 tengelyének x 3 =1pontja pedig az x, y koordinátarendszer kezd pontja. Tekintsük az S sík P (P x,p y ) pontját. A térbeli koordináta-rendszer O kezd pontja és a P pont meghatároz egy egyenest. Minden O ponton áthaladó egyenes egyértelm en meghatározza az S sík egy pontját. Az OP egyenest egyértelm en meghatározhatjuk egy O ponttól különböz közönséges P pontjának megadásával. A P pontot így meghatározó P [P x 1,P x 2,P x 3 ] pont koordinátáit a P pont homogén koordinátáinak mondjuk. P pontot megadhatjuk az OP = p [P x 1,P x 2,P x 3 ] vektorral is. A félreértések elkerülése végett a homogén koordinátákat szögletes zárójelbe tesszük P [P x1,p x2,p x3 ]. x 3 P' [P',P',P' ] x x x 1 2 3 S P (P,P ) x y x 1 p' y O x 2 x 1 1. ábra. A P pont homogén koordinátás megadása Tétel: Ha egy pont homogén koordinátáit ugyanazzal a 0-tól különböz számmal szorozzuk meg, akkor ugyanannak a pontnak homogén koordinátáihoz jutunk, s így a pont minden homogén koordinátahármasához eljuthatunk. Tétel: A közönséges P (P x,p y ) pont P [P x1,p x2,p x3 ] homogén koordinátáira P x1 : P x2 : P x3 = P x : P y :1. A közönséges pontok harmadik homogén koordinátája nem 0, és a homogén koordinátákból a közönséges koordinátákat a következ képpen számítjuk: P x = P x 1 P x3 és P y = P x 2 P x3.

I. A HOMOGÉN KOORDINÁTÁK HASZNÁLATA 15 x 3 S B e = axb 1 x b A y a e x 2 x 1 2. ábra. Az e egyenesnek megfelel e vektor Az S sík e egyenesét jellemezhetjük a térbeli koordináta-rendszer O kezd pontján és az e egyenesen átfektetett sík megadásával. Ezt a síkot legegyszer bben pedig az e 0 normálvektorával adhatjuk meg. A következ kben az egyenest meghatározó vektorok esetén ilyen normálvektorokra kell gondolnunk. Egy e egyenes vektorát a legegyszer bben talán úgy számíthatjuk ki, hogy tekintjük az egyenes két pontját (A[A x,a y, 1] és B[B x,b y, 1]), majd ezen pontokba mutató helyvektorok vektoriális szorzataként határozzuk meg azt. e = a b Mivel az a és b vektorok az S sík e egyenesének és a térbeli koordináta-rendszer O kezd pontja által meghatározott síkjában vannak, a vektoriális szorzatuk pontosan mer leges lesz arra. Tétel: A p vektor által meghatározott pont és az e vektor által meghatározott egyenes akkor és csakis akkor illeszkedik egymáshoz, ha p e =0. Ez tulajdonképpen a két vektor mer legességét jelenti. Az e vektorra mer leges p vektorok pedig pont az e egyenes homogén koordinátás pontjaiba mutatnak. Két egyenes metszéspontját a következ képpen határozhatjuk meg: az el z A, B pontok és e egyenes mellett tekintsünk még két pontot, C és D pontokat és a rájuk illeszked f egyenest. e-nek és f-nek a metszéspontja P lesz. Ezután felhasználjuk a skalárszorzat alaptulajdonságait. Mivel P illeszkedik e-re, ezért p e =0. Azonban P illeszkedik f-re is, ezért p f =0, ahol f az OCD sík normálvektora. Az el z két egyenlet azt jelenti, hogy a P -be mutató p vektor mer leges e illetve f vektorokra.

16 I. ALAPVET FOGALMAK, IRÁNYELVEK x 3 p' = exf C e = axb S D x 1 B y A P e f f = cxd x 2 x 1 3. ábra. Két egyenes metszéspontjának meghatározása Ilyen irányú p vektort a legegyszer bben az e és f vektorok vektoriális szorzataként hozhatunk létre: p = e f. Párhuzamos egyenesek metszéspontja esetén a harmadik koordinátában 0-át kapunk eredményül. Ilyenkoraz x 1 és x 2 koordináták megmutatják avégtelen távoli P [p x 1,p x 2, 0] metszéspont irányát. Amennyiben a x 3 koordináta nem 0, akkor a P ( p x 1, p x 2 ) pont közönséges koordinátáit úgy kaphatjuk meg, hogy a megismert módon az egyes koordinátákat elosztjuk p x 3 p x 3 a p x 3 értékkel. Annak eldöntésére, hogy egy S sík közönséges Q pontja a sík egy közönséges g egyenesének melyik oldalán helyezkedik el, a skalárszorzatot tudjuk felhasználni. Amennyiben a q g skalárszorzat pozitív értéket szolgáltat, Q pont az S sík pozitív félsíkjában helyezkedik el g-re nézve; amennyiben negatív, Q pont az S sík negatív félsíkjában helyezkedik el g-re nézve; nulla érték esetén Q pont illeszkedik a g egyenesre. Két vektor skaláris szorzatát a következ képpen számolhatjuk ki: a b = a x1 b x1 + a x2 b x2 + a x3 b x3 A CPoint2D és a CPoint3D osztályok x, y, z, illetve x, y, z, w tagokkal rendelkeznek. double CPoint2D::Scalar(const CPoint2D &a) return (x * a.x + y * a.y + z * a.z);

I. A HOMOGÉN KOORDINÁTÁK HASZNÁLATA 17 Az e = a b vektoriális szorzathoz az alábbi mátrix e x1, e x2, e x3 -hez tartozó adjungált aldeterminánsait kell meghatároznunk: e x 1 e x2 e x3 a x1 a x2 a x3 b x1 b x2 b x3 Így akövetkez eredményt kapjuk e-re: e x1 = a x2 b x3 a x3 b x2 e x2 = a x3 b x1 a x1 b x3 e x3 = a x1 b x2 a x2 b x1 CPoint2D CPoint2D::Vectorial(const CPoint2D &a) return CPoint2D(y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x); Térbeli esetben a síkbelihez hasonlóan járunk el. A különbség annyi, hogy az x 1, x 2 és x 3 koordináták mellé felveszünk egy negyedik x 4 koordinátát. Egy közönséges térbeli P (P x,p y,p z ) pont egy homogénkoordinátás felírása pedig a P [P x,p y,p z, 1] lesz.

II. fejezet Inkrementális algoritmusok Az inkrementális algoritmusok során a végrehajtandó feladatot egy ciklus felépítésével óhajtjuk megoldani, amit a probléma természetét l függ en valamelyik koordináta komponensre építünk fel. A választott komponens (x, ill. y koordináta) minden egyes iterációban növekedni fog eggyel, míg a másik koordináta az algoritmus függvényében n illetve csökken esetenként eggyel. 1. Szakasz rajzolása A problémaosztály ebben az esetben a tetsz leges P és Q végpontú, illetve color szín szakasz rajzolása. Ez azt jelenti, hogy ezeket a paramétereket kell átvennünk a formális paraméterlistán. A bolondbiztosság során pedig a végpontok azonosságát kell vizsgálnunk. Amennyiben a végpontok megegyeznek, nem írnak le szakaszt. A mi feladatunk az, hogy eldöntsük, mi a teend ebben az esetben. A közölt kódban a végpontok által megjelölt pixelt color színnel megjelenítjük a képerny n. A rajzolás során a következ tulajdonságokat fogjuk megkövetelni. A szakasz: a: legyen szimmetrikus. Ez az esztétikai megfontolások mellett azért is jó, mivel f leg régebbi, vonalas rajzra épül programoknál a képerny törlést a megrajzolt szakaszok háttérszínnel való kirakásával helyettesítették. Ebben az esetben, ha nem szimmetrikus a szakasz és az ellenkez irányból rajzoljuk meg, felesleges pixelek maradhatnak a képerny n. (Az akkori technikával ilyen módon nagyságrendileg gyorsabb programokat lehetett írni. Tulajdonképpen a hardverfejl désével a drótvázrajz is veszített jelent ségéb l. Helyét a különböz felületmodellek veszik át manapság.) A szimmetria bitosítása érdekében a szakaszt a végpontjaiból kiindulva fogjuk megrajzolni a közepe felé haladva, ami tulajdonképpen gyorsítani is fogja az algoritmusunkat, mivel minden egyes kiszámolt pixelt kétszer tudunk megrajzolni. b: ne tartalmazzon szakadásokat illetve csomókat. Ez a gyakorlatban azt jelenti, hogy ha pl. a szakaszunk meredeksége kisebb, mint 45 o, akkor a rajzolást az x koordinátára kell felépítenünk. Ebben az esetben el szeretnénk kerülni, hogy a rajzolás során pixelek egymás alá kerüljenek. Mivel az inkrementális algoritmusok alaptulajdonsága miatt minden egyes iterációban egyetlen újabb pixelt gyújtunk ki, ez a kritérium is teljesülni fog. A koordináta komponenst, melyre a ciklust felépítjük, a szakasz meredeksége a- lapján választjuk ki. Ennek az egyik legegyszer bb módszere az, ha megvizsgáljuk a végpontok koordináta komponenseinek különbségének az abszolútértékét (fabs(q.x - p.x) > fabs(q.y - p.y)). 19

20 II. INKREMENTÁLIS ALGORITMUSOK Ezekután a p és q végpontokat kell rendeznünk a kiválasztott koordináta szerint. Így márnem okoz problémát, hogy az egy pixelre jutó változást meghatározzuk, amit az m változóval jelölünk a kódban. A C++ konverziós eljárása miatt a részeredményeket tároló mt1 és mt2 segédváltozókat 0.5-r l indítjuk el. y Q P m x 1. ábra. Szakasz rajzolása a raszteres képerny n A kiválaszott koordinátára felépített ciklusban pedig már csak a szakasz két felének egy-egy pixelét kell kiraknunk. Függvényünk visszatérési értékét felhasználhatjuk annak jelzésére, hogy a végpontok alapján tényleg szakaszt rajzoltunk-e (return 0;) vagy csak egy pixelt tettünk ki (return -1;). int CGraphPrimitives::Line( ebuffer buffer, CPoint2Dint p, CPoint2Dint q, COLORREF color) CDC *dc = (buffer == Front? m_cdc : &m_cbackdc); CPoint2Dint t; double m, mt1 = 0.5, mt2 = 0.5; int limit; if (p == q) dc->setpixel(p.x, p.y, color); return -1; if (abs(q.x - p.x) > abs(q.y - p.y)) if (q.x < p.x) t = p, p = q, q = t;

II. KÖR RAJZOLÁSA 21 m = (double)(q.y - p.y) / (double)(q.x - p.x); limit = (p.x + q.x) >> 1; for (int i = p.x, j = q.x; i <= limit; i++, j--) dc->setpixel(i, p.y + mt1, color); dc->setpixel(j, q.y + mt2, color); mt1 += m; mt2 -= m; else if (q.y < p.y) t = p, p = q, q = t; m = (double)(q.x - p.x) / (double)(q.y - p.y); limit = (p.y + q.y) >> 1; for (int i = p.y, j = q.y; i <= limit; i++, j--) dc->setpixel(p.x + mt1, i, color); dc->setpixel(q.x + mt2, j, color); mt1 += m; mt2 -= m; return 0; 2. Kör rajzolása Kör rajzolásakor a pixelezett képerny miatt négy szimmetriatengelyt tudunk kihasználni az algoritmus írása során. (A függ leges, a vízszintes, illetve a45 o és a 135 o fokos átlós szimmetriatengelyeket.) Ez azt jelenti, hogy elegend mindössze a kör egy nyolcadához tartozó pixeleket kiszámolni és a többi részt tükrözések segítségével tudjuk el állítani. Az algoritmus során az r sugarú, origó középpontú kör É-ÉK-i nyolcadát fogjuk meghatározni az északi (0,r) pontból kiindulva. A kérdés az, hogy az x koordinátát meddig kell futtatni. Kézenfekv nek t nik az x max = sin(45 o ) r = 2 r 2 válasz. Nem túl szerencsés azonban egy egész értéket egy ciklusfejben rendszeresen egy lebeg pontos értékkel összehasonlítani, jobb lenne csak egész számokat alkalmazni. Az y>xvizsgálat az eredeti elgondolással megegyez eredményt fog szolgáltatni. Az (x, y) pont mindig a soron következ pixelt jelöli, így amire az y>xegyenl tlenség hamissá válik, az É-ÉK-i nyolcadot teljes terjedelmében megrajzoltuk. Az origó középpontú kör pozícióba tolásában és a nyolcadok létrehozásában a CirclePoints függvény lesz segítségünkre. A középpont és az aktuális pont koordinátái int típusúak.

22 II. INKREMENTÁLIS ALGORITMUSOK void CGraphPrimitives::CirclePoints( ebuffer buffer, const CPoint2Dint &center, const CPoint2Dint &p, COLORREF color) CDC *dc = (buffer == Front? m_cdc : &m_cbackdc); dc->setpixel(center.x + p.x, center.y + p.y, color); dc->setpixel(center.x + p.x, center.y - p.y, color); dc->setpixel(center.x - p.x, center.y + p.y, color); dc->setpixel(center.x - p.x, center.y - p.y, color); dc->setpixel(center.x + p.y, center.y + p.x, color); dc->setpixel(center.x + p.y, center.y - p.x, color); dc->setpixel(center.x - p.y, center.y + p.x, color); dc->setpixel(center.x - p.y, center.y - p.x, color); y (-x,y) (x,y) (-y,x) (y,x) x (-y,-x) (y,-x) (-x,-y) (x,-y) 2. ábra. A kiválasztott nyolcad tükrözése A körív meghatározásában egy F (x, y) =x 2 + y 2 r 2 függvényt használunk majd, mely az ideális körívt l való távolságot szolgáltatja. Tehát az F (x, y) < 0 azt jelenti, hogy az (x, y) pont a körön belül helyezkedik el, F (x, y) > 0 azt, hogy a körön kívül, illetve 0pontosan akkor lesz, ha az (x, y) pont illeszkedik a körre.

II. KÖR RAJZOLÁSA 23 y P i E M M E SE M SE x>y 45 o x 3. ábra. Az É-ÉK-i nyolcad kiszámítása Tételezzük fel, hogy a körív kiszámítása során eljutottunk egy P i pontba. A következ pixelt két pont μ E(P ix +1,P iy ) [East] és SE(P ix +1,P iy 1) [South-East] μ közül kell kiválasztanunk. Ezt az E és SE közötti M(P ix +1,P iy 1 2 ) felez pont vizsgálatával tehetjük meg. Amennyiben F (M) < 0, tudjuk, hogy a körív az E és az M pontok között halad, ekkor az E ponttal haladunk tovább. Ellenkez esetben a körív az SE és M pontok között (egyenl ség esetén pontosan M-en) halad át, és ebben az esetben SE pontot választjuk. Íly módon meg is határozhatjuk a kiválasztott nyolcad pontjait. Azonban az F (M) meghatározásához legalább két szorzást kell végrehajtanunk a további gyors m veletek mellett, mivel az r r értéket segédváltozóban tárolhatjuk. A továbbfejlesztés ötlete az, hogy meghatározzuk az egymás utáni F (M) értékek különbségét, és ezeket felhasználva kevesebbet kell számolnunk egy új F (M) érték kiszámításához. Jelöljük az F (M) értékét d old -al. d old = F (M) =F (P ix +1,P iy 1 2 )=(P ix +1) 2 +(P iy 1 2 )2 r 2

24 II. INKREMENTÁLIS ALGORITMUSOK Ha d old < 0, akkoraz E pontot választjuk és az új felez ponthoz (M E ) tartozó F (M E ) értéket, melyet d new -al jelölünk, a következ képpen számolhatjuk ki: d new = F (M E )=F (P ix +2,P iy 1 2 )=(P ix +2) 2 +(P iy 1 2 )2 r 2 A változást ( E ) pedig az alábbi átalakítások után kapjuk: E = d new d old =(P ix +2) 2 +(P iy 1 2 )2 r 2 ((P ix +1) 2 +(P iy 1 2 )2 r 2 )=(P ix +2) 2 (P ix +1) 2 = = Pix 2 +4P ix +4 Pix 2 2P ix 1=2P ix +3 Ha d old 0, akkoraz SE pontot választjuk és az új felez ponthoz (M SE ) tartozó F (M SE ) értéket, melyet d new -al jelölünk, a következ képpen számolhatjuk ki: d new = F (M SE )=F (P ix +2,P iy 3 2 )=(P ix +2) 2 +(P iy 3 2 )2 r 2 A változást ( SE ) pedig az alábbi egyenl ség alapján kapjuk: SE = d new d old =(P ix +2) 2 +(P iy 3 2 )2 r 2 ((P ix +1) 2 +(P iy 1 2 )2 r 2 )=P 2 ix +4P ix +4+P 2 iy 3P iy + 9 4 P 2 ix 2P ix 1 P 2 iy + P iy 1 4 =2(P ix P iy )+5 Látható, hogy a szorzások számát mindkét esetben egy m veletre tudtuk csökkenteni, ráadásul fixpontos aritmetika mellett ezek a kett vel való szorzások bitléptetéssel helyettesíthet ek, ami lényegesen gyorsabb. Egy feladatunk maradt viszont, méghozzá a d változó kezd értékének a meghatározása. Mivel az algoritmus a (0,r) pontból indul, az els középpont (1,r 1 )-ben van. Így: 2 d start = F (1,r 1 2 )=12 +(r 1 2 )2 r 2 =1+r 2 r + 1 4 r2 = 5 4 r Amennyiben csak fixpontos változókkal dolgozunk, a d start értékét a d start =1 r-el közelíthetjük. Az így generált görbe nem fog lényegesen eltérni az ideális körívt l. int CGraphPrimitives::Circle( ebuffer buffer, CPoint2Dint center, double r, COLORREF color) CPoint2Dint p(0, r); int d = 5.0 / 4.0 - r; if (r <= 0.0) return -1; CirclePoints(buffer, center, p, color);

while (p.y > p.x) if (d < 0) d += (p.x << 1) + 3; p.x++; else d += ((p.x - p.y) << 1) + 5; p.x++; p.y--; II. KÖR RAJZOLÁSA 25 CirclePoints(buffer, center, p, color); return 0;

III. fejezet Vágó algoritmusok A vágó algoritmusok segítségével megrajzolandó szakaszok egy meghatározott ablakban látható részeit fogjuk meghatározni vágások sorozatán keresztül. Ez az ablak egyszer bb esetben egy téglalap (Cohen-Sutherland algoritmus), bonyolultabb esetben pedig egy konvex vagy egy konkáv alakzat lesz. Akonkáv alakzat lyukakat és szigeteket is tartalmazhat, akártetsz leges mélységben egymásba ágyazva is. A vágó algoritmusok mellett ebben a fejezetben tárgyaljuk a tartalmazást vizsgáló algoritmusokat is. 1. Cohen-Sutherland algoritmus A kezelend síkot kilenc részre osztjuk fel a téglalap alakú képerny nk négy oldalegyenesének segítségével. A kilenc síkrészhez négybites kódokat rendelünk az oldalegyenesek alapján. Az els bit egyes lesz, ha a vizsgált végpont a fels vízszintes oldalegyenes felett helyezkedik el, egyébként 0. A második bit egyes lesz, ha a vizsgált végpont az alsó vízszintes oldalegyenes alatt helyezkedik el, egyébként 0. A harmadik bit egyes lesz, ha a vizsgált végpont a jobb oldali függ leges oldalegyenest l jobbra helyezkedik el, egyébként 0. A negyedik bit egyes lesz, ha a vizsgált végpont a bal oldali függ leges oldalegyenest l balra helyezkedik el, egyébként 0. int CGraphPrimitives::CSCode( const CRect &window, const CPoint2D &p) int code = 0; if (p.x < window.left) code = 1; else if (p.x > window.right) code = 2; if (p.y < window.bottom) code = 4; else if (p.y > window.top) code = 8; return code; 27

28 III. VÁGÓ ALGORITMUSOK 1 1 1 10 10 10 0 0 0 00 00 00 0 0 0 01 01 01 100 100 101 1001 1000 1010 000 000 001 0001 0000 0010 010 010 011 0101 0100 0110 1. ábra. A bitkódok hozzárendelése Az algoritmus során a végpontokhoz el ször is hozzárendeljük a négybites kódokat. A végpontok egyez ségét itt nem vizsgáljuk, ugyanis az algoritmus felépítéséb l fakadóan nullával való osztáshoz nem vezethet, a szakaszrajzoló függvény pedig fel van készítve az ilyen esetekre. Amennyiben a kódokban azonos helyen egyes jelenik meg, azt jelenti, hogy mindkét végpont ugyanazon oldalegyenesnek a küls részén helyezkedik el, tehát nem tartalmaz látható részt. Ebben az esetben az algoritmust befejezhetjük. Ellenkez esetben meg kell néznünk, hogy a végpontok csupa nulla kóddal rendelkeznek-e. Amennyiben igen, a szakasz a végpontjai segítségével megrajzolható és az algoritmus befejezhet. Azonban ha az 1 érték kódok nem egyez pozíciókban vannak, akkor vágásra van szükség. Vágás után a mozgatott végponthoz minden esetben újra meghatározzuk a kódot, ugyanis nem jósolható meg el re, hogy mi fog történni vele. Nem csak 1-es bit t nhet el, hanem például új helyen be is jöhet egy másik. Vágás során a párhuzamos szel k tételét alkalmazhatjuk. Mivel az új koordinátapár egyik tagja ismert, az arányosságból a másik tag kifejezhet ismert mennyiségek segítségével. A vágás után az új kódok segítségével a vizsgálatokat megismételjük. Ily módon vágások sorozatán keresztül meg tudjuk határozni egy szakasz látható részét egy téglalap alakú képerny n, illetve egyértelm en meg tudjuk mondani, ha nem rendelkezik ilyen résszel.

III. COHEN-SUTHERLAND ALGORITMUS 29 2. ábra. A vágások eredménye int CGraphPrimitives::CSLine( ebuffer buffer, const CRect &window, CPoint2D p, CPoint2D q, COLORREF color_in, COLORREF color_out) int c1, c2, t; CPoint2D r, p_old; c1 = CSCode(window, p); c2 = CSCode(window, q); while ((c1 & c2) == 0) if (c1 == c2) Line(buffer, p, q, color_in); return 0; if (c1 == 0) t = c1, c1 = c2, c2 = t; r = p, p = q, q = r;

30 III. VÁGÓ ALGORITMUSOK p_old = p; if (c1 & 1) p.y += (q.y - p.y) * ( window.left - p.x) / (q.x - p.x); p.x = window.left; else if (c1 & 2) p.y += (q.y - p.y) * ( window.right - p.x) / (q.x - p.x); p.x = window.right; else if (c1 & 4) p.x += (q.x - p.x) * (window.bottom - p.y) / (q.y - p.y); p.y = window.bottom; else if (c1 & 8) p.x += (q.x - p.x) * ( window.top - p.y) / (q.y - p.y); p.y = window.top; Line(buffer, p, p_old, color_out); c1 = CSCode(window, p); Line(buffer, p, q, color_out); return -1; 2. Alakzatra való lehatárolás A különböz alakzatokra való lehatárolás során gyakran kell majd egyenesek metszéspontját kezelni, ami az y = m x + b képlet használatával nehézségekhez vezet. Sokkal egyszer bb lesz a dolgunk, ha bevezetjük a homogén koordinátákat. 2.1. Kinn-benn algoritmus konvex sokszögekre Konvex sokszög esetén a vizsgálatot a legegyszer bben úgy végezhetjük el, ha a vizsgált P [P x,p y, 1] ponton keresztül tekintünk egy e egyenest. (Ennek egyik egyszer el állítási módja, ha a P pont x illetve y koordinátáinak segítségével létrehozunk egy Q[P x +1,P y, 1] pontot, majd ennek a pontnak és a P pontnak a vektoriális szorzataként az e egyenest fogjuk kapni. Érdemes az el bb ismertetett módon csak az x vagy csak az y koordinátában eltérést eszközölni, ugyanis így vízszintes illetve függ leges állású e egyeneshez jutunk. Kés bb pontokat kell majd rendeznünk ezen egyenes mentén és ezek a speciális állású egyenesek optimalizálásra adnak majd lehet séget.) Ezek után szükségünk van az egyenes és az alakzat oldalszakaszainak a metszéspontjaira. Akérdés az, hogy az alakzat csúcspontjai az egyenes mely oldalán helyezkednek el. Ugyanis ahol két egymást követ csúcspont az egyenes két oldalán helyezkedik

III. ALAKZATRA VALÓ LEHATÁROLÁS 31 [P x, P y, 1] P Q [P x+ 1, P y, 1] M A = A 0 0 + 4 M 1 e A 1 - - A 3 - A 2 3. ábra. Kinn-benn vizsgálat konvex sokszögre el, ott nem csak a csúcsokra illeszthet oldalegyenesnek, hanem az oldalszakasznak is metszéspontja van az e egyenessel. Ez azt jelenti, hogy vennünk kell a csúcspontok és az e egyenest leíró számhármas skaláris szorzatát. Most vizsgáljuk meg, hogy az értékek el jelében hol van váltás. Amennyiben nem szeretnénk külön esetként kezelni, amikoraz els és az utolsó csúcsponthoz tartozó értéket vizsgáljuk, használhatjuk a régi trükköt, hogy a legels csúcspontot redundánsan felvesszük legutolsóként is. Egy kicsivel több adatot kell ily módon tárolnunk, azonban egyetlen ciklus segítségével tudjuk most már kezelni a problémát. A 0 érték skalárszorzatokat vagy a pozitív, vagy a negatív értékekhez kell sorolnunk. Így ha egy csúcsponton érint leg átmegy az e egyenes, akkor vagy kett vagy egy metszéspontot sem kapunk az algoritmus során. Az el bbiek miatt egyéb esetekben, amennyiben a P pont az alakzatot tartalmazó vízszintes sávban helyezkedik el, mindig kett metszéspontot kapunk, amennyiben ezen a sávon kívül helyezkedik el, akkor pedig egy metszéspontot sem kapunk. Tehát ha nem kaptunk metszéspontokat, máris megállhatunk az algoritmussal és kijelenthetjük, hogy a P pont akonvex alakzaton kívül helyezkedik el.

32 III. VÁGÓ ALGORITMUSOK Abban az esetben, ha két metszéspontot kaptunk eredményül, meg kell vizsgálni, hogy a vizsgált pont a metszéspontok között helyezkedik-e el. (Ez a vízszintes egyenes miatt mindössze az x koordináták vizsgálatát jelenti.) Ha igen, azt mondhatjuk, hogy a P pont az adott konvex alakzaton belül van, amennyiben nem, akkor pedig megállapíthatjuk, hogy azon kívül helyezkedik el. void CGraphPrimitives::ConvexInOut( ebuffer buffer, CWindowBase &window, CPoint2D &p, COLORREF color_in, COLORREF color_out) CDC *dc = (buffer == Front? m_cdc : &m_cbackdc); int i, position[2], *signum, posnum = 0; CPoint2D q, e, f, t, m[2]; signum = new int[window.m_ivertnum + 1]; q = CPoint2D(p.x + 1.0, p.y, 1.0); e = p * q; for (i = 0; i <= window.m_ivertnum; i++) signum[i] = SGN(e.Scalar(window.m_Vertices[i])); for (i = 0; i < window.m_ivertnum; i++) if (signum[i]!= signum[i + 1]) position[posnum++] = i; delete [] signum; if (posnum == 0) dc->setpixel(p.x, p.y, color_out); return; for (i = 0; i < 2; i++) f = window.m_vertices[position[i]] * window.m_vertices[position[i] + 1]; m[i] = e * f; m[i].descartescoords(); if (m[1].x < m[0].x) t = m[0], m[0] = m[1], m[1] = t; if ((m[0].x <= p.x) && (p.x <= m[1].x)) dc->setpixel(p.x, p.y, color_in); else dc->setpixel(p.x, p.y, color_out);

III. ALAKZATRA VALÓ LEHATÁROLÁS 33 2.2. Szakasz vágása konvex sokszögre Amennyiben szakaszokat szeretnénk konvex alakzatra lehatárolni, hasonlóan kell eljárnunk, mint a kinn-benn vizsgálatkor. A különbség annyi, hogy nem nekünk kell el állítani Q-t, hanem a szakasz másik végpontjaként adott lesz. Ezek után a két végpont segítségével meghatározzuk az e egyenest. A 0 = A + 4 e M 1 A 1 + Q P M 0 - A 3 4. ábra. Szakasz vágása konvex sokszögre - A 2 Itt merül fel a bolondbiztosság kérdése: ugyanis ha P megegyezik Q-val, akkornem írnak le egy szakaszt, és a rájuk illesztett e egyenessel is csak problémánk lesz. Ebben az esetben a leghelyesebben akkor járunk el, ha nem csinálunk semmit és azonnal kilépünk az algoritmusból, illetve haaszakaszt ezentúl pontként kezeljük és P pontra meghívjuk a kinn-benn algoritmust. Helyes paraméterek esetén megvizsgáljuk az alakzat csúcspontjainak a skalárszorzatát az e egyenessel, majd meghatározzuk a metszéspontokat, ha vannak. Amennyiben nem találunk metszéspontokat, az azt jelenti, hogy a konvex alakzat teljes egészében a PQ szakaszra illeszked egyenes egyik vagy másik oldalán helyezkedik el. Amennyiben kaptunk metszéspontokat, a kérdés az, hogy mi a viszonyuk a P és Q végpontokhoz képest. A rendezést az e egyenes mentén kell elvégeznünk. Azonban ha ismerjük az e meredekségét, akkor a vizsgálatot valamelyik (x illetve y) koordináta vizsgálatára redukálhatjuk. A meredekség vizsgálatát legegyszer bben talán a P x Q x és P y Q y összehasonlításával tudjuk elvégezni. Ha P x Q x a nagyobb, akkor az x koordiáta

34 III. VÁGÓ ALGORITMUSOK vizsgálata elegend, ellenkez esetben az y koordinátákat kell tekintenünk. Egyenl ség esetén 45 fokos d lésszög e egyenesr l van szó, tehát a pontosság szempontjából irreleváns, hogy melyik koordinátát fogjuk felhasználni. Ha a metszéspontokat illetve P -t és Q-t rendezzük, akkorminössze öt esetet tudunk megkülönböztetni. Q M[0] vagy P M[1]: PQ szakasz az alakzaton kívül helyezkedik el teljes egészében, így nincs látható része. P M[0] és Q M[1]: PQ szakasz teljes egészében az alakzaton belül van, a teljes szakaszt megrajzolhatjuk. P M[0] és Q M[1]: PQszakasz túlnyúlik az alakzaton mindkét irányban, így csak a metszéspontok közötti rész lesz látható. P<M[0] és Q>M[0]: PQ szakasz belelóg az alakzatba, így csak az M[0] és Q közötti rész lesz látható. P < M[1] és Q>M[1]: PQ szakasz belelóg az alakzatba, így csak a P és M[1] közötti rész lesz látható. void CGraphPrimitives::ConvexWLine( ebuffer buffer, CWindowBase &window, CPoint2D &p, CPoint2D &q, COLORREF color_in, COLORREF color_out) int i; int position[2], *signum, posnum = 0; CPoint2D e, f, t, m[2]; if (p == q) return; signum = new int[window.m_ivertnum + 1]; e = p * q; for (i = 0; i <= window.m_ivertnum; i++) signum[i] = SGN(e.Scalar(window.m_Vertices[i])); for (i = 0; i < window.m_ivertnum; i++) if (signum[i]!= signum[i + 1]) f = window.m_vertices[i] * window.m_vertices[i + 1]; m[posnum] = e * f; m[posnum].descartescoords(); posnum++; delete [] signum; if (posnum == 0) Line(buffer, p, q, color_out); return;

III. ALAKZATRA VALÓ LEHATÁROLÁS 35 if (fabs(p.y - q.y) < fabs(p.x - q.x)) if (m[1].x < m[0].x) t = m[0], m[0] = m[1], m[1] = t; if (q.x < p.x) t = p, p = q, q = t; if ((q.x < m[0].x) (m[1].x < p.x)) Line(buffer, p, q, color_out); return; if ((m[0].x <= p.x) && (q.x <= m[1].x)) Line(buffer, p, q, color_in); return; if ((p.x <= m[0].x) && (m[1].x <= q.x)) Line(buffer, m[0], p, color_out); Line(buffer, m[1], q, color_out); Line(buffer, m[0], m[1], color_in); return; if ((p.x <= m[0].x) && (m[0].x <= q.x)) Line(buffer, m[0], p, color_out); Line(buffer, m[0], q, color_in); return; if ((p.x <= m[1].x) && (m[1].x <= q.x)) Line(buffer, m[1], q, color_out); Line(buffer, m[1], p, color_in); return; else if (m[1].y < m[0].y) t = m[0], m[0] = m[1], m[1] = t; if (q.y < p.y) t = p, p = q, q = t; if ((q.y < m[0].y) (m[1].y < p.y))

36 III. VÁGÓ ALGORITMUSOK Line(buffer, p, q, color_out); return; if ((m[0].y <= p.y) && (q.y <= m[1].y)) Line(buffer, p, q, color_in); return; if ((p.y <= m[0].y) && (m[1].y <= q.y)) Line(buffer, m[0], p, color_out); Line(buffer, m[1], q, color_out); Line(buffer, m[0], m[1], color_in); return; if ((p.y <= m[0].y) && (m[0].y <= q.y)) Line(buffer, m[0], p, color_out); Line(buffer, m[0], q, color_in); return; if ((p.y <= m[1].y) && (m[1].y <= q.y)) Line(buffer, m[1], q, color_out); Line(buffer, m[1], p, color_in); return; 2.3. Kinn-benn algoritmus konkáv sokszögekre Atovábbiakban konkáv alakzatnak tekintjük az olyan alakzatokat is, melyek lyukat tartalmaznak, illetve a lyukban szigetet tetsz leges mélységben. Ennél az algoritmusnál sok dolgot fel tudunk használni a konvex eset tapasztalataiból. Az ott alkalmazottakhoz hasonlóan létrehozunk egy vízszintes e egyenest. Ezek után keressük az oldalszakaszokkal való metszéspontjait. Amennyiben egyet sem kapunk, az azt jelenti, hogy a vizsgált P pont az alakzatot tartalmazó legsz kebb vízszintes sávon kívülre esik, így nem lesz látható. Ha kapunk metszéspontokat, azok mindig páros sokan lesznek. (lsd: kinn-benn algoritmus konvex alakzatra) Ezeket a metszéspontokat az x vagy y koordináták alapján rendeznünk kell. Mivel a C++ tartalmaz beépített rendez függvényt, nekünk csupán a két elem összehasonlítását végz kódot kell elkészítenünk. int sortx(const void *a, const void *b)

III. ALAKZATRA VALÓ LEHATÁROLÁS 37 + + + + + + e M0 M1 M 2 M3 M4 M5 M6 M P Q M 7 8 M M M 9 10 11 - - - - - - - - 5. ábra. Kinn-benn algoritmus konkáv sokszögre CPoint2D *p = (CPoint2D *)a, *q = (CPoint2D *)b; if (p->x > q->x) return 1; if (p->x == q->x) return 0; // if (p->x < q->x) return -1; int sorty(const void *a, const void *b) CPoint2D *p = (CPoint2D *)a, *q = (CPoint2D *)b; if (p->y > q->y) return 1; if (p->y == q->y) return 0; // if (p->y < q->y) return -1; A rendezett metszéspontok között megkeressük P helyét. Amennyiben páros sok metszéspont helyezkedik el P mindkét oldalán, azt mondhatjuk, hogy a vizsgált pont a konkáv alakzaton kívül helyezkedik el. Ha mindkét oldalon páratlan sok metszéspont helyezkedik el, akkor pedig az alakzaton belül van a P pont. void CGraphPrimitives::ConcaveInOut( ebuffer buffer, CConcaveWindow &window, CPoint2D &p, COLORREF color_in, COLORREF color_out) CDC *dc = (buffer == Front? m_cdc : &m_cbackdc); int i, j, *signum, posnum = 0; CPoint2D q, e, f, *m;

38 III. VÁGÓ ALGORITMUSOK signum = new int[window.m_ivertnum + 1]; m = new CPoint2D[window.m_iVertNum + 1]; q = CPoint2D(p.x + 1.0, p.y, 1.0); e = p * q; for (j = 0; j < window.m_iwindownum; j++) for (i = 0; i <= window.m_windows[j]->m_ivertnum; i++) signum[i] = SGN(e.Scalar(window.m_Windows[j]->m_Vertices[i])); for (i = 0; i < window.m_windows[j]->m_ivertnum; i++) if (signum[i]!= signum[i + 1]) f = window.m_windows[j]->m_vertices[i] * window.m_windows[j]->m_vertices[i + 1]; m[posnum] = e * f; m[posnum].descartescoords(); posnum++; delete [] signum; if (posnum == 0) dc->setpixel(p.x, p.y, color_out); delete [] m; return; qsort((void *)m, posnum, sizeof(cpoint2d), sortx); if ((p.x < m[0].x) (m[posnum - 1].x < p.x)) dc->setpixel(p.x, p.y, color_out); delete [] m; return; for (i = 0; i < posnum; i += 2) if ((m[i].x <= p.x) && (p.x <= m[i + 1].x)) dc->setpixel(p.x, p.y, color_in); delete [] m; return;

III. ALAKZATRA VALÓ LEHATÁROLÁS 39 dc->setpixel(p.x, p.y, color_out); delete [] m; 2.4. Szakasz vágása konkáv sokszögre A konvex alakzatra való lehatároláshoz hasonlóan P és Q pontokra illesztünk egy e egyenest. (Már amennyiben nem egyezik meg a két végpont.) Ezek után meghatározzuk a metszéspontjait a konkáv alakzat oldalszakaszaival. Ha nincsenek metszéspontok, akkor a szakasznak nincs látható része, egyébként az e egyenes meredekségének függvényében rendezzük a metszéspontokat az x illetve az y koordináta szerint növekv sorrendbe. Emellett rendezzük P és Q pontokat is ugyanezen koordináták szerint. e + M 0 P M 1 - M 2 M 3 + + + + M 4 M - - - 5 M 6 M M 7 8 M 9 Q - - - - - 6. ábra. Szakasz vágása konkáv sokszögre Amennyiben P megfelel koordinátájánál kisebb az összes metszéspont ezen koordinátája vagy Q ezen koordinátájánál mindegyiküké nagyobb, akkor a szakasznak nem lesz látható része a konkáv ablakon. Egyébként meg kell keresnünk a P és a Q pont helyét a metszéspontok között. (A metszéspontokat a C++ szerint 0-tól indexeljük.) Keressük a P helyét az els metszésponttól felfelé illetve a Q helyét az utolsó metszésponttól csökken indexekkel az els felé. A végs rajzolást egy ciklussal lenne célszer elvégezni. Ez esetenként a metszéspontokat tároló tömb módosítását jelentheti majd. Ha a P pont két oldalán rendre páratlan és páros index metszéspont van, akkor a majdani ciklus start indexét a páros értékre állítjuk be, ha a metszéspontok indexei páros-páratlan sorozatot alkotnak, akkorpedig nem csak a start indexet állítjuk be a páros értékre, hanem a hozzá tartozó metszéspont koordinátáit egyenl vé tesszük a P pont koordinátáival. (Erre azért van szükség, mivel a PQ szakasz belelóg egy látható tartományba és csak a P illetve a páratlan index metszéspont közötti részt kell megrajzolnunk.) Hasonlóképpen megkeressük a Q pont helyét a rendezett metszéspontok között, azonban az utolsótól

40 III. VÁGÓ ALGORITMUSOK indulva visszafelé tesszük ezt. Ha páratlan-páros index metszéspontok között van, akkor mindössze az end indexet kell a páratlan értékre állítanunk, ellenkez esetben az end index beállításán túl a páratlan index metszéspont koordinátáit egyenl vé kell tennünk a Q pont koordinátáival. Ezek után mindössze a start indext l az end indexig meg kell rajzolnunk a szakasz látható darabjait. Ez a páros-páratlan index metszéspontok közötti részeket jelenti, tehát a ciklusváltozónkat kettesével kell majd léptetni. Egy probléma lehet csak, ha a start index nagyobb, mint az end index. Ez abban az esetben lehetséges, ha a vizsgált szakasz akonkáv ablak valamelyik közbüls, nem látható területére esik teljes hosszában. Ekkor azonban a for ciklus a végfeltétele miatt egyszer sem fut le, így a láthatóságnak megfelel en nem rajzol semmit. void CGraphPrimitives::ConcaveWLine( ebuffer buffer, CConcaveWindow &window, CPoint2D &p, CPoint2D &q, COLORREF color_in, COLORREF color_out) int i, j, start, end; int *signum, posnum = 0; CPoint2D e, f, t, *m; signum = new int[window.m_ivertnum + 1]; m = new CPoint2D[window.m_iVertNum + 1]; e = p * q; for (j = 0; j < window.m_iwindownum; j++) for (i = 0; i <= window.m_windows[j]->m_ivertnum; i++) signum[i] = SGN(e.Scalar(window.m_Windows[j]->m_Vertices[i])); for (i = 0; i < window.m_windows[j]->m_ivertnum; i++) if (signum[i]!= signum[i + 1]) f = window.m_windows[j]->m_vertices[i] * window.m_windows[j]->m_vertices[i + 1]; m[posnum] = e * f; m[posnum].descartescoords(); posnum++; delete [] signum; if (posnum == 0) Line(buffer, p, q, color_out); delete [] m; return;

start = 0; end = posnum - 1; III. ALAKZATRA VALÓ LEHATÁROLÁS 41 if (fabs(p.y - q.y) < fabs(p.x - q.x)) qsort((void *)m, posnum, sizeof(cpoint2d), sortx); if (q.x < p.x) t = p, p = q, q = t; if ((q.x < m[0].x) (m[posnum - 1].x < p.x)) Line(buffer, p, q, color_out); delete [] m; return; for (i = 0; i <= posnum - 1; i++) if (p.x <= m[i].x) if ((i % 2) == 1) m[i - 1] = p; start = i - 1; break; else Line(buffer, p, m[i], color_out); start = i; break; for (i = posnum - 1; i >= 0; i--) if (m[i].x <= q.x) if ((i % 2) == 0) m[i + 1] = q; end = i + 1; break; else Line(buffer, q, m[i], color_out); end = i; break; else qsort((void *)m, posnum, sizeof(cpoint2d), sorty); if (q.y < p.y) t = p, p = q, q = t;

42 III. VÁGÓ ALGORITMUSOK if ((q.y < m[0].y) (m[posnum - 1].y < p.y)) Line(buffer, p, q, color_out); delete [] m; return; for (i = 0; i <= posnum - 1; i++) if (p.y <= m[i].y) if ((i % 2) == 1) m[i - 1] = p; start = i - 1; break; else Line(buffer, p, m[i], color_out); start = i; break; for (i = posnum - 1; i >= 0; i--) if (m[i].y <= q.y) if ((i % 2) == 0) m[i + 1] = q; end = i + 1; break; else Line(buffer, q, m[i], color_out); end = i; break; if (end < start) Line(buffer, p, q, color_out); delete [] m; return; for (i = start + 1; i < end; i += 2) Line(buffer, m[i], m[i + 1], color_out); for (i = start; i < end; i += 2) Line(buffer, m[i], m[i + 1], color_in);

III. ALAKZATRA VALÓ LEHATÁROLÁS 43 delete [] m;

IV. fejezet Harmadrend görbék A harmadrend görbék általános alakja a következ : r(t) =a t 3 + b t 2 + c t + d t R, ahol a, b, c és d vektorok r(t)-vel megegyez dimenziójú vektorok. A görbét tulajdonképpen ezen vektoroknak t hatványaival vett szorzatának kombinációjaként tudjuk el állítani. A továbbiakban síkbeli görbéket fogunk vizsgálni t [0, 1] tartományon, amihez vezessük be a következ jelöléseket: azaz: r(t) = [ ] [ ] x(t) ax b, C = x c x d x, T = y(t) a y b y c y d y r(t) =C T t 3 t 2 t 1 A következ fejezetekben azt fogjuk megvizsgálni, hogy bizonyos speciális harmadrend görbéket hogyan tudunk létrehozni. Ebben a DrawCurve függvény lesz a segítségünkre, mely 4 4-es mátrixokkal leírt görbék rajzolására képes. A resolution paraméter azt határozza meg, hogy a görbét a rajzolás során hány szakasszal közelítsük. void CGraphPrimitives::DrawCurve(eBuffer buffer, const CMatrix &g, const CMatrix &m, int resolution) CDC *dc = (buffer == Front? m_cdc : &m_cbackdc); int i; CMatrix t(4, 1), c, coords; double u, step = 1.0 / (double)resolution; c = g * m; t[0][0] = 0.0; t[1][0] = 0.0; t[2][0] = 0.0; t[3][0] = 1.0; coords = c * t; dc->moveto(coords[0][0], coords[0][1]); for (u = step; u <= 1.0; u += step) t[0][0] = u * u * u; 45

46 IV. HARMADREND GÖRBÉK t[1][0] = u * u; t[2][0] = u; coords = c * t; dc->lineto(coords[0][0], coords[0][1]); 1. Hermite-ív Adott a görbe két végpontja (P 0, P 1 ) és ezekben a végpontokban adottak az érint k (v 0, v 1 ). H(t) =C T v 0 v 0 v 1 P 0 P1 P 0 P 1 v 1 1. ábra. Hermite görbék Célunk a C mátrix meghatározása. Ehhez felbontjuk C = G H M H szorzatra, ahol G H egy 2 4-es, M H pedig egy 4 4-es mátrix. G H mátrix a görbét meghatározó geometriai adatokat fogja tartalmazni. G H = [ P 0 P 1 v 0 ] v 1 Ekkor: H(0) = P 0 = G H M H [0 0 0 1 ] T H(1) = P 1 = G H M H [1 1 1 1 ] T H (0) = v 0 = G H M H [0 0 1 0 ] T H (1) = v 1 = G H M H [3 2 1 0 ] T

Azaz: Így: IV. HERMITE-ÍV 47 0 1 0 3 [ ] P0 P 1 v 0 v 1 = GH = G H M H 0 1 0 2 0 1 1 1 1 1 0 0 0 1 0 3 M H = 0 1 0 2 0 1 1 1 1 1 0 0 1 2 3 0 1 = 2 3 0 0 1 2 1 0 1 1 0 0 Összegezve az eddigieket: C = G H M H = [ 2 3 0 1 ] P 0 P 1 v 0 v 1 2 3 0 0 1 2 1 0 1 1 0 0 H(t) =C T = [ 2 3 0 1 t 3 ] P 0 P 1 v 0 v 1 2 3 0 0 1 2 1 0 t 2 t 1 1 0 0 1 Vegyük észre, hogy C = G H M H el re letárolható, így az iteráció során mindössze a H(t) =C T szorzatot kell kiszámítanunk a különböz t [0, 1]-ekre. A megfelel M H és G H mátrixot létrehozó, és ennek segítségével Hermite ívet rajzoló C++ függvény kódja: void CGraphPrimitives::HermiteCurve( ebuffer buffer, const CPoint2D &p0, const CPoint2D &p1, const CPoint2D &v0, const CPoint2D &v1, int resolution) CMatrix g(2, 4), m(4, 4); CPoint2D e, f; e = p0 + v0; f = p1 + v1; Line(buffer, p0, e, RGB(255, 0, 0)); Line(buffer, p1, f, RGB(255, 0, 0)); Circle(buffer, e, 2.0, RGB(255, 0, 0)); Circle(buffer, f, 2.0, RGB(255, 0, 0)); Circle(buffer, p0, 2.0, RGB(0, 255, 0)); Circle(buffer, p1, 2.0, RGB(0, 255, 0)); g[0][0] = p0.x; g[0][1] = p1.x; g[0][2] = v0.x; g[0][3] = v1.x; g[1][0] = p0.y; g[1][1] = p1.y; g[1][2] = v0.y; g[1][3] = v1.y; m[0][0] = 2.0; m[0][1] = -3.0; m[0][2] = 0.0; m[0][3] = 1.0;