390 likes | 589 Views
Obrezovanje črt in poligonov. window. World window & viewport. screen window. world window. viewport. Obrezovanje (c lipping ). Pri 2D grafiki se srečamo s pretvorbo daljic in poligonov v rastersko predstavitev ( 2D scan conversion )
E N D
window World window & viewport screen window world window viewport
Obrezovanje (clipping) • Pri 2D grafiki se srečamo s pretvorbo daljic in poligonov v rastersko predstavitev (2D scan conversion ) • Kaj, če končne točke daljic ali oglišča poligonov ležijo izven vidnega polja naprave? • Potrebujemo obrezovanje! • Delov izven okvirja ne bomo risali • Grafični API to že sami naredijo.
Obrezovanje • Obrezovanje primitivov običajno izvedemo še pred rastersko pretvorbo primitivov • Zakaj? • Rasterska konverzija (scan conversion) bo obdelovala le obrezane dele primitivov, ki so verjetno precej okleščeni v primerjavi z neobrezano različico. • Primitive običajno definiramo v realnem svetu in njihova preslikava v celoštevilčno področje bi lahko povzročala prekoračitev celoštevilčnih vrednosti in s tem nepotrebne in nezaželene učinke.
Algoritem Cohen-Sutherland • Uporaba kode za hitro izločanje črt • Izračun rezanja preostalih črt z oknom gledanja • Uvedba parametričnih enačb črt za ugotavljanje presečišč z robovi okna gledanja? • Cohen-Sutherland v resnici parametričnih enačb ne uporablja • Koda za ugotavljanje presečišč z oknom gledanja: • (x1, y1), (x2, y2) seka vertikalni rob pri xright • yintersect = y1 + m(xright – x1), m=(y2-y1)/(x2-x1) • (x1, y1), (x2, y2) seka horizontalni rob pri ybottom • xintersect = x1 + (ybottom – y1)/m, m=(y2-y1)/(x2-x1)
Cohen-Sutherland: kodiranje področij • Preprosto sprejmemo: oba konca sta FFFF • Preprosto zavrnemo: oba konca imata T na isti poziciji TTFF FTFF FTTF TFFF FFFF FFTF TFFT FFFT FFTT • Pomen bitov: • Levo od okna? • Nad oknom? • Desno od okna? • Pod oknom?
1001 1000 1010 Clipping window 0001 0010 0000 0101 0100 0110 Algoritem Cohen-Sutherland • Računanje kode za točko je preprosto • Uporabljamo le primerjave • Preprosto zavračanje izvedemo z operacijo logičnega andmed kodama dveh točk • Črto zavrnemo, če je katerikoli bit rezultata operacijeandenak 1. Tako učinkovito zavržemo črte, ki so povsem levo, desno spodaj ali zgoraj. Če črte ne moremo trivialno zavreči, jo razdelimo v dva dela. Učinkovito za velika in majhna okna
Preprosto sprejmemo ali zavrnemo • 0000 za obe končni točki= sprejeto • Ujemanje 1 v katerikoli poziciji kode za obe končni točki = zavrnjeno P1 P1 P1 P2 P2 P2 P1 P1 P2 P2 Demo
Cohen-Sutherland: obrezovanje • Če segmenta ne moremo preprosto sprejeti ali zavreči: • zaporedno režemo glede na robove okna
Cohen-Sutherland: obrezovanje(2) Sedaj lahko sprejmemo
y = y0 + slope*(x-x0) x = x0 +(1/ slope)*(y-y0) Računanje končnih točk obrezane daljice P1 P0 • P0: obrezano levo • x = xmin • y = y0 + [(y1-y0)/(x1-x0)] *(xmin-x0) • P1: Obrezano zgoraj • y = ymax • x = x0 + [(x1-x0)/(y1-y0)]*(ymax-y0)
Koda algoritma Cohen-Sutherland clip (int Ax, int Ay, int Bx, int By) { int cA = code(Ax, Ay); int cB = code(Bx, By); while (cA | cB) { if(cA & cB) return; // rejected if(cA) { update Ax, Ay to the clip line depending on which outer region the point is in cA = code(Ax, Ay); } else { update Bx, By to the clip line depending on which outer region the point is in cB = code(Bx, By); } } drawLine(Ax, Ay, Bx, By); }
Obrezovanje črt: Algoritem Cyrus-Beck • Uporabimo parametrično enačbo za črte • Optimiziramo • Kaj pa, če je to drago… • Začnimo s parametrično enačbo za premico: • P(t) = P0 + (P1 - P0) t • Vsakemu robu dodamo točko in normalo • PL, NL
Algoritem Cyrus-Beck (2) točka znotraj polravnine točka na premici, ki vsebuje rob točka izven polravnine
PL P(t) Inside NL Algoritem Cyrus-Beck (3) • NL [P(t) - PL] = 0 • Vstavimo v enačbo za premico P(t) in izračunamo t • t = NL [P0 - PL] / -NL [P1 - P0] P1 P0
Algoritem Cyrus-Beck (4) • Računamo t za presečišča črte z vsemi 4 robovi • Izločimo vsa presečišča, kjer je (t < 0) in(t > 1) • Preostala presečišča klasificiramo kot • Potencialno vstopajoča (potetially entering, PE) • Potencialno izstopajoča (potenitally Leaving PL) • NL [P1 - P0] > 0 pomeni PL • NL [P1 - P0] < 0 pomeniPE • To smo računali, ko smo računali t
P1 PL PL PE PE P0 Algoritem Cyrus-Beck (5) Izračunamo PE z največjim t Izračunamo PL z najmanjšim t Obrežemo med tema dvema točkama
Algoritem Cyrus-Beck (6) • Ker so črte obrezovanja vodoravne ali navpične, se računanje precej poenostavi • Normale: (-1, 0), (1, 0), (0, -1), (0, 1) • Jemljemo konstantne točke na robovih • rešimo za t: • -(x0 - xleft) / (x1 - x0) • (x0 - xright) / -(x1 - x0) • -(y0 - ybottom) / (y1 - y0) • (y0 - ytop) / -(y1 - y0)
Primerjava algoritmov • Cohen-Sutherland • Ponavljajoče obrezovanje je drago • Najboljše, če lahko z večino črt delamo trivialni sprejem ali zavračanje • Cyrus-Beck • Računanje presečišč t je poceni • Račun točk obrezovanja (x,y) clip izvedemo le enkrat • Algoritem ne obravnava trivialnih sprejemov ali zavrnitev • Najboljši, če moramo obrezovati veliko črt • Liang-Barsky: Optimizirani Cyrus-Beck • Nichollin drugi.: hitrejši, vendar ne za 3D
Obrezovanje poligonov • Obrezovanje poligonov je bolj kompleksno od obrezovanja posameznih črt • Vhod: poligon • Izhod: originalni poligon, novi poligon ali nič • Kdaj lahko trivialno sprejmemo ali zavrnemo poligon v primerjavi s segmenti (črtami), ki sestavljajo poligon?
Zakaj je obrezovanje poligonov težavno? Kaj se zgodi s trikotnikom med obrezovanjem? Možni rezultati: trianglequad triangletriangle triangle5-gon Koliko stranic ima lahko obrezani trikotnik?
Res težek primer (2) concave polygonmultiple polygons
Algoritem Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan
Postopek Sutherland-Hodgman • Osnovna ideja: • Vsak rob okna (viewport)obravnavamo posebej • Poligon porežemo v skladu z enačbami robov • Ko to naredimo z vsemi robovi, je poligon polno obrezan Demo
Postopek Sutherland-Hodgman (2) • Vhod/izhod algoritma • Vhod: Urejen seznam verteksov poligona • Izhod: seznam verteksov obrezanega poligona, ki vsebuje (morda) stare vertekse in (morda) nove vertekse • Osnovna rutina: • Gremo okrog poligona in korakamo po verteksih • Tekoči verteks ima pozicijop • Predhodni verteks je imel pozicijosin je bil morda dodan na izhod
inside outside inside outside inside outside inside outside p s p s p s p s p output i output no output i outputp output Postopek Sutherland-Hodgman (3) • Rob zavzame od sdopenega od naslednjih primerov: (violična črta je lahko črta ali ravnina)
Postopek Sutherland-Hodgman (4) • Štirije primeri: • sznotraj ploskve pizven ploskve • pdodamo na izhod • opomba: sje že bil dodan • sznotraj ploskve, pizven ploskve • Poiščemo presečišče i • idodamo na izhod • sizven ploskve,pizven ploskve • Nič ne dodamo • sizven ploskve,pznotraj ploskve • Poiščemo presečiščeI • idodamo na izhod, temu pa še p
Psevdo koda Sutherland Hodgman arrayLength = array.size vertex S = array[ arrayLength - 1 ] for( j = 0, j < arrayLength, j = j+1 ) { vertex P = array[ j ] if( P is inside clip_plane ) { if( S is not inside clip_plane ) { Output( ComputeIntersection( S, P, clip_plane ) ) } Output( P ) } else if( S is inside clip_plane ) { Output( ComputeIntersection( P, S, clip_plane ) ) } S = P }
q n p P Point-to-Plane test • Splošen test ugotavljanja, ali točka pleži “znotraj” ploskve P, definirane s qinn: (p - q) • n < 0: pznotrajP (p - q) • n = 0: pnaP (p - q) • n > 0: pizven P Spomnimo se: p • n = |p| |n| cos (q) q = kot med p in n q q n n p p P P
Iskanje presečišč premice s ploskvijo • Uporabimo definicijo roba: L(t) = L0 + (L1 - L0)t • If t = 0 then L(t) = L0 • If t = 1 then L(t) = L1 • Sicer je L(t) med L0in L1