Osnovni algoritmi rasterske grafike za crtanje 2D primitiva Nela Bosner Reprezentacija pixel-a Scan converting za linije Scan converting za kružnice Obrezivanje (clipping) Osnovni algoritmi rasterske grafike za crtanje 2D primitiva 2. dio kolegija Raˇ cunalna grafika Nela Bosner
56
Embed
Osnovni algoritmi rasterske grafike za crtanje 2D primitivanela/rgpredavanja/osnove_rasterske... · mogucnost crtanja linija debljih od 1 pixel-a, ...
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
DefinicijaScan convering je aproksimacija ili diskretizacijamatematickih primitiva, definiranih pomocu svojih vrhova ukartezijevim koordinatama, skupom pixel-a odredenogintenziteta sive ili neke druge boje.
Scan converting može biti implementiranhardware-skisoftware-ski unutar grafickog paketa
Algoritmi za scan converting se moraju izvršavati brzo. Onikoriste
inkrementalne metode da bi minimizirali broj operacija(narocito * i /)cjelobrojnu aritmetiku (zbog diskretnosti pixel-a)
Mi cemo reprezentirati pixel kaokružna tocka centrirana na pixel-ovim (x , y)koordinatama cjelobrojne mreže.
g g g g gg g g g gg g g g gg g g g g
Kod pravih zaslona razmak izmedu susjednih pixel-a moževarirati:
kod nekih sustava susjedni pixel-i se preklapajukod nekih postoji razmak izmedu pixel-aa kod nekih je razmak izmedu pixel-a uži u vodoravnomsmjeru nego u okomitom.
Scan converting algoritam za linije racuna koordinate pixel-akoji leže na ili blizu idealne, infinitezimalno tanke ravne linijesmještene na 2D rasterskoj mreži.
Razmatramo 1 pixel debelu aproksimaciju linije. Svojstva:niz pixel-a koji leže što je bliže moguce linijii koji je što ravnijiza linije sa koeficijentom smjera k ∈ [−1,1], tocno 1pixel u svakom stupcu treba biti osvjetljenza linije sa koeficijentom smjera k /∈ [−1,1], tocno 1pixel u svakom retku treba biti osvjetljensve linije trebaju biti nacrtane sa konstantnom nijansomsive ili bojom,
neovisno o duljini i orijentacijišto je brže moguce
Dodatna svojstva:mogucnost crtanja linija debljih od 1 pixel-a,razlicitih stilova linije (crtkano, tockasto, . . . )razlicitih oblika krajnjih tocakamogucnost korištenja antialiasing tehnika
Mi cemo razmatrati samo 1 pixel debele linije koje imajutocno jedan monokromatski pixel po stupcu (ili retku).
S obzirom da mi crtamo pixel po pixel, za |k | ≤ 1uzimamo da je ∆ix = 1, pa slijedi
xi+1 = xi + 1,yi+1 = yi + k .
Time smo definirali inkrementalni algoritam.Inicijalizacija: za (x0, y0) uzmu se cjelobrojnekoordinate jedne od krajnjih tocaka.Za |k | > 1 zamijene se uloge od x i y :
yi+1 = yi + 1,xi+1 = xi + 1/k .
Ovaj algoritam se još naziva i digital differentialanalyzer (DDA).
Nedostaci osnovnog inkrementalnog algoritma:zaokruživanje Round(y ) zahtijeva odredeno vrijemeza racunanje k potrebno je dijeljenje
Bresenham je razvio algoritam koji koristi samocjelobrojnu aritmetiku i inkrementalan je.Verzija ovog algoritma u aritmetici pomicnog zarezamože se primijeniti kod linija sa krajnjim tockama urealnim koordinatama.Pretpostavlja se da je koeficijent smjera linije k ∈ [0,1〉.Ostali koeficijenti smjera mogu se obraditi pogodnimzrcaljenjem oko glavnih osi.Donju–lijevu krajnju tocku oznacavamo sa (x0, y0), agornju–desnu sa (x1, y1).
Pixel izabran u prijašnjem koraku oznacen je saP = (xP , yP).U tekucem koraku biramo izmedu dva pixel-a I i SI.Neka je Q tocka sjecišta linije koju obradujemo i linijemreže x = xp + 1.U Bresenhamovoj formulaciji
racuna se razlika okomitih udaljenosti d(I,Q) i d(SI,Q)predznak razlike se koristi za odredivanje pixel-a bližegtocki Q
U formulaciji srednje tockepromatra se na kojoj strani linije leži srednja tocka Mako M leži iznad linije, bira se pixel Iako M leži ispod linije, bira se pixel SI
Linija može prolaziti izmedu I i SI, ili oba pixel-a moguležati na jednoj strani.U oba slucaja test srednje tocke bira najbliži pixel.Greška je uvijek ≤ 1/2.
Algoritam (Algoritam srednje tocke za scan converting linije)void SredtocLinija( /* Pretpostavlja se k ∈ [0, 1〉, x0 < x1 */
int x0, int y0, int x1, int y0, int v){
int dx = x1− x0;int dy = y1− y0;int d = 2 ∗ dy − dx; /* Inicijalna vrijednost od d */int deltaI = 2 ∗ dy; /* Korak za pomicanje do I */int deltaSI = 2 ∗ (dy − dx); /* Korak za pomicanje do SI */int x = x0;int y = y0;NacrtajPixel(x,y,v); /* Pocetni pixel */while(x < x1){
NapomenePoredak krajnjih tocaka: Treba se osigurati da selinija od P0 do P1 aproksimira istim skupom pixel-a kaoi linija od P1 do P0.
Jedino mjesto gdje izbor pixel-a ovisi o smjeru linije jekada linija prolazi kroz srednju tocku i d = 0.→ za k ∈ [0,1〉 u toj situaciji birali smo I.← za k ∈ [0,1〉 moramo birati JZ kako bismo dobili istirezultat.Slicne prilagodbe treba napraviti i za ostale koeficijentesmjera.
Kako zapoceti na rubu pravokutnika za obrezivanje:Algoritam bi trebao prihvatiti linije koje su analitickiobrezane (o tome kasnije).
Kada je linija odrezana kod lijevog ruba x = xminpravokutnika za obrezivanje.
Sjecište linije i ruba ima cjelobrojnu x koordinatu i realnuy koordinatu.Kao pocetni pixel uzimamo (xmin, Round(kxmin + l)) (istipixel kao i kod inkrementalnog algoritma).Test varijabla se inicijalizira sa F (M) na srednjoj tockiizmed I i SI u sljedecem stupcu.Ako se prvo odreže linija kod x = xmin, i onda primijenialgoritam srednje tocke od (xmin, Round(kxmin + l)) do(x1, y1) onda necemo dobiti korektan skup pixel-a —odrezana linija ima drugaciji koeficijent smjera.
Kada je linija odrezana kod donjeg ruba y = yminpravokutnika za obrezivanje.
Za linije sa malim koeficijentom smjera postoji višepixel-a koji leže na pravcu y = ymin.Sve te tocke moraju ostati unutar pravokutnika.Zbog toga se prvo nade sjecište linije i pravcay = ymin − 1
2 , i zaokruži se x vrijednost.Prvi pixel odrezane linije je B = (Round(xymin− 1
2), ymin).
Ako samo nademo sjecište linije i pravca y = ymin, izaokružimo njegovu x koordinatu dobit cemo pixel A ane B.
Treba se izracunati aproksimacija samo za odsjecakkružnice od 45◦.Za kružnice sa središtem u ishodištu, osam simetricnihtocaka mogu se prikazati procedurom TockeKruznice().Slucaj x = y se mora posebno riješiti.
Bresenham je 1977 razvio inkrementalni generatorkružnica koji je efikasan.Podrazumijevamo da je središte kružnice u ishodištu.U obzir uzimamo samo 45◦ od kružice, drugi oktant zax ∈ [0,R/
√2〉 i y ∈ 〈R/
√2,R].
Koristimo proceduru TockeKuznice() za prikazivanjetocaka na cijeloj kružici.Strategija algoritma je odabir 1 od 2 pixel-a, i to onogkoji je bliži kružnici.Odabir se vrši izvrednjavanjem funkcije u srednjoj tockiizmedu ta 2 pixel-a.U drugom oktantu,
ako je pixel P = (xP , yP) bio prethodno izabran kaonajbliži kružniciizbor za sljedeci pixel je izmedu I i JI
Definiramo funkciju F (x , y) = x2 + y2 − R2, i za njuvrijedi:
F (x , y) = 0 na kružniciF (x , y) > 0 izvan kružniceF (x , y) < 0 unutar kružnice
Može se pokazati daako je srednja tocka M izvan kružnice, tada je pixel JIbliži kružniciako je srednja tocka M unutar kružnice, tada je pixel Ibliži kružnici
Ponovo definiramo test varijablu d kao vrijednostfunkcije F (x , y) u srednjoj tocki:
Algoritam cemo ograniciti na cjelobrojne radijuse.Za pocetne uvjete znamo da je prvi pixel na kružici u(0,R).Sljedeca srednja tocka leži u (1,R − 1
2), zato je
F(
1,R − 12
)= 1 +
(R2 − R +
14
)− R2 =
54− R.
Dalje implementiramo algoritam slicno algoritmusrednje tocke za linije.U ovom slucaju smo prinudeni koristiti realnu aritmetikuzbog razlomka u inicijalnoj vrijednosti od d .
Algoritam (Algoritam srednje tocke za scan convertingkružnice)void SredtocKruznica(int r , int v) /* Pretpostavlja se da je središte kružnice u ishodištu */
{int x = 0;int y = r ;double d = 5.0/4.0− r ;TockeKruznice(x,y,v);while (y > x){
Algoritam (Cjelobrojni algoritam srednje tocke za scanconverting kružnice)void SredtocKruznica(int r , int v) /* Pretpostavlja se da je središte kružnice u ishodištu */
/* Samo cjelobrojna aritmetika */
{int x = 0;int y = r ;int d = 1− r ;TockeKruznice(x,y,v);while (y > x){
Ako u tekucemo koraku izaberemo JI:odabrana tocka se pomice sa (xP , yP) na(xP + 1, yP − 1)diferencija prvog reda u (xP , yP) je ∆Istari = 2xP + 3,zato je
u (xP + 1, yP − 1) ∆Inovi = 2(xP + 1) + 3
diferencija drugog reda onda iznosi ∆Inovi −∆Istari = 2diferencija prvog reda u (xP , yP) je∆JIstari = 2xP − 2yP + 5, zato je
Algoritam (Algoritam srednje tocke za scan convertingkružnice sa diferencijama drugog reda)void SredtocKruznica(int r , int v) /* Pretpostavlja se da je središte kružnice u ishodištu */
/* Koriste se diferencije drugog reda za racunanje inkrementa test varijable */{
int x = 0;int y = r ;int d = 1− r ;int deltaI = 3;int deltaJI = −2 ∗ r + 5;TockeKruznice(x,y,v);while (y > x){
if (d < 0) /* Izaberi I */d+ = deltaI;deltaI+ = 2;deltaJI+ = 2;
Korisnik može interaktivno mijenjati položaj i velicinuprozora u kojem se prikazuje grafika.Zbog toga se cesto dogada da se slika u prozoru nemože u potpunosti prikazati, vec se vidi samo jedannjen dio.Zato se vrši obrezivanje (clipping) primitiva kako bi seprikazao samo onaj dio koji stane u prozor, tj. diounutar pravokutnika za obrezivanje.Važno je da se i scan converting i obrezivanje obavljašto je brže moguce.Obrezivanje se može vršiti:
analitickiistovremeno sa scan converting algoritmom
Analiticko obrezivanje:najprije se izracunaju osnovni parametri obrezaneprimitive (kao npr. krajnje tocke linije), a nakon toga seprimijenjuje scan converting algoritam s novimparametrimaefikasno za realni koordinatni sustav — za cjelobrojnugrafiku treba još izvršiti dodatno rastersko obrezivanjejednostavno za obrezivanje linija i poligona — obratitiposebnu pažnju na inicijalizaciju test varijable
Obrezivanje istovremeno sa scan convertingalgoritmom
svaki pixel primitive se podvrgava testu da li se nalaziunutar pravokutnika za obrezivanjeprakticno za popunjene i debele primitive —provjeravaju se samo rubni pixel-iefikasno za slucajeve kada je prikaz primitive malo veciod pravokutnika za obrezivanje
Linije se obrezuju analiticki.Algoritam za obrezivanje linija može se koristiti i zaobrezivanje poligona.Linija koje sijece pravokutnik za obrezivanje se ponovosvodi na jednu liniju:
ako linija leži unutar pravokutnika prikazuje se upotpunostiako sijece barem jedan rub pravokutnika prikazuje seobrezana linijaako linija leži na samoj granici pravokutnika prikazuje seako linija leži izvan pravokutnika ne prikazuje se
Za obrezivanje linije potrebno je provjeriti samo njenekrajnje tocke:
tocka (x , y) leži unutar pravokutnika omedenogkoordinatnim pravcima xmin i xmax , te ymin i ymax ako isamo ako
Vrši se provjera krajnjih tocaka:1 trivijalno prihvacanje — obje krajnje tocke su unutar
pravokutnika za obrezivanje2 trivijalno odbijanje — obje krajnje tocke nalaze se u
vanjskoj poluravnini definiranoj jednim od rubovapravokutnika za obrezivanje
3 ako niti jedan uvjet nije zadovoljen — sjecište linije ipravca definiranog rubom pravokutnika dijeli liniju nadva segmenta, tako da se barem jedan segment možeodbaciti
segment se iterativno obrezuje, provjerom za trivijalnoprihvacanje ili odbijanjeako niti jedan uvjet nije zadovoljen segment se daljedijeli na podsegmenteto se radi tako dugo dok ono što ostane nije upotpunosti unutar pravokutnika, ili se može trivijalnoodbaciti
Za provodenje provjere trivijalnog prihvacanja i odbijanjapromatramo pravce koji su definirani rubovimapravokutnika za obrezivanje — oni dijele ravninu u 9podrucjasvakom podrucju je dodijeljen 4-bitni kodkod je odreden položajem podrucja u odnosu navanjske poluravnine definirane rubovima pravokutnikasvaki bit koda postavljen je na 1 (istina) ili 0 (laž)4 bita u kodu zadovoljavaju sljedece uvjete:
1. bit vanjska poluravnina gornjeg ruba, iznad gornjeg ruba y > ymax
2. bit vanjska poluravnina donjeg ruba, ispod donjeg ruba y < ymin
3. bit vanjska poluravnina desnog ruba, desno od desnog ruba x > xmax
4. bit vanjska poluravnina lijevog ruba, lijevo od lijevog ruba x < xmin
Detalji algoritma:Svakoj krajnjoj tocki linije pridružuje se kod podrucja ukojem leži.Ako su oba koda krajnjih tocaka jednaki nuli, tada linijau potpunosti leži unutar pravokutnika za obrezivanje —linija se trivijalno prihvaca.Ako oba koda imaju postavljenu 1 na istom bitu, tadalinija u potpunosti leži u vanjskoj poluravnini rubaodredenog tim bitom — linija se trivijalno odbija.Ako se linija ne može trivijalno prihvatiti niti odbiti,vršimo podjelu na 2 segmenta:
rub kojeg linija sijece dijeli liniju na dva dijeladio koji leži u vanjskoj poluravnini ruba se odbacujeporedak provjere rubova je proizvoljan — mi cemoprovjeravati
U slucaju da uvjeti prihvacanja i odbijanja nisu zadovoljeni,tada su osnovna svojstva koda pridruženog krajnjoj tocki:
bitovi koji su postavljeni na 1 odgovaraju rubovima kojelinija sijeceako jedna krajnja tocka leži u vanjskoj poluravnininekog ruba, tada druga krajnja tocka mora ležati uunutarnjoj poluravnini tog rubazbog toga linija mora sijeci taj rubalgoritam uvijek bira krajnju tocku koja leži izvanpravokutnika,
iz koda te krajnje tocke odreduje rub kojeg linija sijecetaj rub je prvi u zadanom poretku ciji je bit postavljen na1to je najljeviji bit u kodu postavljen na 1
Sažetak algoritma:1 Izracunamo kodove od oba dvije krajnje tocke.2 Provjerimo uvjete za trivijalno prihvacanje i odbijanje.3 Ako obje provjere nisu zadovoljene, tada tražimo tocku
koja leži izvan pravokutnika.4 Provjeravamo kod vanjske tocke kako bi odredili rub
kojeg linija sijece.5 Nalazimo sjecište linije i tog ruba.6 Odrežimo segment od vanjske tocke do sjecišta, time
što cemo vanjsku krajnju tocku zamijeniti sjecištem.7 Izracunamo kod nove krajnje tocke, kako bismo se
Zbog toga što se provjera i obrezivanje vrši u fiksnomporetku, algoritam ce ponekad izvesti nepotrebnaobrezivanja.Nepotrebna obrezivanja se dogadaju kada se sjecištelinije i pravca odredenog rubom nalazi izvan samogpravokutnika za obrezivanje (tocka H u prethodnomprimjeru).Ovaj algoritam nije najefikasniji, ali je jednostavan inajviše se koristi.Lako ga je proširiti na 3D.
Algoritam (Cohen–Sutherlandov algoritam za obrezivanjelinija)typedef unsigned int kodovi;enum { GORNJI = 0x1, DONJI = 0x2, DESNI = 0x4, LIJEVI = 0x8};
void CohenSutherlandAlg( /* Cohen–Sutherlandov algoritam za obrezivanje linije */double x0, double y0, double x1, double y1, /* od P0 = (x0, y0) do P1 = (x1, y1) i za pravokutnik */double xmin, double xmax, double ymin, /* za obrezivanje sa dijagonalom od (xmin, ymin) do */double ymax, int v) /* (xmax, ymax) */
if (!(kod0 | kod1)){ /* Trivijalno prihvacanje i izlaz */prihvati = TRUE; gotovo = TRUE;
} else if (kod0 & kod1) /* Trivijalno odbijanje i izlaz */gotovo = TRUE;
else { /* Oba dva uvjeta nisu zadovoljena, izracunaj segment */double x,y; /* linije za odrezati: od vanjske tocke do sjecišta s rubom */kodVan = kod0 ? kod0 : kod1; /* Bar jedna krajnja tocka je izvan pravokutnika; odaberi ju *//* Sada nadi sjecište; koristi formule y = y0 + k ∗ (x − x0), x = x0 + (1/k) ∗ (y − y0). */if (kodVan & GORNJI){ /* Razdijeli liniju kod gornjeg ruba pravokutnika /*
Domaca zadacaNapišite program koji ucitava koordinate n tocaka, te xmin,xmax , ymin i ymax koordinate pravokutnika za obrezivanje.Program treba nacrtati poligon zadan tim tockama pomocualgoritma srednje tocke za linije, koji je pravilno obrezanzadanim pravokutnikom za obrezivanje.