Recorte e seleção de linhas e polígonos Motivações Clipping
mbiguidade na seleção Classes de lgoritmos Pontos Linhas Polígonos Clipping 2
Ponto em retângulo y y p 2.tol y m 2.tol m p int pontinrect(int m, int ym, float p, float yp, float tol return ( (p>=m-tol && (p<=m+tol && ( (yp>=ym-tol && (yp<=ym+tol ; Casos de clipping de linhas E ( 2, y 2 C ( 2, y 2 (, y D (, y Clipping 3
Códigos das regiões 00 000 00 000 0000 000 00 000 00 tbrl typedef typedef struct struct all; all; left; left; right; right; bottom; bottom; top; top; Outcode; Outcode; Cálculo do código de um vértice Outcode compoutcode(double, double y, double min, double ma, double ymin, double yma Outcode code; code.top = 0, code.bottom = 0, code.right = 0, code.left = 0, code.all = 0; if (y > yma code.top = ; code.all += 8; if(y < ymin code.bottom = ; code.all += 4; 00 000 00 if ( > ma 000 0000 000 code.right = ; code.all += 2; if( < min code.left = ; code.all += ; return code; 00 000 00 Clipping 4
lgoritmo de Cohen-Sutherland void CohenSutherlandLineClipndDraw(double 0, double y0, double, double y, double min, double ma, double ymin, double yma, int value outcode outcode0, outcode, outcodeout, CompOutCode(; double, y; boolean accept = FLSE, done = FLSE; outcode0 = CompOutCode(0, y0, min, ma, ymin, yma; outcode = CompOutCode(, y, min, ma, ymin, yma; do if (outcode0.all == 0 && outcode.all == 0 accept = TRUE; done = TRUE; /* trivial draw and eit */ if((outcode0.all & outcode.all!= 0 done = TRUE; /* trivial reject and eit */ if (outcode0.all!= 0 outcodeout = outcode0; outcodeout = outcode; if (outcodeout.top = 0 + ( - 0 * (yma - y0 / (y - y0; y = yma; if(outcodeout.bottom = 0 + ( - 0 * (ymin - y0 / (y - y0; y = ymin; if(outcodeout.right y = y0 + (y - y0 * (ma - 0 / ( - 0; = ma; if(outcodeout.left y = y0 + (y - y0 * (min - 0 / ( - 0; = min; if (outcodeout.all == outcode0.all 0 = ; y0 = y; outcode0 = CompOutCode(0, y0, min, ma, ymin, yma; = ; y = y; outcode = CompOutCode(, y, min, ma, ymin, yma; /* Subdivide */ while (!done; if (accept DrawLineReal(0, y0,, y, value; lgoritimo de Cyrus-eck (Liang-arsky N Ei P(t P 0 P P Ei ( Pt = P + ( P P t 0 0 [ ( Ei ] N P t P = 0 Ei Clipping 5
P 0 P lgoritimo de Cyrus-eck (Liang-arsky N Ei P 0 N [ ( ] P Ei P t PEi = 0 [ ( Ei ] N P t P > 0 Ei P Ei [ ( Ei ] N P t P < 0 Ei ( Pt = P+ ( P P t N 0 0 [ Pt ( P ] = 0 Ei Ei [ P0 PEi ] [ P P0] NEi t= N Ei Entrando ou Saindo? Ei N Ei [ ] N Ei P P0 < 0 PE Ei P P 0 N Ei [ ] N Ei P P0 > 0 PL Clipping 6
Cálculo das interseções P L P L P E C P L P L P L P E P E P L P E P E P E Cyrus-eck - caso geral Calcule Ni e escolha um PEi para cada aresta if(p = = P0 o segmento é degenerado e deve ser recortado como um ponto; te = 0; tl = ; for( cada aresta if (Ni.(P-P0!=0 /* aresta não é paralela ao segmento */ calcule t; use sign of Ni.(P-P0 para categorizar como PE ou PL; if( PE te = ma(te, t; if( PL tl = min(tl, t; /* aresta paralela ao segmento */ if (Ni.(P0-PEi > 0 /* está fora */ return nil; if(te > tl return nil; return P(tE and P(tL as true clip intersections; Clipping 7
y Liang e arsky - caso particular - y ma y min min ma Ei N Ei P Ei t left: = min (-, 0 ( min, y -( 0 - min ( - 0 right: = ma (, 0 ( ma, y bottom: y = y min (0,- (, y min top: y = y ma (0, (, y ma ( 0 - ma -( - 0 -(y 0 -y min (y -y 0 (y 0 -y ma -(y -y 0 Liang e arsky - Cálculo da interseção em uma fronteira - boolean Clipt(double den, double num, double *te, double *tl double t; if (den > 0 /* intersecao PE */ t = num/den; if (t > *tl /* te > tl */ return FLSE; if (t > *te *te = t; if (den < 0 /* intersecao PL */ t=num/den; if (t < *te /* tl < te */ return FLSE; if (t < *tl *tl = t; if (num > 0 /* linha esta fora */ return FLSE; return TRUE; Clipping 8
lgoritimo de Liang e arsky boolean Clip2D(double *0, double *y0, double *, double *y, double min, double ma, double ymin, double yma double d = * - *0; double dy = *y - *y0; boolean visible = FLSE; if (d==0&&(dy==0&&clippoint(*0,*y0,min,ma,ymin,yma visible=true; double te=0.0, tl=.0; if (Clipt(d,min-*0,&tE,&tL if (Clipt(-d,*0-ma,&tE,&tL if (Clipt(dy,ymin-*y0,&tE,&tL if (Clipt(-dy,*y0-yma,&tE,&tL visible=true; if (tl<.0 (*=(*0+tL*d; (*y=(*y0+te*dy; if (te>0.0 (*0=(*0+tE*d; (*y0=(*y0+te*dy; return visible; Clipping de polígonos (Hodgman - Sutherland Clip contra uma aresta (plano de cada vez Clipping 9
Clipping de polígonos (Hodgman & Suterland Para cada aresta (plano teste um segmento de cada vez Eistem quatro casos possiveis para um vértice e seu antessessor interno saindo eterno entrando S P S I P P P I S S guarde P guarde II guarde I, I, P (a (b (c (d Cálculo de interseção pela distância y (, y d n y ma y min d = d = t = 0 0 d0 d d ma ma 0 min d 0 ma ( 0, y 0 = + t ( 0 0 y = y + t ( y y 0 0 Clipping 0
Clipping de polígonos (Eemplo S P ção 2 6 3 5 4 2 2 3 store,3 3 4 store 4 4 5 store 5 5 6 store 6 Clipping de polígonos (Eemplo 2 2 3 6 D C 5 4 S P ção 2 store 2 3 3 4 store,4 4 5 store 5 5 6 store C 6 store D, D C 5 4 Clipping
D 5 Clipping de polígonos (Eemplo 2 C E F 4 S P ção store 4 store E 4 5 store F,5 5 C store C C D store D D store store, E, F, 5, 5, C, D,,, 2 3 6 D C 5 Clipping de polígonos (Concatenação de planos 4 3 4 5 2 6 D C E 5 F 4 D C E D 5 C 4 first[0] S[0] P[0] first[] S[] P[] 5 F,,,, E, F, 5, 5, C, D Clipping 2
PIs para definição de polígonos int int npoints; npoints; double double [MXPOINTS], [MXPOINTS], y[mxpoints]; y[mxpoints]; FillPoly(npoints, FillPoly(npoints,,, y; y; Point Point verte[mxpoint] verte[mxpoint] FillPoly(npoints, FillPoly(npoints, verte verte egin(fill; egin(fill; Verte(30.,20.; Verte(30.,20.; Verte(5.,8.; Verte(5.,8.; End( End( ; ; Distâncias as bordas das janelas y y ma y min min ma double Distance( double, double y, int plane switch( plane case 0: return( - + min ; case : return( - ma ; case 2: return( -y + ymin ; case 3: return( y - yma ; return( 0.0 ; Clipping 3
Teste de interseção com uma fronteira void Intersect(double, double y, int plane, double d, double d2 double t = d / (d - d2; double i = s[plane] + t * ( - s[plane]; double yi = sy[plane] + t * (y - sy[plane]; if( plane == LST_PLNE SaveVerte( i, yi; CliptPlane( i, yi, plane+ ; Clipping de polígonos de Sutherland-Hodgman void CliptPlane( double, double y, int plane double d = Distance(, y, plane; /* Check whether it is the first point */ if( first[plane] f[plane] = ; fy[plane] = y; fd[plane] = d; first[plane] = 0; if ((sd[plane] < 0 ^ (d < 0 Intersect(, y, plane, sd[plane], d ; /* Save as previous */ s[plane] = ; sy[plane] = y; /* Check whether it is a visible point */ if( d <= 0.0 if( plane == LST_PLNE SaveVerte(, y; CliptPlane(, y, plane+ ; Clipping 4
Ligando com a PI void void Verte( Verte( double double,, double double y y if if (clip_on_off (clip_on_off CliptPlane( CliptPlane(,, y, y, 0 0 ; ; SaveVerte(, SaveVerte(, y; y; void void ClipClose( ClipClose( int int plane plane if if ((sd[plane] ((sd[plane] < < 0 0 ^ ^ (fd[plane] (fd[plane] < < 0 0 Intersect( Intersect( f[plane], f[plane], fy[plane], fy[plane], plane, plane, sd[plane], sd[plane], fd[plane] fd[plane] ; ; first[plane] first[plane] = = ; ; if( if( plane plane == == LST_PLNE LST_PLNE FillSavedPolygon(; FillSavedPolygon(; ClipClose( ClipClose( plane+ plane+ ; ; Em coordenadas homogêneas /* ===================== Distance ====================== ** ** This function computes and returns the distance between a ** point and a plane. Normal points toward out. */ double Distance(double, double y, double z, double w, int plane switch( plane case 0: return( -w - ; case : return( -w + ; case 2: return( -w - y ; case 3: return( -w + y ; case 4: return( -w - z ; case 5: return( -w + z ; return( 0.0 ; Clipping 5