Rasterizácia, vypĺňanie a orezávanie v 2D
Rastrový a vektorový obraz Rastrový obraz (nazývaný aj bitová mapa) je reprezentovaný množinou bodov (pixelov), kde je každý bod daný svojou farbou. Takáto reprezentácia je najvhodnejšia pre fotografie a fotorealistické scény. Vektorový obraz je daný súborom jednoduchých geometrických útvarov, ktoré obraz vytvárajú (úsečka, kružnica, krivka, text...). Táto reprezentácia je vhodná pre rôzne typy kresieb.
Rasterizácia Rasterizácia je reprezentácia skutočných objektov pomocou množiny pixelov (rastra). Ide o diskretizáciu útvarov, pri ktorej treba nájsť všetky pixely, ktoré daný geometrický útvar reprezentujú, a priradiť im farbu tohto útvaru.
Rasterizácia úsečky Majme úsečku danú jej koncovými bodmi (x1, y1), (x2, y2) Analytické vyjadrenie takejto úsečky je: Naším cieľom je nájsť a vykresliť množinu pixelov, ktoré zodpovedajú takto danej úsečke.
Rasterizácia úsečky Úsečka je základným stavebným prvkom mnohých geometrických útvarov. Rasterizácia úsečky sa vyskytuje v grafických aplikáciách veľmi často, a preto je dôležité robiť ju čo najefektívnejšie. Ukážeme si rasterizáciu pre prípad, že smernica danej úsečky je: Ďalej predpokladajme, že bod (x1, y1) je naľavo od (x2, y2). Nech x1, y1, x2, y2 sú celočíselné (ak nie sú, zaokrúhlime ich). (x2, y2) (x1, y1)
Rasterizácia úsečky Algoritmus DDA (digital differential analyzer) Je to najjednoduchší algoritmus rasterizácie úsečky Prvý vykreslený pixel bude bod (x1, y1) Keďže smernica je m, tak ak x narastie o 1, y narastie o m. Pretože uvažujeme prípad 0<m<1, prírastok y je vždy menší ako prírastok x. Algoritmus sa dá sformulovať takto: Vypočítaj smernicu m Vykresli bod (x1, y1), x=x1, y=y1 Opakuj kým x<x2: Zvýš x o 1 Zvýš y o m Zaokrúhli y Vykresli bod (x,y)
Rasterizácia úsečky Bresenhamov algoritmus Bresenhamov algoritmus je založený na tom, že pracuje len s celočíselnou aritmetikou a minimalizuje počet aritmetických operácií, preto je veľmi efektívny. Predpokladajme, že už máme vykreslený bod (xi, yi) a chceme vykresliť ďalší bod. Keďže stále predpokladáme 0<m<1, bude prírastok v x vždy 1, ale v y bude menší ako 1. Nasledujúci bod teda bude mať súradnice buď (xi+1,yi) alebo (xi+1,yi+1) Medzi týmito dvomi bodmi sa rozhodneme podľa toho, ktorý je bližšie v skutočnému bodu úsečky (xi+1,y) xi yi xi+1 yi+1 d2 d1 (xi+1,y)
Rasterizácia úsečky Vzdialenosti d1, d2 bodov (xi+1,yi), (xi+1,yi+1) od bodu (xi+1,y) určíme takto: d1=y-yi=m(xi+1)+q-yi d2=yi+1-y=yi+1-m(xi+1)-q Rozdiel týchto vzdialeností: d=d1-d2=2m(xi+1)-2yi+2q-1 Rozhodujúcou veličinou pre výber pixla je znamienko rozdielu d: Ak je d<0, teda d1<d2, vyberieme bod (xi+1,y). Ak je d>0, vyberieme bod (xi+1,yi+1). xi yi xi+1 yi+1 d2 d1 (xi+1,y) Nepotrebujeme teda priamo vedieť hodnotu d, stačí nám, ak budeme poznať jej znamienko. Aby sme zvýšili efektívnosť algoritmu, pokúsime sa zistiť toto znamienko len pomocou celočíselnej aritmetiky.
Rasterizácia úsečky Jediná hodnota, ktorá je vo vzťahu pre d neceločíselná, je smernica úsečky m. Keďže máme m=y/x, môžeme celý vzťah pre d vynásobiť x: pi=dx=2y(xi+1)-2xyi+x(2q-1) Predpokladali sme, že bod (x1,y1) leží naľavo od (x2,y2), preto x>0 a teda znamienko pi je rovnaké ako znamienko d. Napíšme teraz vzťah pre pi+1: pi+1=2y(xi+1+1)-2xyi+1+x(2q-1) Odčítaním vzťahov pre pi a pi+1 dostaneme takéto vyjadrenie pi+1: pi+1=pi+2y-2x(yi+1-yi) Podľa znamienka pi môžeme pi+1 konkrétnejšie napísať takto: Ak pi0 vyberieme bod (xi+1,yi), tak yi=yi+1 a teda: pi+1=pi+2y Ak pi>0 vyberieme bod (xi+1,yi+1), tak yi+1=yi+1 a teda: pi+1=pi+2y-2x Hodnotu p1 dostaneme dosadením x1 a y1=mx1+q do vzťahu pre pi: p1=2y-x Teda pi získame len pripočítaním celočíselných konštánt 2y, resp. 2y-2x k predošlej hodnote a na základe jeho znamienka určíme ďalší pixel.
Rasterizácia úsečky Bresenhamov algoritmus môžeme zapísať takto: Vypočítaj k1=2y a k2=2y-2x p1= 2y-x x=x1, y=y1 Vykresli (x,y) Opakuj kým x<x2 Zvýš x o 1 Ak je pi>0, tak zvýš y o 1 a pi o k2 inak zvýš pi o k1 Vykresli (x,y) Pre úsečky, ktoré nemajú smernicu 0<m<1, funguje algoritmus na rovnakom princípe, ale s malými obmenami. Ak by napr. bolo m>1, zvyšovala by sa o 1 súradnica y a x by sa počítala pomocou uvedených algoritmov. Pri záporných smerniciach by sa jedna zo súradníc znižovala a druhá zvyšovala.
Kresba prerušovanej a hrubej čiary Metódy na kresbu prerušovaných čiar môžu fungovať na dvoch princípoch: 1. Úsečka sa vykresľuje pomocou rasterizačného algoritmu, ale niektoré body sa nevykreslia, čím sa dosiahne prerušenie. 2. Vypočítajú sa začiatočné a koncové body pre všetky úseky a potom sa každý úsek vykresľuje zvlášť. Pri kresbe hrubých čiar sa takisto používajú dva postupy: 1. Namiesto jedného pixla sa vždy vykresľuje viac pixlov, čím čiara získava hrúbku 2. Čiara sa považuje nie za 1D objekt, ale za 2D plochu, t.j. namiesto algoritmu pre úsečky použijeme nejaký vypĺňací algoritmus.
Rasterizácia kružnice 1. Kresba kružnice pomocou úsečiek Pri tomto spôsobe rozdelíme kružnicu na n rovnakých častí a príslušné úseky aproximujeme úsečkami. Potom úsečky vykreslíme pomocou rasterizačného algoritmu. Takýto prístup je nepresný, ale rýchly, preto sa odporúča najmä pri interaktívnom zadávaní kružnice, keď sa jej veľkosť rýchlo mení a presný tvar nie je nutný.
Rasterizácia kružnice 2. Bresenhamov algoritmus na kresbu kružnice V tomto prípade uvažujeme analytické vyjadrenie kružnice: F(x,y):=x2+y2-r2=0 Keďže kružnica je stredovo aj osovo súmerná, stačí nám počítať rasterizáciu v jednom jej oktante. Rasterizácia ostatných oktantov môže byť od nej jednoducho odvodená. (x,y) (y,x) (y,-x) (x,-y) (-x,y) (-y,x) (-y,-x) (-x,-y)
Rasterizácia kružnice V danom oktante platí, že ak x rastie, y klesá. Nárast v x je pritom väčší ako nárast v y, preto x vždy zväčšíme o 1 a pri y sa budeme rozhodovať medzi bodmi yi a yi-1. Rozhodovacím kritériom pre výber ďalšieho pixelu bude hodnota funkcie F(x,y) v bode (xi+1,y), ktorý leží v strede medzi (xi+1,yi) a (xi+1,yi-1). xi xi+1 yi yi-1 y Pre funkciu F(x,y) platí, že na kružnici je F(x,y)=0, vnútri kružnice je F(x,y)<0 a vonku je F(x,y)>0. Vyhodnotíme teda znamienko F v bode (xi+1,y). Platí
Rasterizácia kružnice Odčítaním pi+1 a pi dostaneme (berieme do úvahy, že xi+1=xi+1): Ak je hodnota pi kladná, znamená to, že stredový bod (xi+1,y) leží mimo kružnice a teda bližšie k skutočnému bodu kružnice je bod (xi+1,yi-1). Teda máme yi+1=yi-1 a z toho dostaneme: pi+1=pi+2xi-2yi+5 Ak je hodnota pi záporná, zvolíme bod (xi+1,yi), teda yi+1=yi. Z toho dostávame: pi+1=pi+2xi+3
Rasterizácia kružnice Teraz skúsime navrhnúť algoritmus tak, aby bol čo najefektívnejší: Zbavíme sa konštánt 3, resp. 5 vo vzorcoch pre pi+1. To je možné posunutím kružnice zo stredu (0,0) do stredu (m,n) (nech yi+1=yi-1): Aby sa konštanty -2m+3, 2n+2 vynulovali, musíme mať m=1.5, n=-1. Bod kružnice, ktorým začíname, je jej horný bod, teda bod (0,r). Ak zoberieme do úvahy aj posunutie, dostaneme bod (1.5,r-1). Z toho dostávame: p1=1.25-r Ak chceme počítať s celočíselnými hodnotami, musíme túto hodnotu vynásobiť číslom 4. Zavedieme teda novú premennú Pi=4pi. Potom máme: P1=5-4r Pi+1=Pi+8xi pre Pi0 Pi+1=Pi+8xi-8yi pre Pi<0
Rasterizácia kružnice Bresenhamov algoritmus pre kružnicu môžeme zapísať takto: P1= 5-4r x=0, y=r x8=12, y8=8r-8 //osemnásobky posunutých hodnôt x,y pre výpočet Pi+1 Vykresli (x,y) a všetky s ním súmerné body Opakuj kým xy Zvýš x o 1, zvýš x8 o 8 Ak je Pi>0, tak zníž y o 1, zníž y8 o 8 zvýš Pi o x8-y8 Ak je Pi0, tak zvýš Pi o x8 Vykresli (x,y) a s ním 7 súmerných bodov
Vypĺňanie oblastí Vzhľadom na vypĺňanie rozlišujeme dva typy oblastí: Oblasť s geometricky určenou hranicou – v tomto prípade je hranica oblasti popísaná analyticky. Môže byť buď vo forme mnohouholníka, ktorý je daný svojimi vrcholmi, alebo je tvorená krivkami. Oblasť s hranicou nakreslenou v rastri – v tomto prípade môže mať hranica ľubovoľný tvar. Pre vyplnenie treba poznať farbu hranice alebo farbu vnútorných bodov. A B C D E F G
Vypĺňanie oblastí Vypĺňanie oblasti s geometricky určenou hranicou Ukážeme si jednofarebné vyplnenie oblasti s polygonálnou hranicou Algoritmus vypĺňania je založený na analytickom vyjadrení úsečiek tvoriacich hranicu a dôležité sú priesečníky s týmito úsečkami. Aby sme sa vyhli nejednoznačnostiam, vynecháme vodorovné hrany a každú hranu skrátime zdola o jeden pixel: A B C D E F G H I A B C D E F G H I
Vypĺňanie oblastí Vypĺňanie po riadkoch (scan-line algoritmus) Tento algoritmus vypĺňa útvar po riadkoch, postupne odhora dole. Postup je takýto: 1. Nájdeme maximálnu y-ovú súradnicu, v tomto riadku začneme 2. Nájdeme všetky priesečníky daného riadku s hranami oblasti. 3. Za sebou nasledujúce dvojice priesečníkov spojíme úsečkou danej výplňovej farby (priesečníkov by mal byť vždy párny počet) 4. Prejdeme na ďalší riadok a ideme na bod 2. A B C D E F G H I výplň prvých 4 riadkov
Vypĺňanie oblastí Pri implementácii pracujeme s dvomi tabuľkami – tabuľkou hrán, v ktorej sú uložené všetky hrany oblasti okrem vodorovných, a tabuľkou aktívnych hrán, v ktorej sú uložené hrany, ktoré majú priesečník s aktuálnym riadkom. Hrana je v tabuľke uložená pomocou nasledujúcich informácií: horný bod (xi,yi) a dolná súradnica y yiL obrátená hodnota smernice wi=1/mi Tabuľka hrán by mala byť utriedená primárne zostupne podľa yi, sekundárne vzostupne podľa xi a napokon zostupne podľa wi. Hrany v tabuľke aktívnych hrán by mali byť utriedené vzostupne podľa x-ovej súradnice priesečníka s aktuálnym riadkom. Ak zaraďujeme do tabuľky novú hranu, mali by sme ju zaradiť na správne miesto v poradí. Hrana s počiatočným bodom (xi,yi) a smernicou m má rovnicu: y=mx+yi-mxi Aktuálny riadok so súradnicou ya má s ňou x-ovú súradnicu priesečníka: Nasledujúci riadok so súranicou ya-1 má x-ovú súradnicu priesečníka: čo znamená, že nový priesečník vypočítame len odpočítaním hodnoty w.
Vypĺňanie oblastí Scan-line algoritmus môžeme zapísať takto: Vynechaj vodorovné hrany a ostatné hrany skráť o posledný dolný pixel Ulož hrany do tabuľky hrán a tabuľku hrán usporiadaj Opakuj pre ymaxya>ymin: Do tabuľky aktívnych hrán zaraď hrany, ktoré majú yi=ya Nájdi priesečníky hrán v TAH s aktuálnym riadkom Pospájaj dvojice za sebou nasledujúcich priesečníkov Vyraď z TAH hrany, ktoré majú yiL=ya Vykresli hranicu oblasti
Vypĺňanie oblastí Vypĺňanie oblasti s hranicou nakreslenou v rastri Metódy pre vypĺňanie oblasti s hranicou v rastri sa obecne nazývajú semienkové vypĺňanie (seed fill). Princíp spočíva v tom, že zadáme počiatočný bod (seed), ktorý je vnútorným bodom oblasti a od ktorého sa bude vypĺňanie šíriť do celej oblasti. Z hľadiska typu spojitosti rozlišujeme dva typy oblastí: 4-spojitá oblasť – medzi ľubovoľnými dvomi bodmi existuje v rastri cesta zložená len z vodorovných a zvislých čiar. Stačí keď sa vyplnenie od počiatku šíri len v 4 smeroch. 8-spojitá oblasť – medzi ľubovoľnými dvomi bodmi existuje v rastri cesta zložená z vodorovných, zvislých a diagonálnych čiar. Vyplnenie sa šíri v 8 smeroch.
Vypĺňanie oblastí 8-spojitá hranica ohraničuje 4-spojitú oblasť a na ohraničenie 8-spojitej oblasti potrebujeme 4-spojitú hranicu Bresenhamov algoritmus generuje 8-spojité hranice a oblasť je teda 4-spojitá. Budeme sa teda zaoberať týmto prípadom. Rozlišujeme niekoľko typov vypĺňania: Hraničné vypĺňanie – za vnútorný bod je považovaný bod s inou farbou, ako je farba hranice. Záplavové vypĺňanie – za vnútorný bod sa považuje bod s rovnakou farbou, ako má počiatočný bod vypĺňania. Mäkké vypĺňanie – vnútorný bod musí mať výrazne inú farbu, ako je farba hranice. Tento spôsob sa používa napr. ak sú hranice trochu vytieňované a pod.
Vypĺňanie oblastí Základný algoritmus: Funkcia Vyplň(x,y) Ak je bod (x,y) vnútorný, tak: zafarbi bod (x,y) Vyplň(x-1,y) Vyplň(x+1,y) Vyplň(x,y-1) Vyplň(x,y+1) Načítaj počiatok vypĺňania (xp, yp) Vyplň(xp,yp) Toto je najjednoduchšia varianta vypĺňania, v praxi sa však nepoužíva, lebo jeden bod môže byť v nej testovaný aj mnohokrát a metóda je teda pomalá.
Vypĺňanie oblastí Riadkové semienkové vypĺňanie (scan-line seed fill) Táto metóda je založená na podobnom princípe ako uvedený rekurzívny algoritmus, ale snaží sa vyhnúť viacnásobnému farbeniu jedného bodu. Metóda zafarbí vždy maximálny možný vodorovný úsek v aktuálnom riadku a potom hľadá nové štartovacie body v riadku pod a nad aktuálnym. Štartovacie body sa ukladajú do zásobníka, z ktorého sa postupne vyberajú a spracovávajú sa. A B A C B D A C E F B D A C E A B C B D E B F
Vypĺňanie oblastí Algoritmus zapíšeme takto: Načítaj počiatok vypĺňania a ulož ho do zásobníka Vyfarbi úsek riadku, v ktorom leží počiatočný bod Opakuj, kým zásobník nie je prázdny: Vyber bod zo zásobníka Vyfarbi všetky nevyfarbené úseky v riadku nad daným bodom. Pre každý takýto úsek ulož jeden jeho bod do zásobníka. Vyfarbi všetky nevyfarbené úseky v riadku pod daným bodom. Pre každý takýto úsek ulož jeden jeho bod do zásobníka.
Orezávanie 2D objektov Pomocou orezávania vyberieme z daného obrazu len tú časť, ktorá sa nachádza v určitej oblasti, napr. vo viditeľnej časti okna, vo výbere určenom užívateľom a pod. Orezávacie algoritmy sú zamerané na Test polohy bodu – je to rýchly test, ktorý určí, či bod patrí alebo nepatrí do zadanej oblasti. Používa sa v algoritmoch, ktoré pracujú s jednotlivými bodmi. Orezávanie úsečky – týmto spôsobom sa orezávajú úsečky, lomené čiary a krivky aproximované úsečkami Orezávanie oblasti – tu treba brať do úvahy, že orezaním uzavretej oblasti musí opäť vzniknúť uzavretá oblasť alebo niekoľko uzavretých oblastí. Na okraji okna pritom môžu vzniknúť aj úplne nové hranice.
Test polohy bodu Pri orezávaní obdĺžnikovým oknom je test polohy bodu veľmi jednoduchý. Ak sú súradnice bodu (x,y) a obdĺžnik je vymedzený priamkami x=xmin, x=xmax, y=ymin, y=ymax, tak musí byť splnené: xmin x xmax a zároveň ymin y ymax Pri orezávaní mnohouholníkom môžeme použiť dva postupy: Pri konvexnom mnohouholníku využijeme fakt, že tento mnohouholník je prienikom polrovín. Zistíme teda, či bod patrí všetkým týmto polrovinám. Pri všeobecnom mnohouholníku postupujeme tak, že z daného bodu vyšleme ľubovoľným smerom polpriamku. Ak táto polpriamka pretne mnohouholník nepárny počet krát, bod je vo vnútri, inak je vonku. x=xmin x=xmax y=ymin y=ymax (x,y) (x,y) (x,y)
Orezávanie úsečky Cohen-Sutherlandov algoritmus Budeme sa zaoberať len orezávaním úsečky obdĺžnikom Základom je určenie polohy oboch koncových bodov úsečky voči obdĺžniku. Zaveďme 4-bitový kód pre polohu bodu voči obdĺžniku: prvý bit udáva, či je bod vľavo od obdĺžnika druhý bit udáva, či je bod vpravo tretí bit hovorí, či je bod smerom dole štvrtý bit označuje, či je bod smerom hore 0000 0001 0010 1000 1010 1001 0101 0100 0110
Orezávanie úsečky Pre úsečku AB platia nasledujúce pravidlá (prieniky a zjednotenia sa počítajú vzhľadom na jednotky): Ak Kód(A) Kód(B) = , tak úsečka leží celá vnútri a neoreže sa (u1) Ak Kód(A) Kód(B) , tak celá úsečka leží mimo a nezobrazí sa (u2) Ak Kód(A) Kód(B) = , tak úsečka prechádza viacerými oblasťami a bude sa orezávať (u3, u4) 0000 0001 0010 1000 1010 1001 0101 0100 0110 u1 u2 u3 u4
Orezávanie úsečky Cohen-Sutherlandov algoritmus prebieha takto: 1. Vypočítaj kódy pre krajné body úsečky AB 2. Ak Kód(A) Kód(B) = , vykresli úsečku a skonči 3. Ak Kód(A) Kód(B) = , tak orež úsečku niektorou hranicou, ktorá ju pretína a vypočítaj kód pre nový koncový bod, inak skonči. 4. Vráť sa na krok 2. Hranicu, ktorou máme úsečku orezať, určíme podľa toho, kde sa v kóde nachádza jednotka. Keďže body v obdĺžniku majú kód 0000, musíme postupne znulovať všetky jednotky. Môžeme začať napr. prvou zľava. 0000 0001 0010 1000 1010 1001 0101 0100 0110 1 na 2. mieste= orezanie pravou hranicou, potom 1 na 4. mieste= orezanie hornou hranicou 1 na 1. mieste= orezanie ľavou hranicou
Orezanie mnohouholníka Keďže mnohouholník je uzavretá oblasť, musí zostať uzavretý aj po orezaní. Orezanie jednotlivých úsečiek, ktoré tvoria strany mnohouholníka, by mohlo uzavretosť porušiť, preto potrebujeme iný algoritmus. Budeme sa zaoberať len orezaním mnohouholníka obdĺžnikom a použijeme tzv. Sutherland-Hodgmanov algoritmus.
Orezanie mnohouholníka Ukážeme si orezanie mnohouholníka priamkou, na ktorej leží ľavá strana obdĺžnika. Na orezanie ostatnými stranami môžeme použiť ten istý kód, stačí vždy len otočiť mnohouholník a obdĺžnik o 90° (vždy tým istým smerom). Postup orezávania: Zoberieme úsečku EA. Bod E leží vnútri (x>xmin), bod A leží vonku. Vypočítame priesečník P1 a uložíme ho do množiny vrcholov W, ktoré zostanú po orezaní, t.j. W={P1}. Zoberieme úsečku AB. B leží vonku, do W nepridáme nič. Zoberieme úsečku BC. C leží vnútri. Vypočítame priesečník P2 a uložíme P2 aj C do W, W={P1,P2,C}. Zoberieme úsečku CD. D leží vnútri, takže ho uložíme do W, W={P1,P2,C,D}. Zoberieme úsečku DE. E leží vnútri, pridáme ho do W, W={P1,P2,C,D,E}. Po orezaní nám zostal mnohouholník P1P2CDE. P1 E A B P2 D C x=xmin
Orezanie mnohouholníka Všeobecne môžeme algoritmus pre orezanie zľava zapísať takto: Načítaj množinu V={V1,V2...Vn} vrcholov n-uholníka. Do S ulož posledný vrchol Vn. Opakuj pre 1in: Ak xSxmin, tak: Ak xVixmin, tak pridaj Vi do W Inak vypočítaj priesečník Pi=[xmin, yS+(xmin-xS)(yVi-yS)/(xVi-xS)] a pridaj ho do W Inak Ak xVixmin, tak vypočítaj priesečník Pi=[xmin, yS+(xmin-xS)(yVi-yS)/(xVi-xS)] a pridaj Pi a Vi do W. S=Vi Takto dostaneme množinu vrcholov W orezaného polygónu. Túto množinu potom pošleme na orezanie ďalšími tromi hranicami.